Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * RPC Pipe client / server routines
4 : * Copyright (C) Andrew Tridgell 1992-2000,
5 : * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 : * Copyright (C) Jean François Micouleau 1998-2000,
7 : * Copyright (C) Jeremy Allison 2001-2002,
8 : * Copyright (C) Gerald Carter 2000-2004,
9 : * Copyright (C) Tim Potter 2001-2002.
10 : * Copyright (C) Guenther Deschner 2009-2010.
11 : * Copyright (C) Andreas Schneider 2010.
12 : *
13 : * This program is free software; you can redistribute it and/or modify
14 : * it under the terms of the GNU General Public License as published by
15 : * the Free Software Foundation; either version 3 of the License, or
16 : * (at your option) any later version.
17 : *
18 : * This program is distributed in the hope that it will be useful,
19 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 : * GNU General Public License for more details.
22 : *
23 : * You should have received a copy of the GNU General Public License
24 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 : */
26 :
27 : /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 : up, all the errors returned are DOS errors, not NT status codes. */
29 :
30 : #include "includes.h"
31 : #include "lib/util/util_file.h"
32 : #include "libsmb/namequery.h"
33 : #include "ntdomain.h"
34 : #include "nt_printing.h"
35 : #include "srv_spoolss_util.h"
36 : #include "librpc/gen_ndr/ndr_spoolss.h"
37 : #include "librpc/gen_ndr/ndr_spoolss_scompat.h"
38 : #include "../librpc/gen_ndr/ndr_spoolss_c.h"
39 : #include "rpc_client/init_spoolss.h"
40 : #include "rpc_client/cli_pipe.h"
41 : #include "../libcli/security/security.h"
42 : #include "librpc/gen_ndr/ndr_security.h"
43 : #include "registry.h"
44 : #include "include/printing.h"
45 : #include "secrets.h"
46 : #include "../librpc/gen_ndr/netlogon.h"
47 : #include "rpc_misc.h"
48 : #include "printing/notify.h"
49 : #include "serverid.h"
50 : #include "../libcli/registry/util_reg.h"
51 : #include "smbd/smbd.h"
52 : #include "smbd/globals.h"
53 : #include "auth.h"
54 : #include "messages.h"
55 : #include "rpc_server/spoolss/srv_spoolss_nt.h"
56 : #include "util_tdb.h"
57 : #include "libsmb/libsmb.h"
58 : #include "printing/printer_list.h"
59 : #include "../lib/tsocket/tsocket.h"
60 : #include "rpc_client/cli_winreg_spoolss.h"
61 : #include "../libcli/smb/smbXcli_base.h"
62 : #include "rpc_server/spoolss/srv_spoolss_handle.h"
63 : #include "lib/gencache.h"
64 : #include "rpc_server/rpc_server.h"
65 : #include "librpc/rpc/dcesrv_core.h"
66 : #include "printing/nt_printing_migrate_internal.h"
67 : #include "lib/util/string_wrappers.h"
68 : #include "lib/global_contexts.h"
69 :
70 : /* macros stolen from s4 spoolss server */
71 : #define SPOOLSS_BUFFER_UNION(fn,info,level) \
72 : ((info)?ndr_size_##fn(info, level, 0):0)
73 :
74 : #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
75 : ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
76 :
77 : #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
78 : ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
79 :
80 : #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
81 :
82 : #undef DBGC_CLASS
83 : #define DBGC_CLASS DBGC_RPC_SRV
84 :
85 : #ifndef MAX_OPEN_PRINTER_EXS
86 : #define MAX_OPEN_PRINTER_EXS 50
87 : #endif
88 :
89 : #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
90 : #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
91 : #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
92 : #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
93 :
94 : static struct printer_handle *printers_list;
95 :
96 : struct printer_session_counter {
97 : struct printer_session_counter *next;
98 : struct printer_session_counter *prev;
99 :
100 : int snum;
101 : uint32_t counter;
102 : };
103 :
104 : static struct printer_session_counter *counter_list;
105 :
106 : struct notify_back_channel {
107 : struct notify_back_channel *prev, *next;
108 :
109 : /* associated client */
110 : struct sockaddr_storage client_address;
111 :
112 : /* print notify back-channel pipe handle*/
113 : struct rpc_pipe_client *cli_pipe;
114 : struct cli_state *cli;
115 : uint32_t active_connections;
116 : };
117 :
118 : static struct notify_back_channel *back_channels;
119 :
120 : /* Map generic permissions to printer object specific permissions */
121 :
122 : const struct standard_mapping printer_std_mapping = {
123 : PRINTER_READ,
124 : PRINTER_WRITE,
125 : PRINTER_EXECUTE,
126 : PRINTER_ALL_ACCESS
127 : };
128 :
129 : /* Map generic permissions to print server object specific permissions */
130 :
131 : const struct standard_mapping printserver_std_mapping = {
132 : SERVER_READ,
133 : SERVER_WRITE,
134 : SERVER_EXECUTE,
135 : SERVER_ALL_ACCESS
136 : };
137 :
138 : /* API table for Xcv Monitor functions */
139 :
140 : struct xcv_api_table {
141 : const char *name;
142 : WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
143 : };
144 :
145 : static void prune_printername_cache(void);
146 :
147 : /********************************************************************
148 : * Canonicalize servername.
149 : ********************************************************************/
150 :
151 520 : static const char *canon_servername(const char *servername)
152 : {
153 520 : const char *pservername = servername;
154 :
155 520 : if (servername == NULL) {
156 0 : return "";
157 : }
158 :
159 1568 : while (*pservername == '\\') {
160 1048 : pservername++;
161 : }
162 520 : return pservername;
163 : }
164 :
165 : /* translate between internal status numbers and NT status numbers */
166 386 : static int nt_printj_status(int v)
167 : {
168 386 : switch (v) {
169 386 : case LPQ_QUEUED:
170 386 : return 0;
171 0 : case LPQ_PAUSED:
172 0 : return JOB_STATUS_PAUSED;
173 0 : case LPQ_SPOOLING:
174 0 : return JOB_STATUS_SPOOLING;
175 0 : case LPQ_PRINTING:
176 0 : return JOB_STATUS_PRINTING;
177 0 : case LPQ_ERROR:
178 0 : return JOB_STATUS_ERROR;
179 0 : case LPQ_DELETING:
180 0 : return JOB_STATUS_DELETING;
181 0 : case LPQ_OFFLINE:
182 0 : return JOB_STATUS_OFFLINE;
183 0 : case LPQ_PAPEROUT:
184 0 : return JOB_STATUS_PAPEROUT;
185 0 : case LPQ_PRINTED:
186 0 : return JOB_STATUS_PRINTED;
187 0 : case LPQ_DELETED:
188 0 : return JOB_STATUS_DELETED;
189 0 : case LPQ_BLOCKED:
190 0 : return JOB_STATUS_BLOCKED_DEVQ;
191 0 : case LPQ_USER_INTERVENTION:
192 0 : return JOB_STATUS_USER_INTERVENTION;
193 : }
194 0 : return 0;
195 : }
196 :
197 1636 : static int nt_printq_status(int v)
198 : {
199 1636 : switch (v) {
200 220 : case LPQ_PAUSED:
201 220 : return PRINTER_STATUS_PAUSED;
202 1416 : case LPQ_QUEUED:
203 : case LPQ_SPOOLING:
204 : case LPQ_PRINTING:
205 1416 : return 0;
206 : }
207 0 : return 0;
208 : }
209 :
210 : /***************************************************************************
211 : Disconnect from the client
212 : ****************************************************************************/
213 :
214 2 : static void srv_spoolss_replycloseprinter(int snum,
215 : struct printer_handle *prn_hnd)
216 : {
217 0 : WERROR result;
218 0 : NTSTATUS status;
219 :
220 : /*
221 : * Tell the specific printing tdb we no longer want messages for this printer
222 : * by deregistering our PID.
223 : */
224 :
225 2 : if (!print_notify_deregister_pid(snum)) {
226 0 : DEBUG(0, ("Failed to register our pid for printer %s\n",
227 : lp_const_servicename(snum)));
228 : }
229 :
230 : /* weird if the test succeeds !!! */
231 2 : if (prn_hnd->notify.cli_chan == NULL ||
232 2 : prn_hnd->notify.cli_chan->cli_pipe == NULL ||
233 2 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
234 2 : prn_hnd->notify.cli_chan->active_connections == 0) {
235 0 : DEBUG(0, ("Trying to close unexisting backchannel!\n"));
236 0 : DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
237 0 : TALLOC_FREE(prn_hnd->notify.cli_chan);
238 0 : return;
239 : }
240 :
241 2 : status = dcerpc_spoolss_ReplyClosePrinter(
242 2 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
243 : talloc_tos(),
244 : &prn_hnd->notify.cli_hnd,
245 : &result);
246 2 : if (!NT_STATUS_IS_OK(status)) {
247 0 : DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
248 : nt_errstr(status)));
249 0 : result = ntstatus_to_werror(status);
250 2 : } else if (!W_ERROR_IS_OK(result)) {
251 0 : DEBUG(0, ("reply_close_printer failed [%s].\n",
252 : win_errstr(result)));
253 : }
254 :
255 : /* if it's the last connection, deconnect the IPC$ share */
256 2 : if (prn_hnd->notify.cli_chan->active_connections == 1) {
257 :
258 2 : cli_shutdown(prn_hnd->notify.cli_chan->cli);
259 2 : DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
260 2 : TALLOC_FREE(prn_hnd->notify.cli_chan);
261 :
262 2 : if (prn_hnd->notify.msg_ctx != NULL) {
263 2 : messaging_deregister(prn_hnd->notify.msg_ctx,
264 : MSG_PRINTER_NOTIFY2, NULL);
265 : }
266 : }
267 :
268 2 : if (prn_hnd->notify.cli_chan) {
269 0 : prn_hnd->notify.cli_chan->active_connections--;
270 0 : prn_hnd->notify.cli_chan = NULL;
271 : }
272 : }
273 :
274 : /****************************************************************************
275 : Functions to free a printer entry datastruct.
276 : ****************************************************************************/
277 :
278 972 : static int printer_entry_destructor(struct printer_handle *Printer)
279 : {
280 972 : if (Printer->notify.cli_chan != NULL &&
281 2 : Printer->notify.cli_chan->active_connections > 0) {
282 2 : int snum = -1;
283 :
284 2 : switch(Printer->printer_type) {
285 2 : case SPLHND_SERVER:
286 2 : srv_spoolss_replycloseprinter(snum, Printer);
287 2 : break;
288 :
289 0 : case SPLHND_PRINTER:
290 0 : snum = print_queue_snum(Printer->sharename);
291 0 : if (snum != -1) {
292 0 : srv_spoolss_replycloseprinter(snum, Printer);
293 : }
294 0 : break;
295 0 : default:
296 0 : break;
297 : }
298 : }
299 :
300 972 : Printer->notify.flags=0;
301 972 : Printer->notify.options=0;
302 972 : Printer->notify.localmachine[0]='\0';
303 972 : Printer->notify.printerlocal=0;
304 972 : TALLOC_FREE(Printer->notify.option);
305 972 : TALLOC_FREE(Printer->devmode);
306 :
307 : /* Remove from the internal list. */
308 972 : DLIST_REMOVE(printers_list, Printer);
309 972 : return 0;
310 : }
311 :
312 : /****************************************************************************
313 : find printer index by handle
314 : ****************************************************************************/
315 :
316 52175 : static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
317 : struct policy_handle *hnd)
318 : {
319 52175 : struct printer_handle *find_printer = NULL;
320 0 : NTSTATUS status;
321 :
322 52175 : find_printer = find_policy_by_hnd(p,
323 : hnd,
324 : DCESRV_HANDLE_ANY,
325 : struct printer_handle,
326 0 : &status);
327 52175 : if (!NT_STATUS_IS_OK(status)) {
328 0 : DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: %s\n",
329 : nt_errstr(status)));
330 0 : return NULL;
331 : }
332 :
333 52175 : return find_printer;
334 : }
335 :
336 : /****************************************************************************
337 : Close printer index by handle.
338 : ****************************************************************************/
339 :
340 956 : static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
341 : {
342 956 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
343 :
344 956 : if (!Printer) {
345 0 : DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
346 : OUR_HANDLE(hnd)));
347 0 : return false;
348 : }
349 :
350 956 : close_policy_hnd(p, hnd);
351 :
352 956 : return true;
353 : }
354 :
355 : /****************************************************************************
356 : Delete a printer given a handle.
357 : ****************************************************************************/
358 :
359 16 : static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
360 : const char *sharename,
361 : struct messaging_context *msg_ctx)
362 : {
363 0 : const struct loadparm_substitution *lp_sub =
364 16 : loadparm_s3_global_substitution();
365 16 : char *cmd = lp_deleteprinter_command(talloc_tos(), lp_sub);
366 16 : char *command = NULL;
367 0 : int ret;
368 16 : bool is_print_op = false;
369 :
370 : /* can't fail if we don't try */
371 :
372 16 : if ( !*cmd )
373 0 : return WERR_OK;
374 :
375 16 : command = talloc_asprintf(ctx,
376 : "%s \"%s\"",
377 : cmd, sharename);
378 16 : if (!command) {
379 0 : return WERR_NOT_ENOUGH_MEMORY;
380 : }
381 16 : if ( token )
382 16 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
383 :
384 16 : DEBUG(10,("Running [%s]\n", command));
385 :
386 : /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
387 :
388 16 : if ( is_print_op )
389 0 : become_root();
390 :
391 16 : ret = smbrun(command, NULL, NULL);
392 16 : if (ret == 0) {
393 : /* Tell everyone we updated smb.conf. */
394 16 : messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
395 : }
396 :
397 16 : if ( is_print_op )
398 0 : unbecome_root();
399 :
400 : /********** END SePrintOperatorPrivlege BLOCK **********/
401 :
402 16 : DEBUGADD(10,("returned [%d]\n", ret));
403 :
404 16 : TALLOC_FREE(command);
405 :
406 16 : if (ret != 0)
407 0 : return WERR_INVALID_HANDLE; /* What to return here? */
408 :
409 16 : return WERR_OK;
410 : }
411 :
412 : /****************************************************************************
413 : Delete a printer given a handle.
414 : ****************************************************************************/
415 :
416 16 : static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
417 : {
418 16 : struct dcesrv_call_state *dce_call = p->dce_call;
419 0 : struct auth_session_info *session_info =
420 16 : dcesrv_call_session_info(dce_call);
421 16 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
422 0 : WERROR result;
423 :
424 16 : if (!Printer) {
425 0 : DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
426 : OUR_HANDLE(hnd)));
427 0 : return WERR_INVALID_HANDLE;
428 : }
429 :
430 : /*
431 : * It turns out that Windows allows delete printer on a handle
432 : * opened by an admin user, then used on a pipe handle created
433 : * by an anonymous user..... but they're working on security.... riiight !
434 : * JRA.
435 : */
436 :
437 16 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
438 0 : DEBUG(3, ("delete_printer_handle: denied by handle\n"));
439 0 : return WERR_ACCESS_DENIED;
440 : }
441 :
442 : /* this does not need a become root since the access check has been
443 : done on the handle already */
444 :
445 16 : result = winreg_delete_printer_key_internal(p->mem_ctx,
446 : get_session_info_system(),
447 : p->msg_ctx,
448 16 : Printer->sharename,
449 : "");
450 16 : if (!W_ERROR_IS_OK(result)) {
451 0 : DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
452 0 : return WERR_INVALID_HANDLE;
453 : }
454 :
455 16 : result = delete_printer_hook(p->mem_ctx, session_info->security_token,
456 16 : Printer->sharename, p->msg_ctx);
457 16 : if (!W_ERROR_IS_OK(result)) {
458 0 : return result;
459 : }
460 16 : prune_printername_cache();
461 16 : return WERR_OK;
462 : }
463 :
464 : /****************************************************************************
465 : Return the snum of a printer corresponding to an handle.
466 : ****************************************************************************/
467 :
468 24717 : static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
469 : int *number, struct share_params **params)
470 : {
471 24717 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
472 :
473 24717 : if (!Printer) {
474 0 : DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
475 : OUR_HANDLE(hnd)));
476 0 : return false;
477 : }
478 :
479 24717 : switch (Printer->printer_type) {
480 24717 : case SPLHND_PRINTER:
481 24717 : DEBUG(4,("short name:%s\n", Printer->sharename));
482 24717 : *number = print_queue_snum(Printer->sharename);
483 24717 : return (*number != -1);
484 0 : case SPLHND_SERVER:
485 0 : return false;
486 0 : default:
487 0 : return false;
488 : }
489 : }
490 :
491 : /****************************************************************************
492 : Set printer handle type.
493 : Check if it's \\server or \\server\printer
494 : ****************************************************************************/
495 :
496 972 : static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
497 : {
498 972 : DEBUG(3,("Setting printer type=%s\n", handlename));
499 :
500 : /* it's a print server */
501 972 : if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
502 122 : DEBUGADD(4,("Printer is a print server\n"));
503 122 : Printer->printer_type = SPLHND_SERVER;
504 : }
505 : /* it's a printer (set_printer_hnd_name() will handle port monitors */
506 : else {
507 850 : DEBUGADD(4,("Printer is a printer\n"));
508 850 : Printer->printer_type = SPLHND_PRINTER;
509 : }
510 :
511 972 : return true;
512 : }
513 :
514 372 : static void prune_printername_cache_fn(const char *key, const char *value,
515 : time_t timeout, void *private_data)
516 : {
517 372 : gencache_del(key);
518 372 : }
519 :
520 132 : static void prune_printername_cache(void)
521 : {
522 132 : gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
523 132 : }
524 :
525 : /****************************************************************************
526 : Set printer handle name.. Accept names like \\server, \\server\printer,
527 : \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
528 : the MSDN docs regarding OpenPrinter() for details on the XcvData() and
529 : XcvDataPort() interface.
530 : ****************************************************************************/
531 :
532 972 : static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
533 : const struct auth_session_info *session_info,
534 : struct messaging_context *msg_ctx,
535 : struct printer_handle *Printer,
536 : const char *handlename)
537 : {
538 0 : int snum;
539 972 : int n_services=lp_numservices();
540 0 : char *aprinter;
541 0 : const char *printername;
542 972 : const char *servername = NULL;
543 0 : fstring sname;
544 972 : bool found = false;
545 972 : struct spoolss_PrinterInfo2 *info2 = NULL;
546 0 : WERROR result;
547 0 : char *p;
548 :
549 : /*
550 : * Hopefully nobody names his printers like this. Maybe \ or ,
551 : * are illegal in printer names even?
552 : */
553 972 : const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
554 0 : char *cache_key;
555 0 : char *tmp;
556 :
557 972 : DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
558 : (unsigned long)strlen(handlename)));
559 :
560 972 : aprinter = discard_const_p(char, handlename);
561 972 : if ( *handlename == '\\' ) {
562 252 : servername = canon_servername(handlename);
563 252 : if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
564 122 : *aprinter = '\0';
565 122 : aprinter++;
566 : }
567 252 : if (!is_myname_or_ipaddr(servername)) {
568 12 : return WERR_INVALID_PRINTER_NAME;
569 : }
570 240 : Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
571 240 : if (Printer->servername == NULL) {
572 0 : return WERR_NOT_ENOUGH_MEMORY;
573 : }
574 : }
575 :
576 960 : if (Printer->printer_type == SPLHND_SERVER) {
577 118 : return WERR_OK;
578 : }
579 :
580 842 : if (Printer->printer_type != SPLHND_PRINTER) {
581 0 : return WERR_INVALID_HANDLE;
582 : }
583 :
584 842 : DEBUGADD(5, ("searching for [%s]\n", aprinter));
585 :
586 842 : p = strchr(aprinter, ',');
587 842 : if (p != NULL) {
588 504 : char *p2 = p;
589 504 : p++;
590 504 : if (*p == ' ') {
591 308 : p++;
592 : }
593 504 : if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
594 140 : *p2 = '\0';
595 364 : } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
596 140 : *p2 = '\0';
597 : }
598 : }
599 :
600 842 : if (p) {
601 504 : DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
602 : }
603 :
604 : /* check for the Port Monitor Interface */
605 842 : if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
606 0 : Printer->printer_type = SPLHND_PORTMON_TCP;
607 0 : fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
608 0 : found = true;
609 : }
610 842 : else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
611 0 : Printer->printer_type = SPLHND_PORTMON_LOCAL;
612 0 : fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
613 0 : found = true;
614 : }
615 :
616 842 : cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
617 842 : if (cache_key == NULL) {
618 0 : return WERR_NOT_ENOUGH_MEMORY;
619 : }
620 :
621 : /*
622 : * With hundreds of printers, the "for" loop iterating all
623 : * shares can be quite expensive, as it is done on every
624 : * OpenPrinter. The loop maps "aprinter" to "sname", the
625 : * result of which we cache in gencache.
626 : */
627 842 : if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
628 462 : found = (strcmp(tmp, printer_not_found) != 0);
629 462 : if (!found) {
630 32 : DEBUG(4, ("Printer %s not found\n", aprinter));
631 32 : TALLOC_FREE(tmp);
632 32 : return WERR_INVALID_PRINTER_NAME;
633 : }
634 430 : fstrcpy(sname, tmp);
635 430 : TALLOC_FREE(tmp);
636 : }
637 :
638 : /* Search all sharenames first as this is easier than pulling
639 : the printer_info_2 off of disk. Don't use find_service() since
640 : that calls out to map_username() */
641 :
642 : /* do another loop to look for printernames */
643 23566 : for (snum = 0; !found && snum < n_services; snum++) {
644 22848 : const char *printer = lp_const_servicename(snum);
645 :
646 : /* no point going on if this is not a printer */
647 22848 : if (!(lp_snum_ok(snum) && lp_printable(snum))) {
648 20970 : continue;
649 : }
650 :
651 : /* ignore [printers] share */
652 1878 : if (strequal(printer, "printers")) {
653 0 : continue;
654 : }
655 :
656 1878 : fstrcpy(sname, printer);
657 1878 : if (strequal(aprinter, printer)) {
658 84 : found = true;
659 84 : break;
660 : }
661 :
662 : /* no point looking up the printer object if
663 : we aren't allowing printername != sharename */
664 1794 : if (lp_force_printername(snum)) {
665 0 : continue;
666 : }
667 :
668 1794 : result = winreg_get_printer_internal(mem_ctx,
669 : session_info,
670 : msg_ctx,
671 : sname,
672 : &info2);
673 1794 : if ( !W_ERROR_IS_OK(result) ) {
674 54 : DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
675 : sname, win_errstr(result)));
676 54 : continue;
677 : }
678 :
679 1740 : printername = strrchr(info2->printername, '\\');
680 1740 : if (printername == NULL) {
681 1740 : printername = info2->printername;
682 : } else {
683 0 : printername++;
684 : }
685 :
686 1740 : if (strequal(printername, aprinter)) {
687 8 : found = true;
688 8 : break;
689 : }
690 :
691 1732 : DEBUGADD(10, ("printername: %s\n", printername));
692 :
693 1732 : TALLOC_FREE(info2);
694 : }
695 :
696 810 : if (!found) {
697 288 : gencache_set(cache_key, printer_not_found,
698 288 : time(NULL) + 300);
699 288 : TALLOC_FREE(cache_key);
700 288 : DEBUGADD(4,("Printer not found\n"));
701 288 : return WERR_INVALID_PRINTER_NAME;
702 : }
703 :
704 522 : gencache_set(cache_key, sname, time(NULL) + 300);
705 522 : TALLOC_FREE(cache_key);
706 :
707 522 : DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
708 :
709 522 : strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
710 :
711 522 : return WERR_OK;
712 : }
713 :
714 : /****************************************************************************
715 : Find first available printer slot. creates a printer handle for you.
716 : ****************************************************************************/
717 :
718 972 : static WERROR open_printer_hnd(struct pipes_struct *p,
719 : struct policy_handle *hnd,
720 : const char *name,
721 : uint32_t access_granted)
722 : {
723 0 : struct printer_handle *new_printer;
724 0 : WERROR result;
725 :
726 972 : DEBUG(10,("open_printer_hnd: name [%s]\n", name));
727 :
728 972 : new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
729 972 : if (new_printer == NULL) {
730 0 : return WERR_NOT_ENOUGH_MEMORY;
731 : }
732 972 : talloc_set_destructor(new_printer, printer_entry_destructor);
733 :
734 : /* This also steals the printer_handle on the policy_handle */
735 972 : if (!create_policy_hnd(p, hnd, 0, new_printer)) {
736 0 : TALLOC_FREE(new_printer);
737 0 : return WERR_INVALID_HANDLE;
738 : }
739 :
740 : /* Add to the internal list. */
741 972 : DLIST_ADD(printers_list, new_printer);
742 :
743 972 : new_printer->notify.option=NULL;
744 :
745 972 : if (!set_printer_hnd_printertype(new_printer, name)) {
746 0 : close_printer_handle(p, hnd);
747 0 : return WERR_INVALID_HANDLE;
748 : }
749 :
750 972 : result = set_printer_hnd_name(p->mem_ctx,
751 : get_session_info_system(),
752 : p->msg_ctx,
753 : new_printer, name);
754 972 : if (!W_ERROR_IS_OK(result)) {
755 332 : close_printer_handle(p, hnd);
756 332 : return result;
757 : }
758 :
759 640 : new_printer->access_granted = access_granted;
760 :
761 640 : DBG_INFO("%d printer handles active\n", (int)num_pipe_handles());
762 :
763 640 : return WERR_OK;
764 : }
765 :
766 : /***************************************************************************
767 : check to see if the client notify handle is monitoring the notification
768 : given by (notify_type, notify_field).
769 : **************************************************************************/
770 :
771 0 : static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
772 : uint16_t notify_field)
773 : {
774 0 : return true;
775 : }
776 :
777 0 : static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
778 : uint16_t notify_field)
779 : {
780 0 : struct spoolss_NotifyOption *option = p->notify.option;
781 0 : uint32_t i, j;
782 :
783 : /*
784 : * Flags should always be zero when the change notify
785 : * is registered by the client's spooler. A user Win32 app
786 : * might use the flags though instead of the NOTIFY_OPTION_INFO
787 : * --jerry
788 : */
789 :
790 0 : if (!option) {
791 0 : return false;
792 : }
793 :
794 0 : if (p->notify.flags)
795 0 : return is_monitoring_event_flags(
796 : p->notify.flags, notify_type, notify_field);
797 :
798 0 : for (i = 0; i < option->count; i++) {
799 :
800 : /* Check match for notify_type */
801 :
802 0 : if (option->types[i].type != notify_type)
803 0 : continue;
804 :
805 : /* Check match for field */
806 :
807 0 : for (j = 0; j < option->types[i].count; j++) {
808 0 : if (option->types[i].fields[j].field == notify_field) {
809 0 : return true;
810 : }
811 : }
812 : }
813 :
814 0 : DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
815 : p->servername, p->sharename, notify_type, notify_field));
816 :
817 0 : return false;
818 : }
819 :
820 : #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
821 : _data->data.integer[0] = _integer; \
822 : _data->data.integer[1] = 0;
823 :
824 :
825 : #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
826 : _data->data.string.string = talloc_strdup(mem_ctx, _p); \
827 : if (!_data->data.string.string) {\
828 : _data->data.string.size = 0; \
829 : } \
830 : _data->data.string.size = strlen_m_term(_p) * 2;
831 :
832 : #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
833 : _data->data.devmode.devmode = _devmode;
834 :
835 0 : static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
836 : struct tm *t,
837 : const char **pp,
838 : uint32_t *plen)
839 : {
840 0 : struct spoolss_Time st;
841 0 : uint32_t len = 16;
842 0 : char *p;
843 :
844 0 : if (!init_systemtime(&st, t)) {
845 0 : return;
846 : }
847 :
848 0 : p = talloc_array(mem_ctx, char, len);
849 0 : if (!p) {
850 0 : return;
851 : }
852 :
853 : /*
854 : * Systemtime must be linearized as a set of UINT16's.
855 : * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
856 : */
857 :
858 0 : SSVAL(p, 0, st.year);
859 0 : SSVAL(p, 2, st.month);
860 0 : SSVAL(p, 4, st.day_of_week);
861 0 : SSVAL(p, 6, st.day);
862 0 : SSVAL(p, 8, st.hour);
863 0 : SSVAL(p, 10, st.minute);
864 0 : SSVAL(p, 12, st.second);
865 0 : SSVAL(p, 14, st.millisecond);
866 :
867 0 : *pp = p;
868 0 : *plen = len;
869 : }
870 :
871 : /* Convert a notification message to a struct spoolss_Notify */
872 :
873 0 : static void notify_one_value(struct spoolss_notify_msg *msg,
874 : struct spoolss_Notify *data,
875 : TALLOC_CTX *mem_ctx)
876 : {
877 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
878 0 : }
879 :
880 0 : static void notify_string(struct spoolss_notify_msg *msg,
881 : struct spoolss_Notify *data,
882 : TALLOC_CTX *mem_ctx)
883 : {
884 : /* The length of the message includes the trailing \0 */
885 :
886 0 : data->data.string.size = msg->len * 2;
887 0 : data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
888 0 : if (!data->data.string.string) {
889 0 : data->data.string.size = 0;
890 0 : return;
891 : }
892 : }
893 :
894 0 : static void notify_system_time(struct spoolss_notify_msg *msg,
895 : struct spoolss_Notify *data,
896 : TALLOC_CTX *mem_ctx)
897 : {
898 0 : data->data.string.string = NULL;
899 0 : data->data.string.size = 0;
900 :
901 0 : if (msg->len != sizeof(time_t)) {
902 0 : DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
903 : msg->len));
904 0 : return;
905 : }
906 :
907 0 : init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
908 : &data->data.string.string,
909 : &data->data.string.size);
910 : }
911 :
912 : struct notify2_message_table {
913 : const char *name;
914 : void (*fn)(struct spoolss_notify_msg *msg,
915 : struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
916 : };
917 :
918 : static struct notify2_message_table printer_notify_table[] = {
919 : /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
920 : /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
921 : /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
922 : /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
923 : /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
924 : /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
925 : /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
926 : /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
927 : /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
928 : /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
929 : /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
930 : /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
931 : /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
932 : /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
933 : /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
934 : /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
935 : /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
936 : /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
937 : /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
938 : };
939 :
940 : static struct notify2_message_table job_notify_table[] = {
941 : /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
942 : /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
943 : /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
944 : /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
945 : /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
946 : /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
947 : /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
948 : /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
949 : /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
950 : /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
951 : /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
952 : /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
953 : /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
954 : /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
955 : /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
956 : /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
957 : /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
958 : /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
959 : /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
960 : /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
961 : /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
962 : /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
963 : /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
964 : /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
965 : };
966 :
967 :
968 : /***********************************************************************
969 : Allocate talloc context for container object
970 : **********************************************************************/
971 :
972 0 : static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
973 : {
974 0 : if ( !ctr )
975 0 : return;
976 :
977 0 : ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
978 :
979 0 : return;
980 : }
981 :
982 : /***********************************************************************
983 : release all allocated memory and zero out structure
984 : **********************************************************************/
985 :
986 0 : static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
987 : {
988 0 : if ( !ctr )
989 0 : return;
990 :
991 0 : if ( ctr->ctx )
992 0 : talloc_destroy(ctr->ctx);
993 :
994 0 : ZERO_STRUCTP(ctr);
995 :
996 0 : return;
997 : }
998 :
999 : /***********************************************************************
1000 : **********************************************************************/
1001 :
1002 0 : static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1003 : {
1004 0 : if ( !ctr )
1005 0 : return NULL;
1006 :
1007 0 : return ctr->ctx;
1008 : }
1009 :
1010 : /***********************************************************************
1011 : **********************************************************************/
1012 :
1013 0 : static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1014 : {
1015 0 : if ( !ctr || !ctr->msg_groups )
1016 0 : return NULL;
1017 :
1018 0 : if ( idx >= ctr->num_groups )
1019 0 : return NULL;
1020 :
1021 0 : return &ctr->msg_groups[idx];
1022 :
1023 : }
1024 :
1025 : /***********************************************************************
1026 : How many groups of change messages do we have ?
1027 : **********************************************************************/
1028 :
1029 0 : static uint32_t notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1030 : {
1031 0 : if ( !ctr )
1032 0 : return 0;
1033 :
1034 0 : return ctr->num_groups;
1035 : }
1036 :
1037 : /***********************************************************************
1038 : Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1039 : **********************************************************************/
1040 :
1041 0 : static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1042 : {
1043 0 : SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1044 0 : SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1045 0 : SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1046 0 : uint32_t i, new_slot;
1047 :
1048 0 : if ( !ctr || !msg )
1049 0 : return 0;
1050 :
1051 : /* loop over all groups looking for a matching printer name */
1052 :
1053 0 : for ( i=0; i<ctr->num_groups; i++ ) {
1054 0 : if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1055 0 : break;
1056 : }
1057 :
1058 : /* add a new group? */
1059 :
1060 0 : if ( i == ctr->num_groups ) {
1061 0 : ctr->num_groups++;
1062 :
1063 0 : if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1064 0 : DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1065 0 : return 0;
1066 : }
1067 0 : ctr->msg_groups = groups;
1068 :
1069 : /* clear the new entry and set the printer name */
1070 :
1071 0 : ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1072 0 : fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1073 : }
1074 :
1075 : /* add the change messages; 'i' is the correct index now regardless */
1076 :
1077 0 : msg_grp = &ctr->msg_groups[i];
1078 :
1079 0 : msg_grp->num_msgs++;
1080 :
1081 0 : if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1082 0 : DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1083 0 : return 0;
1084 : }
1085 0 : msg_grp->msgs = msg_list;
1086 :
1087 0 : new_slot = msg_grp->num_msgs-1;
1088 0 : memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1089 :
1090 : /* need to allocate own copy of data */
1091 :
1092 0 : if ( msg->len != 0 )
1093 0 : msg_grp->msgs[new_slot].notify.data = (char *)
1094 0 : talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1095 :
1096 0 : return ctr->num_groups;
1097 : }
1098 :
1099 : static void construct_info_data(struct spoolss_Notify *info_data,
1100 : enum spoolss_NotifyType type,
1101 : uint16_t field, int id);
1102 :
1103 : /***********************************************************************
1104 : Send a change notification message on all handles which have a call
1105 : back registered
1106 : **********************************************************************/
1107 :
1108 0 : static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1109 : struct printer_handle *prn_hnd,
1110 : SPOOLSS_NOTIFY_MSG *messages,
1111 : uint32_t num_msgs,
1112 : struct spoolss_Notify **_notifies,
1113 : size_t *_count)
1114 : {
1115 0 : struct spoolss_Notify *notifies;
1116 0 : SPOOLSS_NOTIFY_MSG *msg;
1117 0 : size_t count = 0;
1118 0 : uint32_t id;
1119 0 : uint32_t i;
1120 :
1121 0 : notifies = talloc_zero_array(mem_ctx,
1122 : struct spoolss_Notify, num_msgs);
1123 0 : if (!notifies) {
1124 0 : return ENOMEM;
1125 : }
1126 :
1127 0 : for (i = 0; i < num_msgs; i++) {
1128 :
1129 0 : msg = &messages[i];
1130 :
1131 : /* Are we monitoring this event? */
1132 :
1133 0 : if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1134 0 : continue;
1135 : }
1136 :
1137 0 : DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1138 : "for printer [%s]\n",
1139 : msg->type, msg->field, prn_hnd->sharename));
1140 :
1141 : /*
1142 : * if the is a printer notification handle and not a job
1143 : * notification type, then set the id to 0.
1144 : * Otherwise just use what was specified in the message.
1145 : *
1146 : * When registering change notification on a print server
1147 : * handle we always need to send back the id (snum) matching
1148 : * the printer for which the change took place.
1149 : * For change notify registered on a printer handle,
1150 : * this does not matter and the id should be 0.
1151 : *
1152 : * --jerry
1153 : */
1154 :
1155 0 : if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1156 0 : (prn_hnd->printer_type == SPLHND_PRINTER)) {
1157 0 : id = 0;
1158 : } else {
1159 0 : id = msg->id;
1160 : }
1161 :
1162 : /* Convert unix jobid to smb jobid */
1163 :
1164 0 : if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1165 0 : id = sysjob_to_jobid(msg->id);
1166 :
1167 0 : if (id == -1) {
1168 0 : DEBUG(3, ("no such unix jobid %d\n",
1169 : msg->id));
1170 0 : continue;
1171 : }
1172 : }
1173 :
1174 0 : construct_info_data(¬ifies[count],
1175 0 : msg->type, msg->field, id);
1176 :
1177 0 : switch(msg->type) {
1178 0 : case PRINTER_NOTIFY_TYPE:
1179 0 : if (printer_notify_table[msg->field].fn) {
1180 0 : printer_notify_table[msg->field].fn(msg,
1181 0 : ¬ifies[count], mem_ctx);
1182 : }
1183 0 : break;
1184 :
1185 0 : case JOB_NOTIFY_TYPE:
1186 0 : if (job_notify_table[msg->field].fn) {
1187 0 : job_notify_table[msg->field].fn(msg,
1188 0 : ¬ifies[count], mem_ctx);
1189 : }
1190 0 : break;
1191 :
1192 0 : default:
1193 0 : DEBUG(5, ("Unknown notification type %d\n",
1194 : msg->type));
1195 0 : continue;
1196 : }
1197 :
1198 0 : count++;
1199 : }
1200 :
1201 0 : *_notifies = notifies;
1202 0 : *_count = count;
1203 :
1204 0 : return 0;
1205 : }
1206 :
1207 0 : static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1208 : struct printer_handle *prn_hnd,
1209 : SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1210 : {
1211 0 : struct spoolss_Notify *notifies;
1212 0 : size_t count = 0;
1213 0 : union spoolss_ReplyPrinterInfo info;
1214 0 : struct spoolss_NotifyInfo info0;
1215 0 : uint32_t reply_result;
1216 0 : NTSTATUS status;
1217 0 : WERROR werr;
1218 0 : int ret;
1219 :
1220 : /* Is there notification on this handle? */
1221 0 : if (prn_hnd->notify.cli_chan == NULL ||
1222 0 : prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1223 0 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1224 0 : prn_hnd->notify.cli_chan->active_connections == 0) {
1225 0 : return 0;
1226 : }
1227 :
1228 0 : DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1229 : prn_hnd->servername, prn_hnd->sharename));
1230 :
1231 : /* For this printer? Print servers always receive notifications. */
1232 0 : if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1233 0 : (!strequal(msg_group->printername, prn_hnd->sharename))) {
1234 0 : return 0;
1235 : }
1236 :
1237 0 : DEBUG(10,("Our printer\n"));
1238 :
1239 : /* build the array of change notifications */
1240 0 : ret = build_notify2_messages(mem_ctx, prn_hnd,
1241 : msg_group->msgs,
1242 : msg_group->num_msgs,
1243 : ¬ifies, &count);
1244 0 : if (ret) {
1245 0 : return ret;
1246 : }
1247 :
1248 0 : info0.version = 0x2;
1249 0 : info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1250 0 : info0.count = count;
1251 0 : info0.notifies = notifies;
1252 :
1253 0 : info.info0 = &info0;
1254 :
1255 0 : status = dcerpc_spoolss_RouterReplyPrinterEx(
1256 0 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1257 : mem_ctx,
1258 : &prn_hnd->notify.cli_hnd,
1259 : prn_hnd->notify.change, /* color */
1260 : prn_hnd->notify.flags,
1261 : &reply_result,
1262 : 0, /* reply_type, must be 0 */
1263 : info, &werr);
1264 0 : if (!NT_STATUS_IS_OK(status)) {
1265 0 : DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1266 : "failed: %s\n",
1267 : prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1268 : nt_errstr(status)));
1269 0 : werr = ntstatus_to_werror(status);
1270 0 : } else if (!W_ERROR_IS_OK(werr)) {
1271 0 : DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1272 : "failed: %s\n",
1273 : prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1274 : win_errstr(werr)));
1275 : }
1276 0 : switch (reply_result) {
1277 0 : case 0:
1278 0 : break;
1279 0 : case PRINTER_NOTIFY_INFO_DISCARDED:
1280 : case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1281 : case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1282 0 : break;
1283 0 : default:
1284 0 : break;
1285 : }
1286 :
1287 0 : return 0;
1288 : }
1289 :
1290 0 : static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1291 : {
1292 0 : struct printer_handle *p;
1293 0 : TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1294 0 : SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1295 0 : int ret;
1296 :
1297 0 : if ( !msg_group ) {
1298 0 : DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1299 0 : return;
1300 : }
1301 :
1302 0 : if (!msg_group->msgs) {
1303 0 : DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1304 0 : return;
1305 : }
1306 :
1307 0 : DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1308 :
1309 : /* loop over all printers */
1310 :
1311 0 : for (p = printers_list; p; p = p->next) {
1312 0 : ret = send_notify2_printer(mem_ctx, p, msg_group);
1313 0 : if (ret) {
1314 0 : goto done;
1315 : }
1316 : }
1317 :
1318 0 : done:
1319 0 : DEBUG(8,("send_notify2_changes: Exit...\n"));
1320 0 : return;
1321 : }
1322 :
1323 : /***********************************************************************
1324 : **********************************************************************/
1325 :
1326 0 : static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1327 : {
1328 :
1329 0 : uint32_t tv_sec, tv_usec;
1330 0 : size_t offset = 0;
1331 :
1332 : /* Unpack message */
1333 :
1334 0 : offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1335 0 : msg->printer);
1336 :
1337 0 : offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1338 : &tv_sec, &tv_usec,
1339 : &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1340 :
1341 0 : if (msg->len == 0)
1342 0 : tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1343 : &msg->notify.value[0], &msg->notify.value[1]);
1344 : else
1345 0 : tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1346 : &msg->len, &msg->notify.data);
1347 :
1348 0 : DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1349 : msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1350 :
1351 0 : tv->tv_sec = tv_sec;
1352 0 : tv->tv_usec = tv_usec;
1353 :
1354 0 : if (msg->len == 0)
1355 0 : DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1356 : msg->notify.value[1]));
1357 : else
1358 0 : dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1359 :
1360 0 : return true;
1361 : }
1362 :
1363 : /********************************************************************
1364 : Receive a notify2 message list
1365 : ********************************************************************/
1366 :
1367 0 : static void receive_notify2_message_list(struct messaging_context *msg,
1368 : void *private_data,
1369 : uint32_t msg_type,
1370 : struct server_id server_id,
1371 : DATA_BLOB *data)
1372 : {
1373 0 : size_t msg_count, i, num_groups;
1374 0 : char *buf = (char *)data->data;
1375 0 : char *msg_ptr;
1376 0 : size_t msg_len;
1377 0 : SPOOLSS_NOTIFY_MSG notify;
1378 0 : SPOOLSS_NOTIFY_MSG_CTR messages;
1379 :
1380 0 : if (data->length < 4) {
1381 0 : DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1382 0 : return;
1383 : }
1384 :
1385 0 : msg_count = IVAL(buf, 0);
1386 0 : msg_ptr = buf + 4;
1387 :
1388 0 : DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1389 :
1390 0 : if (msg_count == 0) {
1391 0 : DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1392 0 : return;
1393 : }
1394 :
1395 : /* initialize the container */
1396 :
1397 0 : ZERO_STRUCT( messages );
1398 0 : notify_msg_ctr_init( &messages );
1399 :
1400 : /*
1401 : * build message groups for each printer identified
1402 : * in a change_notify msg. Remember that a PCN message
1403 : * includes the handle returned for the srv_spoolss_replyopenprinter()
1404 : * call. Therefore messages are grouped according to printer handle.
1405 : */
1406 :
1407 0 : for ( i=0; i<msg_count; i++ ) {
1408 0 : struct timeval msg_tv;
1409 :
1410 0 : if (msg_ptr + 4 - buf > data->length) {
1411 0 : DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1412 0 : return;
1413 : }
1414 :
1415 0 : msg_len = IVAL(msg_ptr,0);
1416 0 : msg_ptr += 4;
1417 :
1418 0 : if (msg_ptr + msg_len - buf > data->length) {
1419 0 : DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1420 0 : return;
1421 : }
1422 :
1423 : /* unpack messages */
1424 :
1425 0 : ZERO_STRUCT( notify );
1426 0 : notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1427 0 : msg_ptr += msg_len;
1428 :
1429 : /* add to correct list in container */
1430 :
1431 0 : notify_msg_ctr_addmsg( &messages, ¬ify );
1432 :
1433 : /* free memory that might have been allocated by notify2_unpack_msg() */
1434 :
1435 0 : if ( notify.len != 0 )
1436 0 : SAFE_FREE( notify.notify.data );
1437 : }
1438 :
1439 : /* process each group of messages */
1440 :
1441 0 : num_groups = notify_msg_ctr_numgroups( &messages );
1442 0 : for ( i=0; i<num_groups; i++ )
1443 0 : send_notify2_changes( &messages, i );
1444 :
1445 :
1446 : /* cleanup */
1447 :
1448 0 : DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1449 : (uint32_t)msg_count ));
1450 :
1451 0 : notify_msg_ctr_destroy( &messages );
1452 :
1453 0 : return;
1454 : }
1455 :
1456 : /********************************************************************
1457 : Send a message to ourself about new driver being installed
1458 : so we can upgrade the information for each printer bound to this
1459 : driver
1460 : ********************************************************************/
1461 :
1462 0 : static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1463 : struct messaging_context *msg_ctx)
1464 : {
1465 0 : int len = strlen(drivername);
1466 :
1467 0 : if (!len)
1468 0 : return false;
1469 :
1470 0 : DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1471 : drivername));
1472 :
1473 0 : messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1474 : MSG_PRINTER_DRVUPGRADE,
1475 0 : (const uint8_t *)drivername, len+1);
1476 :
1477 0 : return true;
1478 : }
1479 :
1480 28 : void srv_spoolss_cleanup(void)
1481 : {
1482 0 : struct printer_session_counter *session_counter;
1483 :
1484 28 : for (session_counter = counter_list;
1485 68 : session_counter != NULL;
1486 40 : session_counter = counter_list) {
1487 40 : DLIST_REMOVE(counter_list, session_counter);
1488 40 : TALLOC_FREE(session_counter);
1489 : }
1490 28 : }
1491 :
1492 : /**********************************************************************
1493 : callback to receive a MSG_PRINTER_DRVUPGRADE message and iterate
1494 : over all printers, upgrading ones as necessary
1495 : This is now *ONLY* called inside the background lpq updater. JRA.
1496 : **********************************************************************/
1497 :
1498 0 : void do_drv_upgrade_printer(struct messaging_context *msg,
1499 : void *private_data,
1500 : uint32_t msg_type,
1501 : struct server_id server_id,
1502 : DATA_BLOB *data)
1503 : {
1504 0 : TALLOC_CTX *tmp_ctx;
1505 0 : const struct auth_session_info *session_info = get_session_info_system();
1506 0 : struct spoolss_PrinterInfo2 *pinfo2;
1507 0 : WERROR result;
1508 0 : const char *drivername;
1509 0 : int snum;
1510 0 : int n_services = lp_numservices();
1511 0 : struct dcerpc_binding_handle *b = NULL;
1512 :
1513 0 : tmp_ctx = talloc_new(NULL);
1514 0 : if (!tmp_ctx) return;
1515 :
1516 0 : drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1517 0 : if (!drivername) {
1518 0 : DEBUG(0, ("do_drv_upgrade_printer: Out of memory ?!\n"));
1519 0 : goto done;
1520 : }
1521 :
1522 0 : DEBUG(10, ("do_drv_upgrade_printer: "
1523 : "Got message for new driver [%s]\n", drivername));
1524 :
1525 : /* Iterate the printer list */
1526 :
1527 0 : for (snum = 0; snum < n_services; snum++) {
1528 0 : if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1529 0 : continue;
1530 : }
1531 :
1532 : /* ignore [printers] share */
1533 0 : if (strequal(lp_const_servicename(snum), "printers")) {
1534 0 : continue;
1535 : }
1536 :
1537 0 : if (b == NULL) {
1538 0 : result = winreg_printer_binding_handle(tmp_ctx,
1539 : session_info,
1540 : msg,
1541 : &b);
1542 0 : if (!W_ERROR_IS_OK(result)) {
1543 0 : break;
1544 : }
1545 : }
1546 :
1547 0 : result = winreg_get_printer(tmp_ctx, b,
1548 : lp_const_servicename(snum),
1549 : &pinfo2);
1550 :
1551 0 : if (!W_ERROR_IS_OK(result)) {
1552 0 : continue;
1553 : }
1554 :
1555 0 : if (!pinfo2->drivername) {
1556 0 : continue;
1557 : }
1558 :
1559 0 : if (strcmp(drivername, pinfo2->drivername) != 0) {
1560 0 : continue;
1561 : }
1562 :
1563 0 : DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1564 :
1565 : /* all we care about currently is the change_id */
1566 0 : result = winreg_printer_update_changeid(tmp_ctx, b,
1567 0 : pinfo2->printername);
1568 :
1569 0 : if (!W_ERROR_IS_OK(result)) {
1570 0 : DEBUG(3, ("do_drv_upgrade_printer: "
1571 : "Failed to update changeid [%s]\n",
1572 : win_errstr(result)));
1573 : }
1574 : }
1575 :
1576 : /* all done */
1577 0 : done:
1578 0 : talloc_free(tmp_ctx);
1579 : }
1580 :
1581 : /********************************************************************
1582 : Update the cache for all printq's with a registered client
1583 : connection
1584 : ********************************************************************/
1585 :
1586 0 : void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1587 : {
1588 0 : struct printer_handle *printer = printers_list;
1589 0 : int snum;
1590 :
1591 : /* loop through all printers and update the cache where
1592 : a client is connected */
1593 0 : while (printer) {
1594 0 : if ((printer->printer_type == SPLHND_PRINTER) &&
1595 0 : ((printer->notify.cli_chan != NULL) &&
1596 0 : (printer->notify.cli_chan->active_connections > 0))) {
1597 0 : snum = print_queue_snum(printer->sharename);
1598 0 : print_queue_status(msg_ctx, snum, NULL, NULL);
1599 : }
1600 :
1601 0 : printer = printer->next;
1602 : }
1603 :
1604 0 : return;
1605 : }
1606 :
1607 : /****************************************************************
1608 : _spoolss_OpenPrinter
1609 : ****************************************************************/
1610 :
1611 194 : WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1612 : struct spoolss_OpenPrinter *r)
1613 : {
1614 0 : struct spoolss_OpenPrinterEx e;
1615 0 : struct spoolss_UserLevel1 level1;
1616 0 : WERROR werr;
1617 :
1618 194 : ZERO_STRUCT(level1);
1619 :
1620 194 : e.in.printername = r->in.printername;
1621 194 : e.in.datatype = r->in.datatype;
1622 194 : e.in.devmode_ctr = r->in.devmode_ctr;
1623 194 : e.in.access_mask = r->in.access_mask;
1624 194 : e.in.userlevel_ctr.level = 1;
1625 194 : e.in.userlevel_ctr.user_info.level1 = &level1;
1626 :
1627 194 : e.out.handle = r->out.handle;
1628 :
1629 194 : werr = _spoolss_OpenPrinterEx(p, &e);
1630 :
1631 194 : if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1632 : /* OpenPrinterEx returns this for a bad
1633 : * printer name. We must return WERR_INVALID_PRINTER_NAME
1634 : * instead.
1635 : */
1636 4 : werr = WERR_INVALID_PRINTER_NAME;
1637 : }
1638 :
1639 194 : return werr;
1640 : }
1641 :
1642 2850 : static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1643 : struct spoolss_DeviceMode *orig,
1644 : struct spoolss_DeviceMode **dest)
1645 : {
1646 0 : struct spoolss_DeviceMode *dm;
1647 :
1648 2850 : dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1649 2850 : if (!dm) {
1650 0 : return WERR_NOT_ENOUGH_MEMORY;
1651 : }
1652 :
1653 : /* copy all values, then duplicate strings and structs */
1654 2850 : *dm = *orig;
1655 :
1656 2850 : dm->devicename = talloc_strdup(dm, orig->devicename);
1657 2850 : if (!dm->devicename) {
1658 0 : return WERR_NOT_ENOUGH_MEMORY;
1659 : }
1660 2850 : dm->formname = talloc_strdup(dm, orig->formname);
1661 2850 : if (!dm->formname) {
1662 0 : return WERR_NOT_ENOUGH_MEMORY;
1663 : }
1664 2850 : if (orig->driverextra_data.data) {
1665 1392 : dm->driverextra_data.data =
1666 1392 : (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1667 : orig->driverextra_data.length);
1668 1392 : if (!dm->driverextra_data.data) {
1669 0 : return WERR_NOT_ENOUGH_MEMORY;
1670 : }
1671 : }
1672 :
1673 2850 : *dest = dm;
1674 2850 : return WERR_OK;
1675 : }
1676 :
1677 : /****************************************************************
1678 : _spoolss_OpenPrinterEx
1679 : ****************************************************************/
1680 :
1681 988 : WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1682 : struct spoolss_OpenPrinterEx *r)
1683 : {
1684 988 : struct dcesrv_call_state *dce_call = p->dce_call;
1685 988 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
1686 0 : const struct tsocket_address *remote_address =
1687 988 : dcesrv_connection_get_remote_address(dcesrv_conn);
1688 0 : struct auth_session_info *session_info =
1689 988 : dcesrv_call_session_info(dce_call);
1690 0 : int snum;
1691 0 : char *raddr;
1692 0 : char *rhost;
1693 988 : struct printer_handle *Printer=NULL;
1694 0 : WERROR result;
1695 0 : int rc;
1696 :
1697 988 : if (!r->in.printername) {
1698 0 : return WERR_INVALID_PARAMETER;
1699 : }
1700 :
1701 988 : if (!*r->in.printername) {
1702 8 : return WERR_INVALID_PARAMETER;
1703 : }
1704 :
1705 980 : if (r->in.userlevel_ctr.level > 3) {
1706 0 : return WERR_INVALID_PARAMETER;
1707 : }
1708 980 : if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1709 956 : (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1710 956 : (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1711 24 : return WERR_INVALID_PARAMETER;
1712 : }
1713 :
1714 : /*
1715 : * The printcap printer share inventory is updated on client
1716 : * enumeration. For clients that do not perform enumeration prior to
1717 : * access, such as cupssmbadd, we reinitialise the printer share
1718 : * inventory on open as well.
1719 : */
1720 956 : become_root();
1721 956 : delete_and_reload_printers();
1722 956 : unbecome_root();
1723 :
1724 : /* some sanity check because you can open a printer or a print server */
1725 : /* aka: \\server\printer or \\server */
1726 :
1727 956 : DEBUGADD(3,("checking name: %s\n", r->in.printername));
1728 :
1729 956 : result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1730 956 : if (!W_ERROR_IS_OK(result)) {
1731 332 : DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1732 : "for printer %s\n", r->in.printername));
1733 332 : ZERO_STRUCTP(r->out.handle);
1734 332 : return result;
1735 : }
1736 :
1737 624 : Printer = find_printer_index_by_hnd(p, r->out.handle);
1738 624 : if ( !Printer ) {
1739 0 : DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1740 : "handle we created for printer %s\n", r->in.printername));
1741 0 : close_printer_handle(p, r->out.handle);
1742 0 : ZERO_STRUCTP(r->out.handle);
1743 0 : return WERR_INVALID_PARAMETER;
1744 : }
1745 :
1746 : /*
1747 : * First case: the user is opening the print server:
1748 : *
1749 : * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1750 : * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1751 : *
1752 : * Then both Win2k and WinNT clients try an OpenPrinterEx with
1753 : * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1754 : * or if the user is listed in the smb.conf printer admin parameter.
1755 : *
1756 : * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1757 : * client view printer folder, but does not show the MSAPW.
1758 : *
1759 : * Note: this test needs code to check access rights here too. Jeremy
1760 : * could you look at this?
1761 : *
1762 : * Second case: the user is opening a printer:
1763 : * NT doesn't let us connect to a printer if the connecting user
1764 : * doesn't have print permission.
1765 : *
1766 : * Third case: user is opening a Port Monitor
1767 : * access checks same as opening a handle to the print server.
1768 : */
1769 :
1770 624 : switch (Printer->printer_type )
1771 : {
1772 118 : case SPLHND_SERVER:
1773 : case SPLHND_PORTMON_TCP:
1774 : case SPLHND_PORTMON_LOCAL:
1775 : /* Printserver handles use global struct... */
1776 :
1777 118 : snum = -1;
1778 :
1779 118 : if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1780 90 : r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1781 90 : r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1782 : }
1783 :
1784 : /* Map standard access rights to object specific access rights */
1785 :
1786 118 : se_map_standard(&r->in.access_mask,
1787 : &printserver_std_mapping);
1788 :
1789 : /* Deny any object specific bits that don't apply to print
1790 : servers (i.e printer and job specific bits) */
1791 :
1792 118 : r->in.access_mask &= SEC_MASK_SPECIFIC;
1793 :
1794 118 : if (r->in.access_mask &
1795 : ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1796 0 : DEBUG(3, ("access DENIED for non-printserver bits\n"));
1797 0 : close_printer_handle(p, r->out.handle);
1798 0 : ZERO_STRUCTP(r->out.handle);
1799 0 : return WERR_ACCESS_DENIED;
1800 : }
1801 :
1802 : /* Allow admin access */
1803 :
1804 118 : if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1805 : {
1806 94 : if (!lp_show_add_printer_wizard()) {
1807 0 : close_printer_handle(p, r->out.handle);
1808 0 : ZERO_STRUCTP(r->out.handle);
1809 0 : return WERR_ACCESS_DENIED;
1810 : }
1811 :
1812 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1813 : and not a printer admin, then fail */
1814 :
1815 94 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
1816 2 : !security_token_has_privilege(
1817 2 : session_info->security_token,
1818 0 : SEC_PRIV_PRINT_OPERATOR) &&
1819 0 : !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1820 0 : session_info->security_token)) {
1821 0 : close_printer_handle(p, r->out.handle);
1822 0 : ZERO_STRUCTP(r->out.handle);
1823 0 : DEBUG(3,("access DENIED as user is not root, "
1824 : "has no printoperator privilege and is "
1825 : "not a member of the printoperator builtin group\n"));
1826 0 : return WERR_ACCESS_DENIED;
1827 : }
1828 :
1829 94 : r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1830 : }
1831 : else
1832 : {
1833 24 : r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1834 : }
1835 :
1836 118 : DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1837 : ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1838 :
1839 118 : break;
1840 :
1841 506 : case SPLHND_PRINTER:
1842 : /* NT doesn't let us connect to a printer if the connecting user
1843 : doesn't have print permission. */
1844 :
1845 506 : if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1846 0 : close_printer_handle(p, r->out.handle);
1847 0 : ZERO_STRUCTP(r->out.handle);
1848 0 : return WERR_INVALID_HANDLE;
1849 : }
1850 :
1851 506 : if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1852 170 : r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1853 : }
1854 :
1855 506 : se_map_standard(&r->in.access_mask, &printer_std_mapping);
1856 :
1857 : /* map an empty access mask to the minimum access mask */
1858 506 : if (r->in.access_mask == 0x0)
1859 296 : r->in.access_mask = PRINTER_ACCESS_USE;
1860 :
1861 : /*
1862 : * If we are not serving the printer driver for this printer,
1863 : * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1864 : * will keep NT clients happy --jerry
1865 : */
1866 :
1867 506 : if (lp_use_client_driver(snum)
1868 0 : && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1869 : {
1870 0 : r->in.access_mask = PRINTER_ACCESS_USE;
1871 : }
1872 :
1873 : /* check smb.conf parameters and the the sec_desc */
1874 506 : raddr = tsocket_address_inet_addr_string(remote_address,
1875 : p->mem_ctx);
1876 506 : if (raddr == NULL) {
1877 0 : return WERR_NOT_ENOUGH_MEMORY;
1878 : }
1879 :
1880 506 : rc = get_remote_hostname(remote_address,
1881 : &rhost,
1882 : p->mem_ctx);
1883 506 : if (rc < 0) {
1884 0 : return WERR_NOT_ENOUGH_MEMORY;
1885 : }
1886 506 : if (strequal(rhost, "UNKNOWN")) {
1887 506 : rhost = raddr;
1888 : }
1889 :
1890 506 : if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1891 : rhost, raddr)) {
1892 0 : DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1893 0 : ZERO_STRUCTP(r->out.handle);
1894 0 : return WERR_ACCESS_DENIED;
1895 : }
1896 :
1897 506 : if (!user_ok_token(session_info->unix_info->unix_name,
1898 506 : session_info->info->domain_name,
1899 506 : session_info->security_token, snum) ||
1900 506 : !W_ERROR_IS_OK(print_access_check(session_info,
1901 : p->msg_ctx,
1902 : snum,
1903 : r->in.access_mask))) {
1904 0 : DEBUG(3, ("access DENIED for printer open\n"));
1905 0 : close_printer_handle(p, r->out.handle);
1906 0 : ZERO_STRUCTP(r->out.handle);
1907 0 : return WERR_ACCESS_DENIED;
1908 : }
1909 :
1910 506 : if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1911 4 : DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912 4 : close_printer_handle(p, r->out.handle);
1913 4 : ZERO_STRUCTP(r->out.handle);
1914 4 : return WERR_ACCESS_DENIED;
1915 : }
1916 :
1917 502 : if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1918 170 : r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1919 : else
1920 332 : r->in.access_mask = PRINTER_ACCESS_USE;
1921 :
1922 502 : DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1923 : ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1924 :
1925 502 : winreg_create_printer_internal(p->mem_ctx,
1926 : get_session_info_system(),
1927 : p->msg_ctx,
1928 : lp_const_servicename(snum));
1929 :
1930 502 : break;
1931 :
1932 0 : default:
1933 : /* sanity check to prevent programmer error */
1934 0 : ZERO_STRUCTP(r->out.handle);
1935 0 : return WERR_INVALID_HANDLE;
1936 : }
1937 :
1938 620 : Printer->access_granted = r->in.access_mask;
1939 :
1940 : /*
1941 : * If the client sent a devmode in the OpenPrinter() call, then
1942 : * save it here in case we get a job submission on this handle
1943 : */
1944 :
1945 620 : if ((Printer->printer_type != SPLHND_SERVER)
1946 502 : && (r->in.devmode_ctr.devmode != NULL)) {
1947 8 : copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1948 : &Printer->devmode);
1949 : }
1950 :
1951 620 : return WERR_OK;
1952 : }
1953 :
1954 : /****************************************************************
1955 : _spoolss_ClosePrinter
1956 : ****************************************************************/
1957 :
1958 620 : WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1959 : struct spoolss_ClosePrinter *r)
1960 : {
1961 620 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1962 :
1963 620 : if (Printer && Printer->document_started) {
1964 0 : struct spoolss_EndDocPrinter e;
1965 :
1966 28 : e.in.handle = r->in.handle;
1967 :
1968 28 : _spoolss_EndDocPrinter(p, &e);
1969 : }
1970 :
1971 620 : if (!close_printer_handle(p, r->in.handle))
1972 0 : return WERR_INVALID_HANDLE;
1973 :
1974 : /* clear the returned printer handle. Observed behavior
1975 : from Win2k server. Don't think this really matters.
1976 : Previous code just copied the value of the closed
1977 : handle. --jerry */
1978 :
1979 620 : ZERO_STRUCTP(r->out.handle);
1980 :
1981 620 : return WERR_OK;
1982 : }
1983 :
1984 : /****************************************************************
1985 : _spoolss_DeletePrinter
1986 : ****************************************************************/
1987 :
1988 16 : WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1989 : struct spoolss_DeletePrinter *r)
1990 : {
1991 16 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1992 0 : WERROR result;
1993 0 : int snum;
1994 :
1995 16 : if (Printer && Printer->document_started) {
1996 0 : struct spoolss_EndDocPrinter e;
1997 :
1998 0 : e.in.handle = r->in.handle;
1999 :
2000 0 : _spoolss_EndDocPrinter(p, &e);
2001 : }
2002 :
2003 16 : if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2004 16 : winreg_delete_printer_key_internal(p->mem_ctx,
2005 : get_session_info_system(),
2006 : p->msg_ctx,
2007 : lp_const_servicename(snum),
2008 : "");
2009 : }
2010 :
2011 16 : result = delete_printer_handle(p, r->in.handle);
2012 :
2013 16 : return result;
2014 : }
2015 :
2016 : /*******************************************************************
2017 : * static function to lookup the version id corresponding to an
2018 : * long architecture string
2019 : ******************************************************************/
2020 :
2021 : static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2022 : SPOOLSS_DRIVER_VERSION_NT35,
2023 : SPOOLSS_DRIVER_VERSION_NT4,
2024 : SPOOLSS_DRIVER_VERSION_200X,
2025 : -1};
2026 :
2027 0 : static int get_version_id(const char *arch)
2028 : {
2029 0 : int i;
2030 :
2031 0 : for (i=0; archi_table[i].long_archi != NULL; i++)
2032 : {
2033 0 : if (strcmp(arch, archi_table[i].long_archi) == 0)
2034 0 : return (archi_table[i].version);
2035 : }
2036 :
2037 0 : return -1;
2038 : }
2039 :
2040 : /****************************************************************
2041 : _spoolss_DeletePrinterDriver
2042 : ****************************************************************/
2043 :
2044 0 : WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2045 : struct spoolss_DeletePrinterDriver *r)
2046 : {
2047 :
2048 0 : struct dcesrv_call_state *dce_call = p->dce_call;
2049 0 : struct auth_session_info *session_info =
2050 0 : dcesrv_call_session_info(dce_call);
2051 0 : struct spoolss_DriverInfo8 *info = NULL;
2052 0 : int version;
2053 0 : WERROR status;
2054 0 : struct dcerpc_binding_handle *b;
2055 0 : TALLOC_CTX *tmp_ctx = NULL;
2056 0 : int i;
2057 0 : bool found;
2058 :
2059 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2060 : and not a printer admin, then fail */
2061 :
2062 0 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
2063 0 : !security_token_has_privilege(session_info->security_token,
2064 : SEC_PRIV_PRINT_OPERATOR)) {
2065 0 : return WERR_ACCESS_DENIED;
2066 : }
2067 :
2068 0 : if (r->in.architecture == NULL || r->in.driver == NULL) {
2069 0 : return WERR_INVALID_ENVIRONMENT;
2070 : }
2071 :
2072 : /* check that we have a valid driver name first */
2073 :
2074 0 : if ((version = get_version_id(r->in.architecture)) == -1) {
2075 0 : return WERR_INVALID_ENVIRONMENT;
2076 : }
2077 :
2078 0 : tmp_ctx = talloc_new(p->mem_ctx);
2079 0 : if (!tmp_ctx) {
2080 0 : return WERR_NOT_ENOUGH_MEMORY;
2081 : }
2082 :
2083 0 : status = winreg_printer_binding_handle(tmp_ctx,
2084 : get_session_info_system(),
2085 : p->msg_ctx,
2086 : &b);
2087 0 : if (!W_ERROR_IS_OK(status)) {
2088 0 : goto done;
2089 : }
2090 :
2091 0 : for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2092 0 : status = winreg_get_driver(tmp_ctx, b,
2093 : r->in.architecture, r->in.driver,
2094 0 : drv_cversion[i], &info);
2095 0 : if (!W_ERROR_IS_OK(status)) {
2096 0 : DEBUG(5, ("skipping del of driver with version %d\n",
2097 : drv_cversion[i]));
2098 0 : continue;
2099 : }
2100 0 : found = true;
2101 :
2102 0 : if (printer_driver_in_use(tmp_ctx, b, info)) {
2103 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2104 0 : goto done;
2105 : }
2106 :
2107 0 : status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2108 0 : if (!W_ERROR_IS_OK(status)) {
2109 0 : DEBUG(0, ("failed del of driver with version %d\n",
2110 : drv_cversion[i]));
2111 0 : goto done;
2112 : }
2113 : }
2114 0 : if (found == false) {
2115 0 : DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2116 0 : status = WERR_UNKNOWN_PRINTER_DRIVER;
2117 : } else {
2118 0 : status = WERR_OK;
2119 : }
2120 :
2121 0 : done:
2122 0 : talloc_free(tmp_ctx);
2123 :
2124 0 : return status;
2125 : }
2126 :
2127 0 : static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2128 : struct pipes_struct *p,
2129 : struct spoolss_DeletePrinterDriverEx *r,
2130 : struct dcerpc_binding_handle *b,
2131 : struct spoolss_DriverInfo8 *info)
2132 : {
2133 0 : struct dcesrv_call_state *dce_call = p->dce_call;
2134 0 : struct auth_session_info *session_info =
2135 0 : dcesrv_call_session_info(dce_call);
2136 0 : WERROR status;
2137 0 : bool delete_files;
2138 :
2139 0 : if (printer_driver_in_use(mem_ctx, b, info)) {
2140 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2141 0 : goto done;
2142 : }
2143 :
2144 : /*
2145 : * we have a couple of cases to consider.
2146 : * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2147 : * then the delete should fail if **any** files overlap with
2148 : * other drivers
2149 : * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2150 : * non-overlapping files
2151 : * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2152 : * are set, then do not delete any files
2153 : * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2154 : */
2155 :
2156 0 : delete_files = r->in.delete_flags
2157 0 : & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2158 :
2159 :
2160 0 : if (delete_files) {
2161 0 : bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2162 0 : if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2163 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2164 0 : goto done;
2165 : }
2166 : /*
2167 : * printer_driver_files_in_use() has trimmed overlapping files
2168 : * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2169 : */
2170 : }
2171 :
2172 :
2173 0 : status = winreg_del_driver(mem_ctx, b, info, info->version);
2174 0 : if (!W_ERROR_IS_OK(status)) {
2175 0 : goto done;
2176 : }
2177 :
2178 : /*
2179 : * now delete any associated files if delete_files is
2180 : * true. Even if this part fails, we return success
2181 : * because the driver does not exist any more
2182 : */
2183 0 : if (delete_files) {
2184 0 : delete_driver_files(session_info, info);
2185 : }
2186 :
2187 0 : done:
2188 0 : return status;
2189 : }
2190 :
2191 : /****************************************************************
2192 : _spoolss_DeletePrinterDriverEx
2193 : ****************************************************************/
2194 :
2195 0 : WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2196 : struct spoolss_DeletePrinterDriverEx *r)
2197 : {
2198 0 : struct dcesrv_call_state *dce_call = p->dce_call;
2199 0 : struct auth_session_info *session_info =
2200 0 : dcesrv_call_session_info(dce_call);
2201 0 : struct spoolss_DriverInfo8 *info = NULL;
2202 0 : WERROR status;
2203 0 : struct dcerpc_binding_handle *b;
2204 0 : TALLOC_CTX *tmp_ctx = NULL;
2205 0 : int i;
2206 0 : bool found;
2207 :
2208 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2209 : and not a printer admin, then fail */
2210 :
2211 0 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
2212 0 : !security_token_has_privilege(session_info->security_token,
2213 : SEC_PRIV_PRINT_OPERATOR)) {
2214 0 : return WERR_ACCESS_DENIED;
2215 : }
2216 :
2217 0 : if (r->in.architecture == NULL || r->in.driver == NULL) {
2218 0 : return WERR_INVALID_ENVIRONMENT;
2219 : }
2220 :
2221 : /* check that we have a valid driver name first */
2222 0 : if (get_version_id(r->in.architecture) == -1) {
2223 : /* this is what NT returns */
2224 0 : return WERR_INVALID_ENVIRONMENT;
2225 : }
2226 :
2227 0 : tmp_ctx = talloc_new(p->mem_ctx);
2228 0 : if (!tmp_ctx) {
2229 0 : return WERR_NOT_ENOUGH_MEMORY;
2230 : }
2231 :
2232 0 : status = winreg_printer_binding_handle(tmp_ctx,
2233 : get_session_info_system(),
2234 : p->msg_ctx,
2235 : &b);
2236 0 : if (!W_ERROR_IS_OK(status)) {
2237 0 : goto done;
2238 : }
2239 :
2240 0 : for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2241 0 : if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2242 0 : && (drv_cversion[i] != r->in.version)) {
2243 0 : continue;
2244 : }
2245 :
2246 : /* check if a driver with this version exists before delete */
2247 0 : status = winreg_get_driver(tmp_ctx, b,
2248 : r->in.architecture, r->in.driver,
2249 0 : drv_cversion[i], &info);
2250 0 : if (!W_ERROR_IS_OK(status)) {
2251 0 : DEBUG(5, ("skipping del of driver with version %d\n",
2252 : drv_cversion[i]));
2253 0 : continue;
2254 : }
2255 0 : found = true;
2256 :
2257 0 : status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2258 0 : if (!W_ERROR_IS_OK(status)) {
2259 0 : DEBUG(0, ("failed to delete driver with version %d\n",
2260 : drv_cversion[i]));
2261 0 : goto done;
2262 : }
2263 : }
2264 0 : if (found == false) {
2265 0 : DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2266 0 : status = WERR_UNKNOWN_PRINTER_DRIVER;
2267 : } else {
2268 0 : status = WERR_OK;
2269 : }
2270 :
2271 0 : done:
2272 0 : talloc_free(tmp_ctx);
2273 0 : return status;
2274 : }
2275 :
2276 :
2277 : /********************************************************************
2278 : GetPrinterData on a printer server Handle.
2279 : ********************************************************************/
2280 :
2281 404 : static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2282 : const char *value,
2283 : enum winreg_Type *type,
2284 : union spoolss_PrinterData *data)
2285 : {
2286 404 : DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2287 :
2288 404 : if (!strcasecmp_m(value, "W3SvcInstalled")) {
2289 28 : *type = REG_DWORD;
2290 28 : SIVAL(&data->value, 0, 0x00);
2291 28 : return WERR_OK;
2292 : }
2293 :
2294 376 : if (!strcasecmp_m(value, "BeepEnabled")) {
2295 24 : *type = REG_DWORD;
2296 24 : SIVAL(&data->value, 0, 0x00);
2297 24 : return WERR_OK;
2298 : }
2299 :
2300 352 : if (!strcasecmp_m(value, "EventLog")) {
2301 24 : *type = REG_DWORD;
2302 : /* formally was 0x1b */
2303 24 : SIVAL(&data->value, 0, 0x00);
2304 24 : return WERR_OK;
2305 : }
2306 :
2307 328 : if (!strcasecmp_m(value, "NetPopup")) {
2308 0 : *type = REG_DWORD;
2309 0 : SIVAL(&data->value, 0, 0x00);
2310 0 : return WERR_OK;
2311 : }
2312 :
2313 328 : if (!strcasecmp_m(value, "MajorVersion")) {
2314 28 : *type = REG_DWORD;
2315 :
2316 : /* Windows NT 4.0 seems to not allow uploading of drivers
2317 : to a server that reports 0x3 as the MajorVersion.
2318 : need to investigate more how Win2k gets around this .
2319 : -- jerry */
2320 :
2321 28 : if (RA_WINNT == get_remote_arch()) {
2322 0 : SIVAL(&data->value, 0, 0x02);
2323 : } else {
2324 28 : SIVAL(&data->value, 0, 0x03);
2325 : }
2326 :
2327 28 : return WERR_OK;
2328 : }
2329 :
2330 300 : if (!strcasecmp_m(value, "MinorVersion")) {
2331 24 : *type = REG_DWORD;
2332 24 : SIVAL(&data->value, 0, 0x00);
2333 24 : return WERR_OK;
2334 : }
2335 :
2336 : /* REG_BINARY
2337 : * uint32_t size = 0x114
2338 : * uint32_t major = 5
2339 : * uint32_t minor = [0|1]
2340 : * uint32_t build = [2195|2600]
2341 : * extra unicode string = e.g. "Service Pack 3"
2342 : */
2343 276 : if (!strcasecmp_m(value, "OSVersion")) {
2344 0 : DATA_BLOB blob;
2345 0 : enum ndr_err_code ndr_err;
2346 0 : struct spoolss_OSVersion os;
2347 :
2348 : /*
2349 : * Set the default OSVersion to:
2350 : *
2351 : * Windows Server 2003R2 SP2 (5.2.3790)
2352 : *
2353 : * used to be Windows 2000 (5.0.2195)
2354 : */
2355 40 : os.major = lp_parm_int(GLOBAL_SECTION_SNUM,
2356 : "spoolss", "os_major",
2357 : GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
2358 40 : os.minor = lp_parm_int(GLOBAL_SECTION_SNUM,
2359 : "spoolss", "os_minor",
2360 : GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
2361 40 : os.build = lp_parm_int(GLOBAL_SECTION_SNUM,
2362 : "spoolss", "os_build",
2363 : GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
2364 40 : os.extra_string = ""; /* leave extra string empty */
2365 :
2366 40 : ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2367 : (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2368 40 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2369 0 : return WERR_GEN_FAILURE;
2370 : }
2371 :
2372 40 : if (DEBUGLEVEL >= 10) {
2373 0 : NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2374 : }
2375 :
2376 40 : *type = REG_BINARY;
2377 40 : data->binary = blob;
2378 :
2379 40 : return WERR_OK;
2380 : }
2381 :
2382 :
2383 236 : if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2384 24 : *type = REG_SZ;
2385 :
2386 24 : data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
2387 24 : W_ERROR_HAVE_NO_MEMORY(data->string);
2388 :
2389 24 : return WERR_OK;
2390 : }
2391 :
2392 212 : if (!strcasecmp_m(value, "Architecture")) {
2393 160 : *type = REG_SZ;
2394 160 : data->string = talloc_strdup(mem_ctx,
2395 : lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
2396 160 : W_ERROR_HAVE_NO_MEMORY(data->string);
2397 :
2398 160 : return WERR_OK;
2399 : }
2400 :
2401 52 : if (!strcasecmp_m(value, "DsPresent")) {
2402 24 : *type = REG_DWORD;
2403 :
2404 : /* only show the publish check box if we are a
2405 : member of a AD domain */
2406 :
2407 24 : if (lp_security() == SEC_ADS) {
2408 0 : SIVAL(&data->value, 0, 0x01);
2409 : } else {
2410 24 : SIVAL(&data->value, 0, 0x00);
2411 : }
2412 24 : return WERR_OK;
2413 : }
2414 :
2415 28 : if (!strcasecmp_m(value, "DNSMachineName")) {
2416 24 : const char *hostname = get_mydnsfullname();
2417 :
2418 24 : if (!hostname) {
2419 0 : return WERR_FILE_NOT_FOUND;
2420 : }
2421 :
2422 24 : *type = REG_SZ;
2423 24 : data->string = talloc_strdup(mem_ctx, hostname);
2424 24 : W_ERROR_HAVE_NO_MEMORY(data->string);
2425 :
2426 24 : return WERR_OK;
2427 : }
2428 :
2429 4 : *type = REG_NONE;
2430 :
2431 4 : return WERR_INVALID_PARAMETER;
2432 : }
2433 :
2434 : /****************************************************************
2435 : _spoolss_GetPrinterData
2436 : ****************************************************************/
2437 :
2438 480 : WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2439 : struct spoolss_GetPrinterData *r)
2440 : {
2441 0 : struct spoolss_GetPrinterDataEx r2;
2442 :
2443 480 : r2.in.handle = r->in.handle;
2444 480 : r2.in.key_name = "PrinterDriverData";
2445 480 : r2.in.value_name = r->in.value_name;
2446 480 : r2.in.offered = r->in.offered;
2447 480 : r2.out.type = r->out.type;
2448 480 : r2.out.data = r->out.data;
2449 480 : r2.out.needed = r->out.needed;
2450 :
2451 480 : return _spoolss_GetPrinterDataEx(p, &r2);
2452 : }
2453 :
2454 : /*********************************************************
2455 : Connect to the client machine.
2456 : **********************************************************/
2457 :
2458 2 : static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2459 : struct sockaddr_storage *client_ss, const char *remote_machine)
2460 : {
2461 0 : NTSTATUS ret;
2462 0 : struct sockaddr_storage rm_addr;
2463 0 : char addr[INET6_ADDRSTRLEN];
2464 2 : struct cli_credentials *anon_creds = NULL;
2465 :
2466 2 : if ( is_zero_addr(client_ss) ) {
2467 0 : DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2468 : remote_machine));
2469 0 : if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2470 0 : DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2471 0 : return false;
2472 : }
2473 0 : print_sockaddr(addr, sizeof(addr), &rm_addr);
2474 : } else {
2475 2 : rm_addr = *client_ss;
2476 2 : print_sockaddr(addr, sizeof(addr), &rm_addr);
2477 2 : DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2478 : addr));
2479 : }
2480 :
2481 2 : if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2482 0 : DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2483 : addr));
2484 0 : return false;
2485 : }
2486 :
2487 2 : anon_creds = cli_credentials_init_anon(NULL);
2488 2 : if (anon_creds == NULL) {
2489 0 : DBG_ERR("cli_credentials_init_anon() failed\n");
2490 0 : return false;
2491 : }
2492 :
2493 : /* setup the connection */
2494 2 : ret = cli_full_connection_creds(NULL,
2495 : pp_cli,
2496 : lp_netbios_name(),
2497 : remote_machine,
2498 : &rm_addr,
2499 : 0,
2500 : "IPC$",
2501 : "IPC",
2502 : anon_creds,
2503 : CLI_FULL_CONNECTION_IPC);
2504 2 : TALLOC_FREE(anon_creds);
2505 2 : if ( !NT_STATUS_IS_OK( ret ) ) {
2506 0 : DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2507 : remote_machine ));
2508 0 : return false;
2509 : }
2510 :
2511 2 : if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
2512 0 : DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2513 0 : cli_shutdown(*pp_cli);
2514 0 : return false;
2515 : }
2516 :
2517 : /*
2518 : * Ok - we have an anonymous connection to the IPC$ share.
2519 : * Now start the NT Domain stuff :-).
2520 : */
2521 :
2522 2 : ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2523 2 : if (!NT_STATUS_IS_OK(ret)) {
2524 0 : DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2525 : remote_machine, nt_errstr(ret)));
2526 0 : cli_shutdown(*pp_cli);
2527 0 : return false;
2528 : }
2529 :
2530 2 : return true;
2531 : }
2532 :
2533 : /***************************************************************************
2534 : Connect to the client.
2535 : ****************************************************************************/
2536 :
2537 2 : static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2538 : uint32_t localprinter,
2539 : enum winreg_Type type,
2540 : struct policy_handle *handle,
2541 : struct notify_back_channel **_chan,
2542 : struct sockaddr_storage *client_ss,
2543 : struct messaging_context *msg_ctx)
2544 : {
2545 0 : WERROR result;
2546 0 : NTSTATUS status;
2547 0 : struct notify_back_channel *chan;
2548 :
2549 2 : for (chan = back_channels; chan; chan = chan->next) {
2550 0 : if (memcmp(&chan->client_address, client_ss,
2551 : sizeof(struct sockaddr_storage)) == 0) {
2552 0 : break;
2553 : }
2554 : }
2555 :
2556 : /*
2557 : * If it's the first connection, contact the client
2558 : * and connect to the IPC$ share anonymously
2559 : */
2560 2 : if (!chan) {
2561 0 : fstring unix_printer;
2562 :
2563 : /* the +2 is to strip the leading 2 backslashes */
2564 2 : fstrcpy(unix_printer, printer + 2);
2565 :
2566 2 : chan = talloc_zero(NULL, struct notify_back_channel);
2567 2 : if (!chan) {
2568 0 : return false;
2569 : }
2570 2 : chan->client_address = *client_ss;
2571 :
2572 2 : if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2573 0 : TALLOC_FREE(chan);
2574 0 : return false;
2575 : }
2576 :
2577 2 : DLIST_ADD(back_channels, chan);
2578 :
2579 2 : messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2580 : receive_notify2_message_list);
2581 : }
2582 :
2583 2 : if (chan->cli_pipe == NULL ||
2584 2 : chan->cli_pipe->binding_handle == NULL) {
2585 0 : DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2586 : "NULL %s for printer %s\n",
2587 : chan->cli_pipe == NULL ?
2588 : "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2589 : printer));
2590 0 : return false;
2591 : }
2592 :
2593 : /*
2594 : * Tell the specific printing tdb we want messages for this printer
2595 : * by registering our PID.
2596 : */
2597 :
2598 2 : if (!print_notify_register_pid(snum)) {
2599 0 : DEBUG(0, ("Failed to register our pid for printer %s\n",
2600 : printer));
2601 : }
2602 :
2603 2 : status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2604 : talloc_tos(),
2605 : printer,
2606 : localprinter,
2607 : type,
2608 : 0,
2609 : NULL,
2610 : handle,
2611 : &result);
2612 2 : if (!NT_STATUS_IS_OK(status)) {
2613 0 : DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2614 0 : result = ntstatus_to_werror(status);
2615 2 : } else if (!W_ERROR_IS_OK(result)) {
2616 0 : DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2617 : }
2618 :
2619 2 : chan->active_connections++;
2620 2 : *_chan = chan;
2621 :
2622 2 : return (W_ERROR_IS_OK(result));
2623 : }
2624 :
2625 : /****************************************************************
2626 : ****************************************************************/
2627 :
2628 2 : static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2629 : const struct spoolss_NotifyOption *r)
2630 : {
2631 0 : struct spoolss_NotifyOption *option;
2632 0 : uint32_t i,k;
2633 :
2634 2 : if (!r) {
2635 0 : return NULL;
2636 : }
2637 :
2638 2 : option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2639 2 : if (!option) {
2640 0 : return NULL;
2641 : }
2642 :
2643 2 : *option = *r;
2644 :
2645 2 : if (!option->count) {
2646 0 : return option;
2647 : }
2648 :
2649 2 : option->types = talloc_zero_array(option,
2650 : struct spoolss_NotifyOptionType, option->count);
2651 2 : if (!option->types) {
2652 0 : talloc_free(option);
2653 0 : return NULL;
2654 : }
2655 :
2656 6 : for (i=0; i < option->count; i++) {
2657 4 : option->types[i] = r->types[i];
2658 :
2659 4 : if (option->types[i].count) {
2660 4 : option->types[i].fields = talloc_zero_array(option,
2661 : union spoolss_Field, option->types[i].count);
2662 4 : if (!option->types[i].fields) {
2663 0 : talloc_free(option);
2664 0 : return NULL;
2665 : }
2666 8 : for (k=0; k<option->types[i].count; k++) {
2667 4 : option->types[i].fields[k] =
2668 4 : r->types[i].fields[k];
2669 : }
2670 : }
2671 : }
2672 :
2673 2 : return option;
2674 : }
2675 :
2676 : /****************************************************************
2677 : * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2678 : *
2679 : * before replying OK: status=0 a rpc call is made to the workstation
2680 : * asking ReplyOpenPrinter
2681 : *
2682 : * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2683 : * called from api_spoolss_rffpcnex
2684 : ****************************************************************/
2685 :
2686 2 : WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2687 : struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2688 : {
2689 2 : struct dcesrv_call_state *dce_call = p->dce_call;
2690 2 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
2691 0 : const struct tsocket_address *remote_address =
2692 2 : dcesrv_connection_get_remote_address(dcesrv_conn);
2693 2 : int snum = -1;
2694 2 : struct spoolss_NotifyOption *option = r->in.notify_options;
2695 0 : struct sockaddr_storage client_ss;
2696 0 : ssize_t client_len;
2697 :
2698 : /* store the notify value in the printer struct */
2699 :
2700 2 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2701 :
2702 2 : if (!Printer) {
2703 0 : DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2704 : "Invalid handle (%s:%u:%u).\n",
2705 : OUR_HANDLE(r->in.handle)));
2706 0 : return WERR_INVALID_HANDLE;
2707 : }
2708 :
2709 2 : Printer->notify.flags = r->in.flags;
2710 2 : Printer->notify.options = r->in.options;
2711 2 : Printer->notify.printerlocal = r->in.printer_local;
2712 2 : Printer->notify.msg_ctx = p->msg_ctx;
2713 :
2714 2 : TALLOC_FREE(Printer->notify.option);
2715 2 : Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2716 :
2717 2 : fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2718 :
2719 : /* Connect to the client machine and send a ReplyOpenPrinter */
2720 :
2721 2 : if ( Printer->printer_type == SPLHND_SERVER)
2722 2 : snum = -1;
2723 0 : else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2724 0 : !get_printer_snum(p, r->in.handle, &snum, NULL) )
2725 0 : return WERR_INVALID_HANDLE;
2726 :
2727 2 : DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2728 : "remote_address is %s\n",
2729 : tsocket_address_string(remote_address, p->mem_ctx)));
2730 :
2731 2 : if (!lp_print_notify_backchannel(snum)) {
2732 0 : DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2733 : "backchannel disabled\n"));
2734 0 : return WERR_RPC_S_SERVER_UNAVAILABLE;
2735 : }
2736 :
2737 2 : client_len = tsocket_address_bsd_sockaddr(remote_address,
2738 : (struct sockaddr *) &client_ss,
2739 : sizeof(struct sockaddr_storage));
2740 2 : if (client_len < 0) {
2741 0 : return WERR_NOT_ENOUGH_MEMORY;
2742 : }
2743 :
2744 2 : if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2745 : Printer->notify.printerlocal, REG_SZ,
2746 : &Printer->notify.cli_hnd,
2747 : &Printer->notify.cli_chan,
2748 : &client_ss, p->msg_ctx)) {
2749 0 : return WERR_RPC_S_SERVER_UNAVAILABLE;
2750 : }
2751 :
2752 2 : return WERR_OK;
2753 : }
2754 :
2755 : /*******************************************************************
2756 : * fill a notify_info_data with the servername
2757 : ********************************************************************/
2758 :
2759 0 : static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2760 : int snum,
2761 : struct spoolss_Notify *data,
2762 : print_queue_struct *queue,
2763 : struct spoolss_PrinterInfo2 *pinfo2,
2764 : TALLOC_CTX *mem_ctx)
2765 : {
2766 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2767 0 : }
2768 :
2769 : /*******************************************************************
2770 : * fill a notify_info_data with the printername (not including the servername).
2771 : ********************************************************************/
2772 :
2773 0 : static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2774 : int snum,
2775 : struct spoolss_Notify *data,
2776 : print_queue_struct *queue,
2777 : struct spoolss_PrinterInfo2 *pinfo2,
2778 : TALLOC_CTX *mem_ctx)
2779 : {
2780 : /* the notify name should not contain the \\server\ part */
2781 0 : const char *p = strrchr(pinfo2->printername, '\\');
2782 :
2783 0 : if (!p) {
2784 0 : p = pinfo2->printername;
2785 : } else {
2786 0 : p++;
2787 : }
2788 :
2789 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2790 0 : }
2791 :
2792 : /*******************************************************************
2793 : * fill a notify_info_data with the servicename
2794 : ********************************************************************/
2795 :
2796 0 : static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2797 : int snum,
2798 : struct spoolss_Notify *data,
2799 : print_queue_struct *queue,
2800 : struct spoolss_PrinterInfo2 *pinfo2,
2801 : TALLOC_CTX *mem_ctx)
2802 : {
2803 0 : const struct loadparm_substitution *lp_sub =
2804 0 : loadparm_s3_global_substitution();
2805 :
2806 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), lp_sub, snum));
2807 0 : }
2808 :
2809 : /*******************************************************************
2810 : * fill a notify_info_data with the port name
2811 : ********************************************************************/
2812 :
2813 0 : static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2814 : int snum,
2815 : struct spoolss_Notify *data,
2816 : print_queue_struct *queue,
2817 : struct spoolss_PrinterInfo2 *pinfo2,
2818 : TALLOC_CTX *mem_ctx)
2819 : {
2820 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2821 0 : }
2822 :
2823 : /*******************************************************************
2824 : * fill a notify_info_data with the printername
2825 : * but it doesn't exist, have to see what to do
2826 : ********************************************************************/
2827 :
2828 0 : static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2829 : int snum,
2830 : struct spoolss_Notify *data,
2831 : print_queue_struct *queue,
2832 : struct spoolss_PrinterInfo2 *pinfo2,
2833 : TALLOC_CTX *mem_ctx)
2834 : {
2835 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2836 0 : }
2837 :
2838 : /*******************************************************************
2839 : * fill a notify_info_data with the comment
2840 : ********************************************************************/
2841 :
2842 0 : static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2843 : int snum,
2844 : struct spoolss_Notify *data,
2845 : print_queue_struct *queue,
2846 : struct spoolss_PrinterInfo2 *pinfo2,
2847 : TALLOC_CTX *mem_ctx)
2848 : {
2849 0 : const struct loadparm_substitution *lp_sub =
2850 0 : loadparm_s3_global_substitution();
2851 0 : const char *p;
2852 :
2853 0 : if (*pinfo2->comment == '\0') {
2854 0 : p = lp_comment(talloc_tos(), lp_sub, snum);
2855 : } else {
2856 0 : p = pinfo2->comment;
2857 : }
2858 :
2859 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2860 0 : }
2861 :
2862 : /*******************************************************************
2863 : * fill a notify_info_data with the comment
2864 : * location = "Room 1, floor 2, building 3"
2865 : ********************************************************************/
2866 :
2867 0 : static void spoolss_notify_location(struct messaging_context *msg_ctx,
2868 : int snum,
2869 : struct spoolss_Notify *data,
2870 : print_queue_struct *queue,
2871 : struct spoolss_PrinterInfo2 *pinfo2,
2872 : TALLOC_CTX *mem_ctx)
2873 : {
2874 0 : const char *loc = pinfo2->location;
2875 0 : NTSTATUS status;
2876 :
2877 0 : status = printer_list_get_printer(mem_ctx,
2878 : pinfo2->sharename,
2879 : NULL,
2880 : &loc,
2881 : NULL);
2882 0 : if (NT_STATUS_IS_OK(status)) {
2883 0 : if (loc == NULL) {
2884 0 : loc = pinfo2->location;
2885 : }
2886 : }
2887 :
2888 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2889 0 : }
2890 :
2891 : /*******************************************************************
2892 : * fill a notify_info_data with the device mode
2893 : * jfm:xxxx don't to it for know but that's a real problem !!!
2894 : ********************************************************************/
2895 :
2896 0 : static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2897 : int snum,
2898 : struct spoolss_Notify *data,
2899 : print_queue_struct *queue,
2900 : struct spoolss_PrinterInfo2 *pinfo2,
2901 : TALLOC_CTX *mem_ctx)
2902 : {
2903 : /* for a dummy implementation we have to zero the fields */
2904 0 : SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2905 0 : }
2906 :
2907 : /*******************************************************************
2908 : * fill a notify_info_data with the separator file name
2909 : ********************************************************************/
2910 :
2911 0 : static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2912 : int snum,
2913 : struct spoolss_Notify *data,
2914 : print_queue_struct *queue,
2915 : struct spoolss_PrinterInfo2 *pinfo2,
2916 : TALLOC_CTX *mem_ctx)
2917 : {
2918 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2919 0 : }
2920 :
2921 : /*******************************************************************
2922 : * fill a notify_info_data with the print processor
2923 : * jfm:xxxx return always winprint to indicate we don't do anything to it
2924 : ********************************************************************/
2925 :
2926 0 : static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2927 : int snum,
2928 : struct spoolss_Notify *data,
2929 : print_queue_struct *queue,
2930 : struct spoolss_PrinterInfo2 *pinfo2,
2931 : TALLOC_CTX *mem_ctx)
2932 : {
2933 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2934 0 : }
2935 :
2936 : /*******************************************************************
2937 : * fill a notify_info_data with the print processor options
2938 : * jfm:xxxx send an empty string
2939 : ********************************************************************/
2940 :
2941 0 : static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2942 : int snum,
2943 : struct spoolss_Notify *data,
2944 : print_queue_struct *queue,
2945 : struct spoolss_PrinterInfo2 *pinfo2,
2946 : TALLOC_CTX *mem_ctx)
2947 : {
2948 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2949 0 : }
2950 :
2951 : /*******************************************************************
2952 : * fill a notify_info_data with the data type
2953 : * jfm:xxxx always send RAW as data type
2954 : ********************************************************************/
2955 :
2956 0 : static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2957 : int snum,
2958 : struct spoolss_Notify *data,
2959 : print_queue_struct *queue,
2960 : struct spoolss_PrinterInfo2 *pinfo2,
2961 : TALLOC_CTX *mem_ctx)
2962 : {
2963 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2964 0 : }
2965 :
2966 : /*******************************************************************
2967 : * fill a notify_info_data with the security descriptor
2968 : * jfm:xxxx send an null pointer to say no security desc
2969 : * have to implement security before !
2970 : ********************************************************************/
2971 :
2972 0 : static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2973 : int snum,
2974 : struct spoolss_Notify *data,
2975 : print_queue_struct *queue,
2976 : struct spoolss_PrinterInfo2 *pinfo2,
2977 : TALLOC_CTX *mem_ctx)
2978 : {
2979 0 : if (pinfo2->secdesc == NULL) {
2980 0 : data->data.sd.sd = NULL;
2981 : } else {
2982 0 : data->data.sd.sd = security_descriptor_copy(mem_ctx,
2983 0 : pinfo2->secdesc);
2984 : }
2985 0 : data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2986 : 0);
2987 0 : }
2988 :
2989 : /*******************************************************************
2990 : * fill a notify_info_data with the attributes
2991 : * jfm:xxxx a samba printer is always shared
2992 : ********************************************************************/
2993 :
2994 0 : static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2995 : int snum,
2996 : struct spoolss_Notify *data,
2997 : print_queue_struct *queue,
2998 : struct spoolss_PrinterInfo2 *pinfo2,
2999 : TALLOC_CTX *mem_ctx)
3000 : {
3001 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3002 0 : }
3003 :
3004 : /*******************************************************************
3005 : * fill a notify_info_data with the priority
3006 : ********************************************************************/
3007 :
3008 0 : static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3009 : int snum,
3010 : struct spoolss_Notify *data,
3011 : print_queue_struct *queue,
3012 : struct spoolss_PrinterInfo2 *pinfo2,
3013 : TALLOC_CTX *mem_ctx)
3014 : {
3015 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3016 0 : }
3017 :
3018 : /*******************************************************************
3019 : * fill a notify_info_data with the default priority
3020 : ********************************************************************/
3021 :
3022 0 : static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3023 : int snum,
3024 : struct spoolss_Notify *data,
3025 : print_queue_struct *queue,
3026 : struct spoolss_PrinterInfo2 *pinfo2,
3027 : TALLOC_CTX *mem_ctx)
3028 : {
3029 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3030 0 : }
3031 :
3032 : /*******************************************************************
3033 : * fill a notify_info_data with the start time
3034 : ********************************************************************/
3035 :
3036 0 : static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3037 : int snum,
3038 : struct spoolss_Notify *data,
3039 : print_queue_struct *queue,
3040 : struct spoolss_PrinterInfo2 *pinfo2,
3041 : TALLOC_CTX *mem_ctx)
3042 : {
3043 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3044 0 : }
3045 :
3046 : /*******************************************************************
3047 : * fill a notify_info_data with the until time
3048 : ********************************************************************/
3049 :
3050 0 : static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3051 : int snum,
3052 : struct spoolss_Notify *data,
3053 : print_queue_struct *queue,
3054 : struct spoolss_PrinterInfo2 *pinfo2,
3055 : TALLOC_CTX *mem_ctx)
3056 : {
3057 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3058 0 : }
3059 :
3060 : /*******************************************************************
3061 : * fill a notify_info_data with the status
3062 : ********************************************************************/
3063 :
3064 0 : static void spoolss_notify_status(struct messaging_context *msg_ctx,
3065 : int snum,
3066 : struct spoolss_Notify *data,
3067 : print_queue_struct *queue,
3068 : struct spoolss_PrinterInfo2 *pinfo2,
3069 : TALLOC_CTX *mem_ctx)
3070 : {
3071 0 : print_status_struct status;
3072 :
3073 0 : print_queue_length(msg_ctx, snum, &status);
3074 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3075 0 : }
3076 :
3077 : /*******************************************************************
3078 : * fill a notify_info_data with the number of jobs queued
3079 : ********************************************************************/
3080 :
3081 0 : static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3082 : int snum,
3083 : struct spoolss_Notify *data,
3084 : print_queue_struct *queue,
3085 : struct spoolss_PrinterInfo2 *pinfo2,
3086 : TALLOC_CTX *mem_ctx)
3087 : {
3088 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3089 0 : data, print_queue_length(msg_ctx, snum, NULL));
3090 0 : }
3091 :
3092 : /*******************************************************************
3093 : * fill a notify_info_data with the average ppm
3094 : ********************************************************************/
3095 :
3096 0 : static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3097 : int snum,
3098 : struct spoolss_Notify *data,
3099 : print_queue_struct *queue,
3100 : struct spoolss_PrinterInfo2 *pinfo2,
3101 : TALLOC_CTX *mem_ctx)
3102 : {
3103 : /* always respond 8 pages per minutes */
3104 : /* a little hard ! */
3105 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3106 0 : }
3107 :
3108 : /*******************************************************************
3109 : * fill a notify_info_data with username
3110 : ********************************************************************/
3111 :
3112 0 : static void spoolss_notify_username(struct messaging_context *msg_ctx,
3113 : int snum,
3114 : struct spoolss_Notify *data,
3115 : print_queue_struct *queue,
3116 : struct spoolss_PrinterInfo2 *pinfo2,
3117 : TALLOC_CTX *mem_ctx)
3118 : {
3119 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3120 0 : }
3121 :
3122 : /*******************************************************************
3123 : * fill a notify_info_data with job status
3124 : ********************************************************************/
3125 :
3126 0 : static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3127 : int snum,
3128 : struct spoolss_Notify *data,
3129 : print_queue_struct *queue,
3130 : struct spoolss_PrinterInfo2 *pinfo2,
3131 : TALLOC_CTX *mem_ctx)
3132 : {
3133 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3134 0 : }
3135 :
3136 : /*******************************************************************
3137 : * fill a notify_info_data with job name
3138 : ********************************************************************/
3139 :
3140 0 : static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3141 : int snum,
3142 : struct spoolss_Notify *data,
3143 : print_queue_struct *queue,
3144 : struct spoolss_PrinterInfo2 *pinfo2,
3145 : TALLOC_CTX *mem_ctx)
3146 : {
3147 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3148 0 : }
3149 :
3150 : /*******************************************************************
3151 : * fill a notify_info_data with job status
3152 : ********************************************************************/
3153 :
3154 0 : static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3155 : int snum,
3156 : struct spoolss_Notify *data,
3157 : print_queue_struct *queue,
3158 : struct spoolss_PrinterInfo2 *pinfo2,
3159 : TALLOC_CTX *mem_ctx)
3160 : {
3161 : /*
3162 : * Now we're returning job status codes we just return a "" here. JRA.
3163 : */
3164 :
3165 0 : const char *p = "";
3166 :
3167 : #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3168 : p = "unknown";
3169 :
3170 : switch (queue->status) {
3171 : case LPQ_QUEUED:
3172 : p = "Queued";
3173 : break;
3174 : case LPQ_PAUSED:
3175 : p = ""; /* NT provides the paused string */
3176 : break;
3177 : case LPQ_SPOOLING:
3178 : p = "Spooling";
3179 : break;
3180 : case LPQ_PRINTING:
3181 : p = "Printing";
3182 : break;
3183 : }
3184 : #endif /* NO LONGER NEEDED. */
3185 :
3186 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3187 0 : }
3188 :
3189 : /*******************************************************************
3190 : * fill a notify_info_data with job time
3191 : ********************************************************************/
3192 :
3193 0 : static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3194 : int snum,
3195 : struct spoolss_Notify *data,
3196 : print_queue_struct *queue,
3197 : struct spoolss_PrinterInfo2 *pinfo2,
3198 : TALLOC_CTX *mem_ctx)
3199 : {
3200 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3201 0 : }
3202 :
3203 : /*******************************************************************
3204 : * fill a notify_info_data with job size
3205 : ********************************************************************/
3206 :
3207 0 : static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3208 : int snum,
3209 : struct spoolss_Notify *data,
3210 : print_queue_struct *queue,
3211 : struct spoolss_PrinterInfo2 *pinfo2,
3212 : TALLOC_CTX *mem_ctx)
3213 : {
3214 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3215 0 : }
3216 :
3217 : /*******************************************************************
3218 : * fill a notify_info_data with page info
3219 : ********************************************************************/
3220 0 : static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3221 : int snum,
3222 : struct spoolss_Notify *data,
3223 : print_queue_struct *queue,
3224 : struct spoolss_PrinterInfo2 *pinfo2,
3225 : TALLOC_CTX *mem_ctx)
3226 : {
3227 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3228 0 : }
3229 :
3230 : /*******************************************************************
3231 : * fill a notify_info_data with pages printed info.
3232 : ********************************************************************/
3233 0 : static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3234 : int snum,
3235 : struct spoolss_Notify *data,
3236 : print_queue_struct *queue,
3237 : struct spoolss_PrinterInfo2 *pinfo2,
3238 : TALLOC_CTX *mem_ctx)
3239 : {
3240 : /* Add code when back-end tracks this */
3241 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3242 0 : }
3243 :
3244 : /*******************************************************************
3245 : Fill a notify_info_data with job position.
3246 : ********************************************************************/
3247 :
3248 0 : static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3249 : int snum,
3250 : struct spoolss_Notify *data,
3251 : print_queue_struct *queue,
3252 : struct spoolss_PrinterInfo2 *pinfo2,
3253 : TALLOC_CTX *mem_ctx)
3254 : {
3255 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3256 0 : }
3257 :
3258 : /*******************************************************************
3259 : Fill a notify_info_data with submitted time.
3260 : ********************************************************************/
3261 :
3262 0 : static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3263 : int snum,
3264 : struct spoolss_Notify *data,
3265 : print_queue_struct *queue,
3266 : struct spoolss_PrinterInfo2 *pinfo2,
3267 : TALLOC_CTX *mem_ctx)
3268 : {
3269 0 : data->data.string.string = NULL;
3270 0 : data->data.string.size = 0;
3271 :
3272 0 : init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3273 : &data->data.string.string,
3274 : &data->data.string.size);
3275 :
3276 0 : }
3277 :
3278 : struct s_notify_info_data_table
3279 : {
3280 : enum spoolss_NotifyType type;
3281 : uint16_t field;
3282 : const char *name;
3283 : enum spoolss_NotifyTable variable_type;
3284 : void (*fn) (struct messaging_context *msg_ctx,
3285 : int snum, struct spoolss_Notify *data,
3286 : print_queue_struct *queue,
3287 : struct spoolss_PrinterInfo2 *pinfo2,
3288 : TALLOC_CTX *mem_ctx);
3289 : };
3290 :
3291 : /* A table describing the various print notification constants and
3292 : whether the notification data is a pointer to a variable sized
3293 : buffer, a one value uint32_t or a two value uint32_t. */
3294 :
3295 : static const struct s_notify_info_data_table notify_info_data_table[] =
3296 : {
3297 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3298 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3299 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3300 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3301 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3302 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3303 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3304 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3305 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3306 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3307 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3308 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3309 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3310 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3311 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3312 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3313 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3314 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3315 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3316 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3317 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3318 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3319 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3320 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3321 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3322 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3323 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3324 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3325 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3326 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3327 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3328 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3329 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3330 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3331 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3332 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3333 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3334 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3335 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3336 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3337 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3338 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3339 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3340 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3341 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3342 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3343 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3344 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3345 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3346 : };
3347 :
3348 : /*******************************************************************
3349 : Return the variable_type of info_data structure.
3350 : ********************************************************************/
3351 :
3352 0 : static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3353 : uint16_t field)
3354 : {
3355 0 : int i=0;
3356 :
3357 0 : for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3358 0 : if ( (notify_info_data_table[i].type == type) &&
3359 0 : (notify_info_data_table[i].field == field) ) {
3360 0 : return notify_info_data_table[i].variable_type;
3361 : }
3362 : }
3363 :
3364 0 : DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3365 :
3366 0 : return (enum spoolss_NotifyTable) 0;
3367 : }
3368 :
3369 : /****************************************************************************
3370 : ****************************************************************************/
3371 :
3372 0 : static bool search_notify(enum spoolss_NotifyType type,
3373 : uint16_t field,
3374 : int *value)
3375 : {
3376 0 : int i;
3377 :
3378 0 : for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3379 0 : if (notify_info_data_table[i].type == type &&
3380 0 : notify_info_data_table[i].field == field &&
3381 0 : notify_info_data_table[i].fn != NULL) {
3382 0 : *value = i;
3383 0 : return true;
3384 : }
3385 : }
3386 :
3387 0 : return false;
3388 : }
3389 :
3390 : /****************************************************************************
3391 : ****************************************************************************/
3392 :
3393 0 : static void construct_info_data(struct spoolss_Notify *info_data,
3394 : enum spoolss_NotifyType type,
3395 : uint16_t field, int id)
3396 : {
3397 0 : info_data->type = type;
3398 0 : info_data->field.field = field;
3399 0 : info_data->variable_type = variable_type_of_notify_info_data(type, field);
3400 0 : info_data->job_id = id;
3401 0 : }
3402 :
3403 : /*******************************************************************
3404 : *
3405 : * fill a notify_info struct with info asked
3406 : *
3407 : ********************************************************************/
3408 :
3409 0 : static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3410 : struct printer_handle *print_hnd,
3411 : struct spoolss_NotifyInfo *info,
3412 : struct spoolss_PrinterInfo2 *pinfo2,
3413 : int snum,
3414 : const struct spoolss_NotifyOptionType *option_type,
3415 : uint32_t id,
3416 : TALLOC_CTX *mem_ctx)
3417 : {
3418 0 : const struct loadparm_substitution *lp_sub =
3419 0 : loadparm_s3_global_substitution();
3420 0 : int field_num,j;
3421 0 : enum spoolss_NotifyType type;
3422 0 : uint16_t field;
3423 :
3424 0 : struct spoolss_Notify *current_data;
3425 :
3426 0 : type = option_type->type;
3427 :
3428 0 : DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3429 : (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3430 : option_type->count, lp_servicename(talloc_tos(), lp_sub, snum)));
3431 :
3432 0 : for(field_num=0; field_num < option_type->count; field_num++) {
3433 0 : field = option_type->fields[field_num].field;
3434 :
3435 0 : DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3436 :
3437 0 : if (!search_notify(type, field, &j) )
3438 0 : continue;
3439 :
3440 0 : info->notifies = talloc_realloc(info, info->notifies,
3441 : struct spoolss_Notify,
3442 : info->count + 1);
3443 0 : if (info->notifies == NULL) {
3444 0 : DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3445 0 : return false;
3446 : }
3447 :
3448 0 : current_data = &info->notifies[info->count];
3449 :
3450 0 : construct_info_data(current_data, type, field, id);
3451 :
3452 0 : DEBUG(10, ("construct_notify_printer_info: "
3453 : "calling [%s] snum=%d printername=[%s])\n",
3454 : notify_info_data_table[j].name, snum,
3455 : pinfo2->printername));
3456 :
3457 0 : notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3458 : NULL, pinfo2, mem_ctx);
3459 :
3460 0 : info->count++;
3461 : }
3462 :
3463 0 : return true;
3464 : }
3465 :
3466 : /*******************************************************************
3467 : *
3468 : * fill a notify_info struct with info asked
3469 : *
3470 : ********************************************************************/
3471 :
3472 0 : static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3473 : print_queue_struct *queue,
3474 : struct spoolss_NotifyInfo *info,
3475 : struct spoolss_PrinterInfo2 *pinfo2,
3476 : int snum,
3477 : const struct spoolss_NotifyOptionType *option_type,
3478 : uint32_t id,
3479 : TALLOC_CTX *mem_ctx)
3480 : {
3481 0 : int field_num,j;
3482 0 : enum spoolss_NotifyType type;
3483 0 : uint16_t field;
3484 0 : struct spoolss_Notify *current_data;
3485 :
3486 0 : DEBUG(4,("construct_notify_jobs_info\n"));
3487 :
3488 0 : type = option_type->type;
3489 :
3490 0 : DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3491 : (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3492 : option_type->count));
3493 :
3494 0 : for(field_num=0; field_num<option_type->count; field_num++) {
3495 0 : field = option_type->fields[field_num].field;
3496 :
3497 0 : if (!search_notify(type, field, &j) )
3498 0 : continue;
3499 :
3500 0 : info->notifies = talloc_realloc(info, info->notifies,
3501 : struct spoolss_Notify,
3502 : info->count + 1);
3503 0 : if (info->notifies == NULL) {
3504 0 : DEBUG(2,("construct_notify_jobs_info: failed to enlarge buffer info->data!\n"));
3505 0 : return false;
3506 : }
3507 :
3508 0 : current_data=&(info->notifies[info->count]);
3509 :
3510 0 : construct_info_data(current_data, type, field, id);
3511 0 : notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3512 : queue, pinfo2, mem_ctx);
3513 0 : info->count++;
3514 : }
3515 :
3516 0 : return true;
3517 : }
3518 :
3519 : /*
3520 : * JFM: The enumeration is not that simple, it's even non obvious.
3521 : *
3522 : * let's take an example: I want to monitor the PRINTER SERVER for
3523 : * the printer's name and the number of jobs currently queued.
3524 : * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3525 : * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3526 : *
3527 : * I have 3 printers on the back of my server.
3528 : *
3529 : * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3530 : * structures.
3531 : * Number Data Id
3532 : * 1 printer 1 name 1
3533 : * 2 printer 1 cjob 1
3534 : * 3 printer 2 name 2
3535 : * 4 printer 2 cjob 2
3536 : * 5 printer 3 name 3
3537 : * 6 printer 3 name 3
3538 : *
3539 : * that's the print server case, the printer case is even worse.
3540 : */
3541 :
3542 : /*******************************************************************
3543 : *
3544 : * enumerate all printers on the printserver
3545 : * fill a notify_info struct with info asked
3546 : *
3547 : ********************************************************************/
3548 :
3549 4 : static WERROR printserver_notify_info(struct pipes_struct *p,
3550 : struct policy_handle *hnd,
3551 : struct spoolss_NotifyInfo *info,
3552 : TALLOC_CTX *mem_ctx)
3553 : {
3554 0 : const struct loadparm_substitution *lp_sub =
3555 4 : loadparm_s3_global_substitution();
3556 0 : int snum;
3557 4 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3558 4 : int n_services=lp_numservices();
3559 0 : int i;
3560 0 : struct spoolss_NotifyOption *option;
3561 0 : struct spoolss_NotifyOptionType option_type;
3562 4 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3563 0 : WERROR result;
3564 :
3565 4 : DEBUG(4,("printserver_notify_info\n"));
3566 :
3567 4 : if (!Printer)
3568 0 : return WERR_INVALID_HANDLE;
3569 :
3570 4 : option = Printer->notify.option;
3571 :
3572 4 : info->version = 2;
3573 4 : info->notifies = NULL;
3574 4 : info->count = 0;
3575 :
3576 : /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3577 : sending a ffpcn() request first */
3578 :
3579 4 : if ( !option )
3580 0 : return WERR_INVALID_HANDLE;
3581 :
3582 12 : for (i=0; i<option->count; i++) {
3583 8 : option_type = option->types[i];
3584 :
3585 8 : if (option_type.type != PRINTER_NOTIFY_TYPE)
3586 4 : continue;
3587 :
3588 492 : for (snum = 0; snum < n_services; snum++) {
3589 488 : if (!lp_browseable(snum) ||
3590 488 : !lp_snum_ok(snum) ||
3591 488 : !lp_printable(snum)) {
3592 468 : continue; /* skip */
3593 : }
3594 :
3595 : /* Maybe we should use the SYSTEM session_info here... */
3596 20 : result = winreg_get_printer_internal(mem_ctx,
3597 : get_session_info_system(),
3598 : p->msg_ctx,
3599 20 : lp_servicename(talloc_tos(), lp_sub, snum),
3600 : &pinfo2);
3601 20 : if (!W_ERROR_IS_OK(result)) {
3602 20 : DEBUG(4, ("printserver_notify_info: "
3603 : "Failed to get printer [%s]\n",
3604 : lp_servicename(talloc_tos(), lp_sub, snum)));
3605 20 : continue;
3606 : }
3607 :
3608 :
3609 0 : construct_notify_printer_info(p->msg_ctx,
3610 : Printer, info,
3611 : pinfo2, snum,
3612 : &option_type, snum,
3613 : mem_ctx);
3614 :
3615 0 : TALLOC_FREE(pinfo2);
3616 : }
3617 : }
3618 :
3619 : #if 0
3620 : /*
3621 : * Debugging information, don't delete.
3622 : */
3623 :
3624 : DEBUG(1,("dumping the NOTIFY_INFO\n"));
3625 : DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3626 : DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3627 :
3628 : for (i=0; i<info->count; i++) {
3629 : DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3630 : i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3631 : info->data[i].id, info->data[i].size, info->data[i].enc_type));
3632 : }
3633 : #endif
3634 :
3635 4 : return WERR_OK;
3636 : }
3637 :
3638 : /*******************************************************************
3639 : *
3640 : * fill a notify_info struct with info asked
3641 : *
3642 : ********************************************************************/
3643 :
3644 0 : static WERROR printer_notify_info(struct pipes_struct *p,
3645 : struct policy_handle *hnd,
3646 : struct spoolss_NotifyInfo *info,
3647 : TALLOC_CTX *mem_ctx)
3648 : {
3649 0 : const struct loadparm_substitution *lp_sub =
3650 0 : loadparm_s3_global_substitution();
3651 0 : int snum;
3652 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3653 0 : int i;
3654 0 : uint32_t id;
3655 0 : struct spoolss_NotifyOption *option;
3656 0 : struct spoolss_NotifyOptionType option_type;
3657 0 : int count,j;
3658 0 : print_queue_struct *queue=NULL;
3659 0 : print_status_struct status;
3660 0 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3661 0 : WERROR result;
3662 0 : struct tdb_print_db *pdb;
3663 :
3664 0 : DEBUG(4,("printer_notify_info\n"));
3665 :
3666 0 : if (!Printer)
3667 0 : return WERR_INVALID_HANDLE;
3668 :
3669 0 : option = Printer->notify.option;
3670 0 : id = 0x0;
3671 :
3672 0 : info->version = 2;
3673 0 : info->notifies = NULL;
3674 0 : info->count = 0;
3675 :
3676 : /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3677 : sending a ffpcn() request first */
3678 :
3679 0 : if ( !option )
3680 0 : return WERR_INVALID_HANDLE;
3681 :
3682 0 : if (!get_printer_snum(p, hnd, &snum, NULL)) {
3683 0 : return WERR_INVALID_HANDLE;
3684 : }
3685 :
3686 0 : pdb = get_print_db_byname(Printer->sharename);
3687 0 : if (pdb == NULL) {
3688 0 : return WERR_INVALID_HANDLE;
3689 : }
3690 :
3691 : /* Maybe we should use the SYSTEM session_info here... */
3692 0 : result = winreg_get_printer_internal(mem_ctx,
3693 : get_session_info_system(),
3694 : p->msg_ctx,
3695 0 : lp_servicename(talloc_tos(), lp_sub, snum), &pinfo2);
3696 0 : if (!W_ERROR_IS_OK(result)) {
3697 0 : result = WERR_INVALID_HANDLE;
3698 0 : goto err_pdb_drop;
3699 : }
3700 :
3701 : /*
3702 : * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3703 : * correct servername.
3704 : */
3705 0 : pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3706 0 : if (pinfo2->servername == NULL) {
3707 0 : result = WERR_NOT_ENOUGH_MEMORY;
3708 0 : goto err_pdb_drop;
3709 : }
3710 :
3711 0 : for (i = 0; i < option->count; i++) {
3712 0 : option_type = option->types[i];
3713 :
3714 0 : switch (option_type.type) {
3715 0 : case PRINTER_NOTIFY_TYPE:
3716 0 : if (construct_notify_printer_info(p->msg_ctx,
3717 : Printer, info,
3718 : pinfo2, snum,
3719 : &option_type, id,
3720 : mem_ctx)) {
3721 0 : id--;
3722 : }
3723 0 : break;
3724 :
3725 0 : case JOB_NOTIFY_TYPE:
3726 :
3727 0 : count = print_queue_status(p->msg_ctx, snum, &queue,
3728 : &status);
3729 :
3730 0 : for (j = 0; j < count; j++) {
3731 0 : uint32_t jobid;
3732 0 : jobid = sysjob_to_jobid_pdb(pdb,
3733 0 : queue[j].sysjob);
3734 0 : if (jobid == (uint32_t)-1) {
3735 0 : DEBUG(2, ("ignoring untracked job %d\n",
3736 : queue[j].sysjob));
3737 0 : continue;
3738 : }
3739 : /* FIXME check return value */
3740 0 : construct_notify_jobs_info(p->msg_ctx,
3741 0 : &queue[j], info,
3742 : pinfo2, snum,
3743 : &option_type,
3744 : jobid,
3745 : mem_ctx);
3746 : }
3747 :
3748 0 : SAFE_FREE(queue);
3749 0 : break;
3750 : }
3751 : }
3752 :
3753 : /*
3754 : * Debugging information, don't delete.
3755 : */
3756 : /*
3757 : DEBUG(1,("dumping the NOTIFY_INFO\n"));
3758 : DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3759 : DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3760 :
3761 : for (i=0; i<info->count; i++) {
3762 : DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3763 : i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3764 : info->data[i].id, info->data[i].size, info->data[i].enc_type));
3765 : }
3766 : */
3767 :
3768 0 : talloc_free(pinfo2);
3769 0 : result = WERR_OK;
3770 0 : err_pdb_drop:
3771 0 : release_print_db(pdb);
3772 0 : return result;
3773 : }
3774 :
3775 : /****************************************************************
3776 : _spoolss_RouterRefreshPrinterChangeNotify
3777 : ****************************************************************/
3778 :
3779 4 : WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3780 : struct spoolss_RouterRefreshPrinterChangeNotify *r)
3781 : {
3782 0 : struct spoolss_NotifyInfo *info;
3783 :
3784 4 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3785 4 : WERROR result = WERR_INVALID_HANDLE;
3786 :
3787 : /* we always have a spoolss_NotifyInfo struct */
3788 4 : info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3789 4 : if (!info) {
3790 0 : result = WERR_NOT_ENOUGH_MEMORY;
3791 0 : goto done;
3792 : }
3793 :
3794 4 : *r->out.info = info;
3795 :
3796 4 : if (!Printer) {
3797 0 : DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3798 : "Invalid handle (%s:%u:%u).\n",
3799 : OUR_HANDLE(r->in.handle)));
3800 0 : goto done;
3801 : }
3802 :
3803 4 : DEBUG(4,("Printer type %x\n",Printer->printer_type));
3804 :
3805 : /*
3806 : * We are now using the change value, and
3807 : * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3808 : * I don't have a global notification system, I'm sending back all the
3809 : * information even when _NOTHING_ has changed.
3810 : */
3811 :
3812 : /* We need to keep track of the change value to send back in
3813 : RRPCN replies otherwise our updates are ignored. */
3814 :
3815 4 : Printer->notify.fnpcn = true;
3816 :
3817 4 : if (Printer->notify.cli_chan != NULL &&
3818 4 : Printer->notify.cli_chan->active_connections > 0) {
3819 4 : DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3820 : "Saving change value in request [%x]\n",
3821 : r->in.change_low));
3822 4 : Printer->notify.change = r->in.change_low;
3823 : }
3824 :
3825 : /* just ignore the spoolss_NotifyOption */
3826 :
3827 4 : switch (Printer->printer_type) {
3828 4 : case SPLHND_SERVER:
3829 4 : result = printserver_notify_info(p, r->in.handle,
3830 : info, p->mem_ctx);
3831 4 : break;
3832 :
3833 0 : case SPLHND_PRINTER:
3834 0 : result = printer_notify_info(p, r->in.handle,
3835 : info, p->mem_ctx);
3836 0 : break;
3837 : }
3838 :
3839 4 : Printer->notify.fnpcn = false;
3840 :
3841 4 : done:
3842 4 : return result;
3843 : }
3844 :
3845 : /********************************************************************
3846 : ********************************************************************/
3847 :
3848 4076 : static WERROR create_printername(TALLOC_CTX *mem_ctx,
3849 : const char *servername,
3850 : const char *printername,
3851 : const char **printername_p)
3852 : {
3853 : /* FIXME: add lp_force_printername() */
3854 :
3855 4076 : if (servername == NULL) {
3856 1732 : *printername_p = talloc_strdup(mem_ctx, printername);
3857 1732 : W_ERROR_HAVE_NO_MEMORY(*printername_p);
3858 1732 : return WERR_OK;
3859 : }
3860 :
3861 2344 : if (servername[0] == '\\' && servername[1] == '\\') {
3862 2344 : servername += 2;
3863 : }
3864 :
3865 2344 : *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3866 2344 : W_ERROR_HAVE_NO_MEMORY(*printername_p);
3867 :
3868 2344 : return WERR_OK;
3869 : }
3870 :
3871 : /********************************************************************
3872 : ********************************************************************/
3873 :
3874 2936 : static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3875 : const char *printername)
3876 : {
3877 2936 : if (dm == NULL) {
3878 94 : return;
3879 : }
3880 :
3881 2842 : dm->devicename = talloc_strndup(dm, printername,
3882 2842 : MIN(strlen(printername), 31));
3883 : }
3884 :
3885 : /********************************************************************
3886 : * construct_printer_info_0
3887 : * fill a printer_info_0 struct
3888 : ********************************************************************/
3889 :
3890 276 : static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3891 : const struct auth_session_info *session_info,
3892 : struct messaging_context *msg_ctx,
3893 : struct spoolss_PrinterInfo2 *info2,
3894 : const char *servername,
3895 : struct spoolss_PrinterInfo0 *r,
3896 : int snum)
3897 : {
3898 0 : int count;
3899 0 : struct printer_session_counter *session_counter;
3900 0 : struct timeval setuptime;
3901 0 : print_status_struct status;
3902 0 : WERROR result;
3903 0 : int os_major, os_minor, os_build;
3904 0 : const char *architecture;
3905 0 : uint32_t processor_architecture, processor_type;
3906 :
3907 276 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3908 276 : if (!W_ERROR_IS_OK(result)) {
3909 0 : return result;
3910 : }
3911 :
3912 276 : if (servername) {
3913 140 : r->servername = talloc_strdup(mem_ctx, servername);
3914 140 : W_ERROR_HAVE_NO_MEMORY(r->servername);
3915 : } else {
3916 136 : r->servername = NULL;
3917 : }
3918 :
3919 276 : count = print_queue_length(msg_ctx, snum, &status);
3920 :
3921 : /* check if we already have a counter for this printer */
3922 660 : for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3923 620 : if (session_counter->snum == snum)
3924 236 : break;
3925 : }
3926 :
3927 : /* it's the first time, add it to the list */
3928 276 : if (session_counter == NULL) {
3929 40 : session_counter = talloc_zero(counter_list, struct printer_session_counter);
3930 40 : W_ERROR_HAVE_NO_MEMORY(session_counter);
3931 40 : session_counter->snum = snum;
3932 40 : session_counter->counter = 0;
3933 40 : DLIST_ADD(counter_list, session_counter);
3934 : }
3935 :
3936 : /* increment it */
3937 276 : session_counter->counter++;
3938 :
3939 276 : r->cjobs = count;
3940 276 : r->total_jobs = 0;
3941 276 : r->total_bytes = 0;
3942 :
3943 276 : get_startup_time(&setuptime);
3944 276 : init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3945 :
3946 : /* JFM:
3947 : * the global_counter should be stored in a TDB as it's common to all the clients
3948 : * and should be zeroed on samba startup
3949 : */
3950 276 : r->global_counter = session_counter->counter;
3951 276 : r->total_pages = 0;
3952 :
3953 : /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3954 276 : os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
3955 : "spoolss", "os_major",
3956 : GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
3957 276 : os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
3958 : "spoolss", "os_minor",
3959 : GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
3960 276 : os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
3961 : "spoolss", "os_build",
3962 : GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
3963 :
3964 276 : SCVAL(&r->version, 0, os_major);
3965 276 : SCVAL(&r->version, 1, os_minor);
3966 276 : SSVAL(&r->version, 2, os_build);
3967 :
3968 276 : architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
3969 : "spoolss",
3970 : "architecture",
3971 : GLOBAL_SPOOLSS_ARCHITECTURE);
3972 :
3973 276 : if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
3974 276 : processor_architecture = PROCESSOR_ARCHITECTURE_AMD64;
3975 276 : processor_type = PROCESSOR_AMD_X8664;
3976 0 : } else if (strequal(architecture, SPOOLSS_ARCHITECTURE_ARM64)) {
3977 0 : processor_architecture = PROCESSOR_ARCHITECTURE_ARM64;
3978 0 : processor_type = PROCESSOR_ARM820;
3979 : } else {
3980 0 : processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3981 0 : processor_type = PROCESSOR_INTEL_PENTIUM;
3982 : }
3983 :
3984 276 : r->free_build = SPOOLSS_RELEASE_BUILD;
3985 276 : r->spooling = 0;
3986 276 : r->max_spooling = 0;
3987 276 : r->session_counter = session_counter->counter;
3988 276 : r->num_error_out_of_paper = 0x0;
3989 276 : r->num_error_not_ready = 0x0; /* number of print failure */
3990 276 : r->job_error = 0x0;
3991 276 : r->number_of_processors = 0x1;
3992 276 : r->processor_type = processor_type;
3993 276 : r->high_part_total_bytes = 0x0;
3994 :
3995 : /* ChangeID in milliseconds*/
3996 276 : winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3997 : info2->sharename, &r->change_id);
3998 :
3999 276 : r->last_error = WERR_OK;
4000 276 : r->status = nt_printq_status(status.status);
4001 276 : r->enumerate_network_printers = 0x0;
4002 276 : r->c_setprinter = 0x0;
4003 276 : r->processor_architecture = processor_architecture;
4004 276 : r->processor_level = 0x6; /* 6 ???*/
4005 276 : r->ref_ic = 0;
4006 276 : r->reserved2 = 0;
4007 276 : r->reserved3 = 0;
4008 :
4009 276 : return WERR_OK;
4010 : }
4011 :
4012 :
4013 : /********************************************************************
4014 : * construct_printer_info1
4015 : * fill a spoolss_PrinterInfo1 struct
4016 : ********************************************************************/
4017 :
4018 528 : static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4019 : const struct spoolss_PrinterInfo2 *info2,
4020 : uint32_t flags,
4021 : const char *servername,
4022 : struct spoolss_PrinterInfo1 *r,
4023 : int snum)
4024 : {
4025 0 : const struct loadparm_substitution *lp_sub =
4026 528 : loadparm_s3_global_substitution();
4027 0 : WERROR result;
4028 :
4029 528 : r->flags = flags;
4030 :
4031 528 : if (info2->comment == NULL || info2->comment[0] == '\0') {
4032 388 : r->comment = lp_comment(mem_ctx, lp_sub, snum);
4033 : } else {
4034 140 : r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4035 : }
4036 528 : W_ERROR_HAVE_NO_MEMORY(r->comment);
4037 :
4038 528 : result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4039 528 : if (!W_ERROR_IS_OK(result)) {
4040 0 : return result;
4041 : }
4042 :
4043 1056 : r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4044 : r->name,
4045 528 : info2->drivername,
4046 : r->comment);
4047 528 : W_ERROR_HAVE_NO_MEMORY(r->description);
4048 :
4049 528 : return WERR_OK;
4050 : }
4051 :
4052 : /********************************************************************
4053 : * construct_printer_info2
4054 : * fill a spoolss_PrinterInfo2 struct
4055 : ********************************************************************/
4056 :
4057 1272 : static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4058 : struct messaging_context *msg_ctx,
4059 : const struct spoolss_PrinterInfo2 *info2,
4060 : const char *servername,
4061 : struct spoolss_PrinterInfo2 *r,
4062 : int snum)
4063 : {
4064 0 : const struct loadparm_substitution *lp_sub =
4065 1272 : loadparm_s3_global_substitution();
4066 0 : int count;
4067 0 : print_status_struct status;
4068 0 : WERROR result;
4069 :
4070 1272 : count = print_queue_length(msg_ctx, snum, &status);
4071 :
4072 1272 : if (servername) {
4073 572 : r->servername = talloc_strdup(mem_ctx, servername);
4074 572 : W_ERROR_HAVE_NO_MEMORY(r->servername);
4075 : } else {
4076 700 : r->servername = NULL;
4077 : }
4078 :
4079 1272 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4080 1272 : if (!W_ERROR_IS_OK(result)) {
4081 0 : return result;
4082 : }
4083 :
4084 1272 : r->sharename = lp_servicename(mem_ctx, lp_sub, snum);
4085 1272 : W_ERROR_HAVE_NO_MEMORY(r->sharename);
4086 1272 : r->portname = talloc_strdup(mem_ctx, info2->portname);
4087 1272 : W_ERROR_HAVE_NO_MEMORY(r->portname);
4088 1272 : r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4089 1272 : W_ERROR_HAVE_NO_MEMORY(r->drivername);
4090 :
4091 1272 : if (info2->comment[0] == '\0') {
4092 876 : r->comment = lp_comment(mem_ctx, lp_sub, snum);
4093 : } else {
4094 396 : r->comment = talloc_strdup(mem_ctx, info2->comment);
4095 : }
4096 1272 : W_ERROR_HAVE_NO_MEMORY(r->comment);
4097 :
4098 1272 : r->location = talloc_strdup(mem_ctx, info2->location);
4099 1272 : if (info2->location[0] == '\0') {
4100 1192 : const char *loc = NULL;
4101 0 : NTSTATUS nt_status;
4102 :
4103 1192 : nt_status = printer_list_get_printer(mem_ctx,
4104 1192 : info2->sharename,
4105 : NULL,
4106 : &loc,
4107 : NULL);
4108 1192 : if (NT_STATUS_IS_OK(nt_status)) {
4109 0 : if (loc != NULL) {
4110 0 : r->location = talloc_strdup(mem_ctx, loc);
4111 : }
4112 : }
4113 : }
4114 1272 : W_ERROR_HAVE_NO_MEMORY(r->location);
4115 :
4116 1272 : r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4117 1272 : W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4118 1272 : r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4119 1272 : W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4120 1272 : r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4121 1272 : W_ERROR_HAVE_NO_MEMORY(r->datatype);
4122 1272 : r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4123 1272 : W_ERROR_HAVE_NO_MEMORY(r->parameters);
4124 :
4125 1272 : r->attributes = info2->attributes;
4126 :
4127 1272 : r->priority = info2->priority;
4128 1272 : r->defaultpriority = info2->defaultpriority;
4129 1272 : r->starttime = info2->starttime;
4130 1272 : r->untiltime = info2->untiltime;
4131 1272 : r->status = nt_printq_status(status.status);
4132 1272 : r->cjobs = count;
4133 1272 : r->averageppm = info2->averageppm;
4134 :
4135 1272 : if (info2->devmode != NULL) {
4136 1186 : result = copy_devicemode(mem_ctx,
4137 1186 : info2->devmode,
4138 : &r->devmode);
4139 1186 : if (!W_ERROR_IS_OK(result)) {
4140 0 : return result;
4141 : }
4142 86 : } else if (lp_default_devmode(snum)) {
4143 0 : result = spoolss_create_default_devmode(mem_ctx,
4144 0 : info2->printername,
4145 : &r->devmode);
4146 0 : if (!W_ERROR_IS_OK(result)) {
4147 0 : return result;
4148 : }
4149 : } else {
4150 86 : r->devmode = NULL;
4151 86 : DEBUG(8,("Returning NULL Devicemode!\n"));
4152 : }
4153 :
4154 1272 : compose_devicemode_devicename(r->devmode, r->printername);
4155 :
4156 1272 : r->secdesc = NULL;
4157 :
4158 1272 : if (info2->secdesc != NULL) {
4159 : /* don't use talloc_steal() here unless you do a deep steal of all
4160 : the SEC_DESC members */
4161 :
4162 1272 : r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4163 1272 : if (r->secdesc == NULL) {
4164 0 : return WERR_NOT_ENOUGH_MEMORY;
4165 : }
4166 : }
4167 :
4168 1272 : return WERR_OK;
4169 : }
4170 :
4171 : /********************************************************************
4172 : * construct_printer_info3
4173 : * fill a spoolss_PrinterInfo3 struct
4174 : ********************************************************************/
4175 :
4176 144 : static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4177 : const struct spoolss_PrinterInfo2 *info2,
4178 : const char *servername,
4179 : struct spoolss_PrinterInfo3 *r,
4180 : int snum)
4181 : {
4182 : /* These are the components of the SD we are returning. */
4183 :
4184 144 : if (info2->secdesc != NULL) {
4185 : /* don't use talloc_steal() here unless you do a deep steal of all
4186 : the SEC_DESC members */
4187 :
4188 144 : r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4189 144 : if (r->secdesc == NULL) {
4190 0 : return WERR_NOT_ENOUGH_MEMORY;
4191 : }
4192 : }
4193 :
4194 144 : return WERR_OK;
4195 : }
4196 :
4197 : /********************************************************************
4198 : * construct_printer_info4
4199 : * fill a spoolss_PrinterInfo4 struct
4200 : ********************************************************************/
4201 :
4202 168 : static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4203 : const struct spoolss_PrinterInfo2 *info2,
4204 : const char *servername,
4205 : struct spoolss_PrinterInfo4 *r,
4206 : int snum)
4207 : {
4208 0 : WERROR result;
4209 :
4210 168 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4211 168 : if (!W_ERROR_IS_OK(result)) {
4212 0 : return result;
4213 : }
4214 :
4215 168 : if (servername) {
4216 8 : r->servername = talloc_strdup(mem_ctx, servername);
4217 8 : W_ERROR_HAVE_NO_MEMORY(r->servername);
4218 : } else {
4219 160 : r->servername = NULL;
4220 : }
4221 :
4222 168 : r->attributes = info2->attributes;
4223 :
4224 168 : return WERR_OK;
4225 : }
4226 :
4227 : /********************************************************************
4228 : * construct_printer_info5
4229 : * fill a spoolss_PrinterInfo5 struct
4230 : ********************************************************************/
4231 :
4232 168 : static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4233 : const struct spoolss_PrinterInfo2 *info2,
4234 : const char *servername,
4235 : struct spoolss_PrinterInfo5 *r,
4236 : int snum)
4237 : {
4238 0 : WERROR result;
4239 :
4240 168 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4241 168 : if (!W_ERROR_IS_OK(result)) {
4242 0 : return result;
4243 : }
4244 :
4245 168 : r->portname = talloc_strdup(mem_ctx, info2->portname);
4246 168 : W_ERROR_HAVE_NO_MEMORY(r->portname);
4247 :
4248 168 : r->attributes = info2->attributes;
4249 :
4250 : /*
4251 : * These two are not used by NT+ according to MSDN. However the values
4252 : * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
4253 : */
4254 168 : r->device_not_selected_timeout = 0xafc8; /* 45 sec */
4255 168 : r->transmission_retry_timeout = 0xafc8; /* 45 sec */
4256 :
4257 168 : return WERR_OK;
4258 : }
4259 :
4260 : /********************************************************************
4261 : * construct_printer_info_6
4262 : * fill a spoolss_PrinterInfo6 struct
4263 : ********************************************************************/
4264 :
4265 88 : static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4266 : struct messaging_context *msg_ctx,
4267 : const struct spoolss_PrinterInfo2 *info2,
4268 : const char *servername,
4269 : struct spoolss_PrinterInfo6 *r,
4270 : int snum)
4271 : {
4272 0 : print_status_struct status;
4273 :
4274 88 : print_queue_length(msg_ctx, snum, &status);
4275 :
4276 88 : r->status = nt_printq_status(status.status);
4277 :
4278 88 : return WERR_OK;
4279 : }
4280 :
4281 : /********************************************************************
4282 : * construct_printer_info7
4283 : * fill a spoolss_PrinterInfo7 struct
4284 : ********************************************************************/
4285 :
4286 112 : static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4287 : struct messaging_context *msg_ctx,
4288 : const char *servername,
4289 : struct spoolss_PrinterInfo7 *r,
4290 : int snum)
4291 : {
4292 0 : const struct loadparm_substitution *lp_sub =
4293 112 : loadparm_s3_global_substitution();
4294 0 : const struct auth_session_info *session_info;
4295 112 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4296 0 : char *printer;
4297 0 : WERROR werr;
4298 112 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4299 112 : if (tmp_ctx == NULL) {
4300 0 : return WERR_NOT_ENOUGH_MEMORY;
4301 : }
4302 :
4303 112 : session_info = get_session_info_system();
4304 112 : SMB_ASSERT(session_info != NULL);
4305 :
4306 112 : printer = lp_servicename(tmp_ctx, lp_sub, snum);
4307 112 : if (printer == NULL) {
4308 0 : DEBUG(0, ("invalid printer snum %d\n", snum));
4309 0 : werr = WERR_INVALID_PARAMETER;
4310 0 : goto out_tmp_free;
4311 : }
4312 :
4313 112 : if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4314 : servername, printer, &pinfo2)) {
4315 0 : struct GUID guid;
4316 0 : char *guidstr;
4317 0 : werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4318 : printer, &guid);
4319 0 : if (!W_ERROR_IS_OK(werr)) {
4320 : /*
4321 : * If we do not have a GUID entry in the registry, then
4322 : * try to retrieve it from AD and store it now.
4323 : */
4324 0 : werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4325 : &guid);
4326 0 : if (!W_ERROR_IS_OK(werr)) {
4327 0 : DBG_NOTICE("Failed to retrieve GUID for "
4328 : "printer [%s] from AD - %s\n",
4329 : printer,
4330 : win_errstr(werr));
4331 0 : if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
4332 : /*
4333 : * If we did not find it in AD, then it
4334 : * is unpublished and we should reflect
4335 : * this in the registry and return
4336 : * success.
4337 : */
4338 0 : DBG_WARNING("Unpublish printer [%s]\n",
4339 : pinfo2->sharename);
4340 0 : nt_printer_publish(tmp_ctx,
4341 : session_info,
4342 : msg_ctx,
4343 : pinfo2,
4344 : DSPRINT_UNPUBLISH);
4345 0 : r->guid = talloc_strdup(mem_ctx, "");
4346 0 : r->action = DSPRINT_UNPUBLISH;
4347 :
4348 0 : if (r->guid == NULL) {
4349 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4350 : } else {
4351 0 : werr = WERR_OK;
4352 : }
4353 : }
4354 0 : goto out_tmp_free;
4355 : }
4356 :
4357 0 : werr = nt_printer_guid_store(msg_ctx, printer, guid);
4358 0 : if (!W_ERROR_IS_OK(werr)) {
4359 0 : DEBUG(3, ("failed to store printer %s guid\n",
4360 : printer));
4361 : }
4362 : }
4363 :
4364 : /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
4365 0 : guidstr = GUID_string2(mem_ctx, &guid);
4366 0 : if (guidstr == NULL) {
4367 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4368 0 : goto out_tmp_free;
4369 : }
4370 : /* Convert GUID string to uppercase otherwise printers
4371 : * are pruned */
4372 0 : r->guid = talloc_strdup_upper(mem_ctx, guidstr);
4373 0 : r->action = DSPRINT_PUBLISH;
4374 :
4375 0 : TALLOC_FREE(guidstr);
4376 : } else {
4377 112 : r->guid = talloc_strdup(mem_ctx, "");
4378 112 : r->action = DSPRINT_UNPUBLISH;
4379 : }
4380 112 : if (r->guid == NULL) {
4381 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4382 0 : goto out_tmp_free;
4383 : }
4384 :
4385 112 : werr = WERR_OK;
4386 112 : out_tmp_free:
4387 112 : talloc_free(tmp_ctx);
4388 112 : return werr;
4389 : }
4390 :
4391 : /********************************************************************
4392 : * construct_printer_info8
4393 : * fill a spoolss_PrinterInfo8 struct
4394 : ********************************************************************/
4395 :
4396 1664 : static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4397 : const struct spoolss_PrinterInfo2 *info2,
4398 : const char *servername,
4399 : struct spoolss_DeviceModeInfo *r,
4400 : int snum)
4401 : {
4402 0 : WERROR result;
4403 0 : const char *printername;
4404 :
4405 1664 : result = create_printername(mem_ctx, servername, info2->printername, &printername);
4406 1664 : if (!W_ERROR_IS_OK(result)) {
4407 0 : return result;
4408 : }
4409 :
4410 1664 : if (info2->devmode != NULL) {
4411 1656 : result = copy_devicemode(mem_ctx,
4412 1656 : info2->devmode,
4413 : &r->devmode);
4414 1656 : if (!W_ERROR_IS_OK(result)) {
4415 0 : return result;
4416 : }
4417 8 : } else if (lp_default_devmode(snum)) {
4418 0 : result = spoolss_create_default_devmode(mem_ctx,
4419 0 : info2->printername,
4420 : &r->devmode);
4421 0 : if (!W_ERROR_IS_OK(result)) {
4422 0 : return result;
4423 : }
4424 : } else {
4425 8 : r->devmode = NULL;
4426 8 : DEBUG(8,("Returning NULL Devicemode!\n"));
4427 : }
4428 :
4429 1664 : compose_devicemode_devicename(r->devmode, printername);
4430 :
4431 1664 : return WERR_OK;
4432 : }
4433 :
4434 : /********************************************************************
4435 : Spoolss_enumprinters.
4436 : ********************************************************************/
4437 :
4438 180 : static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4439 : const struct auth_session_info *session_info,
4440 : struct messaging_context *msg_ctx,
4441 : const char *servername,
4442 : uint32_t level,
4443 : uint32_t flags,
4444 : union spoolss_PrinterInfo **info_p,
4445 : uint32_t *count_p)
4446 : {
4447 0 : int snum;
4448 0 : int n_services;
4449 180 : union spoolss_PrinterInfo *info = NULL;
4450 180 : uint32_t count = 0;
4451 180 : WERROR result = WERR_OK;
4452 180 : struct dcerpc_binding_handle *b = NULL;
4453 180 : TALLOC_CTX *tmp_ctx = NULL;
4454 :
4455 180 : tmp_ctx = talloc_new(mem_ctx);
4456 180 : if (!tmp_ctx) {
4457 0 : return WERR_NOT_ENOUGH_MEMORY;
4458 : }
4459 :
4460 : /*
4461 : * printer shares are updated on client enumeration. The background
4462 : * printer process updates printer_list.tdb at regular intervals.
4463 : */
4464 180 : become_root();
4465 180 : delete_and_reload_printers();
4466 180 : unbecome_root();
4467 :
4468 180 : n_services = lp_numservices();
4469 180 : *count_p = 0;
4470 180 : *info_p = NULL;
4471 :
4472 12230 : for (snum = 0; snum < n_services; snum++) {
4473 :
4474 0 : const char *printer;
4475 0 : struct spoolss_PrinterInfo2 *info2;
4476 :
4477 12050 : if (!snum_is_shared_printer(snum)) {
4478 11070 : continue;
4479 : }
4480 :
4481 980 : printer = lp_const_servicename(snum);
4482 :
4483 980 : DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4484 : printer, snum));
4485 :
4486 980 : if (b == NULL) {
4487 180 : result = winreg_printer_binding_handle(tmp_ctx,
4488 : session_info,
4489 : msg_ctx,
4490 : &b);
4491 180 : if (!W_ERROR_IS_OK(result)) {
4492 0 : goto out;
4493 : }
4494 : }
4495 :
4496 980 : result = winreg_create_printer(tmp_ctx, b,
4497 : printer);
4498 980 : if (!W_ERROR_IS_OK(result)) {
4499 0 : goto out;
4500 : }
4501 :
4502 980 : info = talloc_realloc(tmp_ctx, info,
4503 : union spoolss_PrinterInfo,
4504 : count + 1);
4505 980 : if (!info) {
4506 0 : result = WERR_NOT_ENOUGH_MEMORY;
4507 0 : goto out;
4508 : }
4509 :
4510 980 : result = winreg_get_printer(tmp_ctx, b,
4511 : printer, &info2);
4512 980 : if (!W_ERROR_IS_OK(result)) {
4513 0 : goto out;
4514 : }
4515 :
4516 980 : switch (level) {
4517 40 : case 0:
4518 40 : result = construct_printer_info0(info, session_info,
4519 : msg_ctx, info2,
4520 : servername,
4521 40 : &info[count].info0, snum);
4522 40 : break;
4523 440 : case 1:
4524 440 : result = construct_printer_info1(info, info2, flags,
4525 : servername,
4526 440 : &info[count].info1, snum);
4527 440 : break;
4528 340 : case 2:
4529 340 : result = construct_printer_info2(info, msg_ctx, info2,
4530 : servername,
4531 340 : &info[count].info2, snum);
4532 340 : break;
4533 80 : case 4:
4534 80 : result = construct_printer_info4(info, info2,
4535 : servername,
4536 80 : &info[count].info4, snum);
4537 80 : break;
4538 80 : case 5:
4539 80 : result = construct_printer_info5(info, info2,
4540 : servername,
4541 80 : &info[count].info5, snum);
4542 80 : break;
4543 :
4544 0 : default:
4545 0 : result = WERR_INVALID_LEVEL;
4546 0 : goto out;
4547 : }
4548 :
4549 980 : if (!W_ERROR_IS_OK(result)) {
4550 0 : goto out;
4551 : }
4552 :
4553 980 : count++;
4554 : }
4555 :
4556 180 : out:
4557 180 : if (W_ERROR_IS_OK(result)) {
4558 180 : *info_p = talloc_move(mem_ctx, &info);
4559 180 : *count_p = count;
4560 : }
4561 :
4562 180 : talloc_free(tmp_ctx);
4563 :
4564 180 : return result;
4565 : }
4566 :
4567 : /********************************************************************
4568 : * handle enumeration of printers at level 0
4569 : ********************************************************************/
4570 :
4571 8 : static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4572 : const struct auth_session_info *session_info,
4573 : struct messaging_context *msg_ctx,
4574 : uint32_t flags,
4575 : const char *servername,
4576 : union spoolss_PrinterInfo **info,
4577 : uint32_t *count)
4578 : {
4579 8 : DEBUG(4,("enum_all_printers_info_0\n"));
4580 :
4581 8 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4582 : servername, 0, flags, info, count);
4583 : }
4584 :
4585 :
4586 : /********************************************************************
4587 : ********************************************************************/
4588 :
4589 72 : static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4590 : const struct auth_session_info *session_info,
4591 : struct messaging_context *msg_ctx,
4592 : const char *servername,
4593 : uint32_t flags,
4594 : union spoolss_PrinterInfo **info,
4595 : uint32_t *count)
4596 : {
4597 72 : DEBUG(4,("enum_all_printers_info_1\n"));
4598 :
4599 72 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4600 : servername, 1, flags, info, count);
4601 : }
4602 :
4603 : /********************************************************************
4604 : enum_all_printers_info_1_local.
4605 : *********************************************************************/
4606 :
4607 72 : static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4608 : const struct auth_session_info *session_info,
4609 : struct messaging_context *msg_ctx,
4610 : const char *servername,
4611 : union spoolss_PrinterInfo **info,
4612 : uint32_t *count)
4613 : {
4614 72 : DEBUG(4,("enum_all_printers_info_1_local\n"));
4615 :
4616 72 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4617 : servername, PRINTER_ENUM_ICON8, info, count);
4618 : }
4619 :
4620 : /********************************************************************
4621 : enum_all_printers_info_1_name.
4622 : *********************************************************************/
4623 :
4624 0 : static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4625 : const struct auth_session_info *session_info,
4626 : struct messaging_context *msg_ctx,
4627 : const char *servername,
4628 : union spoolss_PrinterInfo **info,
4629 : uint32_t *count)
4630 : {
4631 0 : const char *s = servername;
4632 :
4633 0 : DEBUG(4,("enum_all_printers_info_1_name\n"));
4634 :
4635 0 : if (servername != NULL &&
4636 0 : (servername[0] == '\\') && (servername[1] == '\\')) {
4637 0 : s = servername + 2;
4638 : }
4639 :
4640 0 : if (!is_myname_or_ipaddr(s)) {
4641 0 : return WERR_INVALID_NAME;
4642 : }
4643 :
4644 0 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4645 : servername, PRINTER_ENUM_ICON8, info, count);
4646 : }
4647 :
4648 : /********************************************************************
4649 : enum_all_printers_info_1_network.
4650 : *********************************************************************/
4651 :
4652 0 : static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4653 : const struct auth_session_info *session_info,
4654 : struct messaging_context *msg_ctx,
4655 : const char *servername,
4656 : union spoolss_PrinterInfo **info,
4657 : uint32_t *count)
4658 : {
4659 0 : const char *s = servername;
4660 :
4661 0 : DEBUG(4,("enum_all_printers_info_1_network\n"));
4662 :
4663 : /* If we respond to a enum_printers level 1 on our name with flags
4664 : set to PRINTER_ENUM_REMOTE with a list of printers then these
4665 : printers incorrectly appear in the APW browse list.
4666 : Specifically the printers for the server appear at the workgroup
4667 : level where all the other servers in the domain are
4668 : listed. Windows responds to this call with a
4669 : WERR_CAN_NOT_COMPLETE so we should do the same. */
4670 :
4671 0 : if (servername != NULL &&
4672 0 : (servername[0] == '\\') && (servername[1] == '\\')) {
4673 0 : s = servername + 2;
4674 : }
4675 :
4676 0 : if (is_myname_or_ipaddr(s)) {
4677 0 : return WERR_CAN_NOT_COMPLETE;
4678 : }
4679 :
4680 0 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4681 : servername, PRINTER_ENUM_NAME, info, count);
4682 : }
4683 :
4684 : /********************************************************************
4685 : * api_spoolss_enumprinters
4686 : *
4687 : * called from api_spoolss_enumprinters (see this to understand)
4688 : ********************************************************************/
4689 :
4690 68 : static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4691 : const struct auth_session_info *session_info,
4692 : struct messaging_context *msg_ctx,
4693 : const char *servername,
4694 : union spoolss_PrinterInfo **info,
4695 : uint32_t *count)
4696 : {
4697 68 : DEBUG(4,("enum_all_printers_info_2\n"));
4698 :
4699 68 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4700 : servername, 2, 0, info, count);
4701 : }
4702 :
4703 : /********************************************************************
4704 : * handle enumeration of printers at level 1
4705 : ********************************************************************/
4706 :
4707 72 : static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4708 : const struct auth_session_info *session_info,
4709 : struct messaging_context *msg_ctx,
4710 : uint32_t flags,
4711 : const char *servername,
4712 : union spoolss_PrinterInfo **info,
4713 : uint32_t *count)
4714 : {
4715 : /* Not all the flags are equals */
4716 :
4717 72 : if (flags & PRINTER_ENUM_LOCAL) {
4718 72 : return enum_all_printers_info_1_local(mem_ctx, session_info,
4719 : msg_ctx, servername, info, count);
4720 : }
4721 :
4722 0 : if (flags & PRINTER_ENUM_NAME) {
4723 0 : return enum_all_printers_info_1_name(mem_ctx, session_info,
4724 : msg_ctx, servername, info,
4725 : count);
4726 : }
4727 :
4728 0 : if (flags & PRINTER_ENUM_NETWORK) {
4729 0 : return enum_all_printers_info_1_network(mem_ctx, session_info,
4730 : msg_ctx, servername, info,
4731 : count);
4732 : }
4733 :
4734 0 : return WERR_OK; /* NT4sp5 does that */
4735 : }
4736 :
4737 : /********************************************************************
4738 : * handle enumeration of printers at level 2
4739 : ********************************************************************/
4740 :
4741 68 : static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4742 : const struct auth_session_info *session_info,
4743 : struct messaging_context *msg_ctx,
4744 : uint32_t flags,
4745 : const char *servername,
4746 : union spoolss_PrinterInfo **info,
4747 : uint32_t *count)
4748 : {
4749 68 : if (flags & PRINTER_ENUM_LOCAL) {
4750 :
4751 52 : return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4752 : servername,
4753 : info, count);
4754 : }
4755 :
4756 16 : if (flags & PRINTER_ENUM_NAME) {
4757 16 : if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4758 0 : return WERR_INVALID_NAME;
4759 : }
4760 :
4761 16 : return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4762 : servername,
4763 : info, count);
4764 : }
4765 :
4766 0 : if (flags & PRINTER_ENUM_REMOTE) {
4767 0 : return WERR_INVALID_LEVEL;
4768 : }
4769 :
4770 0 : return WERR_OK;
4771 : }
4772 :
4773 : /********************************************************************
4774 : * handle enumeration of printers at level 4
4775 : ********************************************************************/
4776 :
4777 16 : static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4778 : const struct auth_session_info *session_info,
4779 : struct messaging_context *msg_ctx,
4780 : uint32_t flags,
4781 : const char *servername,
4782 : union spoolss_PrinterInfo **info,
4783 : uint32_t *count)
4784 : {
4785 16 : DEBUG(4,("enum_all_printers_info_4\n"));
4786 :
4787 16 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4788 : servername, 4, flags, info, count);
4789 : }
4790 :
4791 :
4792 : /********************************************************************
4793 : * handle enumeration of printers at level 5
4794 : ********************************************************************/
4795 :
4796 16 : static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4797 : const struct auth_session_info *session_info,
4798 : struct messaging_context *msg_ctx,
4799 : uint32_t flags,
4800 : const char *servername,
4801 : union spoolss_PrinterInfo **info,
4802 : uint32_t *count)
4803 : {
4804 16 : DEBUG(4,("enum_all_printers_info_5\n"));
4805 :
4806 16 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4807 : servername, 5, flags, info, count);
4808 : }
4809 :
4810 : /****************************************************************
4811 : _spoolss_EnumPrinters
4812 : ****************************************************************/
4813 :
4814 180 : WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4815 : struct spoolss_EnumPrinters *r)
4816 : {
4817 180 : const struct auth_session_info *session_info = get_session_info_system();
4818 0 : WERROR result;
4819 :
4820 : /* that's an [in out] buffer */
4821 :
4822 180 : if (!r->in.buffer && (r->in.offered != 0)) {
4823 0 : return WERR_INVALID_PARAMETER;
4824 : }
4825 :
4826 180 : DEBUG(4,("_spoolss_EnumPrinters\n"));
4827 :
4828 180 : *r->out.needed = 0;
4829 180 : *r->out.count = 0;
4830 180 : *r->out.info = NULL;
4831 :
4832 : /*
4833 : * Level 1:
4834 : * flags==PRINTER_ENUM_NAME
4835 : * if name=="" then enumerates all printers
4836 : * if name!="" then enumerate the printer
4837 : * flags==PRINTER_ENUM_REMOTE
4838 : * name is NULL, enumerate printers
4839 : * Level 2: name!="" enumerates printers, name can't be NULL
4840 : * Level 3: doesn't exist
4841 : * Level 4: does a local registry lookup
4842 : * Level 5: same as Level 2
4843 : */
4844 :
4845 180 : if (r->in.server && r->in.server[0] == '\0') {
4846 80 : r->in.server = NULL;
4847 : }
4848 :
4849 180 : switch (r->in.level) {
4850 8 : case 0:
4851 8 : result = enumprinters_level0(p->mem_ctx, session_info,
4852 : p->msg_ctx, r->in.flags,
4853 : r->in.server,
4854 : r->out.info, r->out.count);
4855 8 : break;
4856 72 : case 1:
4857 72 : result = enumprinters_level1(p->mem_ctx, session_info,
4858 : p->msg_ctx, r->in.flags,
4859 : r->in.server,
4860 : r->out.info, r->out.count);
4861 72 : break;
4862 68 : case 2:
4863 68 : result = enumprinters_level2(p->mem_ctx, session_info,
4864 : p->msg_ctx, r->in.flags,
4865 : r->in.server,
4866 : r->out.info, r->out.count);
4867 68 : break;
4868 16 : case 4:
4869 16 : result = enumprinters_level4(p->mem_ctx, session_info,
4870 : p->msg_ctx, r->in.flags,
4871 : r->in.server,
4872 : r->out.info, r->out.count);
4873 16 : break;
4874 16 : case 5:
4875 16 : result = enumprinters_level5(p->mem_ctx, session_info,
4876 : p->msg_ctx, r->in.flags,
4877 : r->in.server,
4878 : r->out.info, r->out.count);
4879 16 : break;
4880 0 : default:
4881 0 : return WERR_INVALID_LEVEL;
4882 : }
4883 :
4884 180 : if (!W_ERROR_IS_OK(result)) {
4885 0 : return result;
4886 : }
4887 :
4888 180 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4889 : spoolss_EnumPrinters,
4890 : *r->out.info, r->in.level,
4891 : *r->out.count);
4892 180 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4893 180 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4894 :
4895 180 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4896 : }
4897 :
4898 : /****************************************************************
4899 : _spoolss_GetPrinter
4900 : ****************************************************************/
4901 :
4902 3512 : WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4903 : struct spoolss_GetPrinter *r)
4904 : {
4905 3512 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4906 3512 : struct spoolss_PrinterInfo2 *info2 = NULL;
4907 3512 : WERROR result = WERR_OK;
4908 0 : int snum;
4909 :
4910 : /* that's an [in out] buffer */
4911 :
4912 3512 : if (!r->in.buffer && (r->in.offered != 0)) {
4913 0 : result = WERR_INVALID_PARAMETER;
4914 0 : goto err_info_free;
4915 : }
4916 :
4917 3512 : *r->out.needed = 0;
4918 :
4919 3512 : if (Printer == NULL) {
4920 0 : result = WERR_INVALID_HANDLE;
4921 0 : goto err_info_free;
4922 : }
4923 :
4924 3512 : if (Printer->printer_type == SPLHND_SERVER) {
4925 :
4926 0 : struct dcerpc_binding_handle *b;
4927 :
4928 72 : if (r->in.level != 3) {
4929 32 : result = WERR_INVALID_LEVEL;
4930 32 : goto err_info_free;
4931 : }
4932 :
4933 40 : result = winreg_printer_binding_handle(p->mem_ctx,
4934 : get_session_info_system(),
4935 : p->msg_ctx,
4936 : &b);
4937 40 : if (!W_ERROR_IS_OK(result)) {
4938 0 : goto err_info_free;
4939 : }
4940 :
4941 40 : result = winreg_get_printserver_secdesc(p->mem_ctx,
4942 : b,
4943 40 : &r->out.info->info3.secdesc);
4944 40 : if (!W_ERROR_IS_OK(result)) {
4945 0 : goto err_info_free;
4946 : }
4947 :
4948 40 : goto done;
4949 : }
4950 :
4951 3440 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4952 0 : result = WERR_INVALID_HANDLE;
4953 0 : goto err_info_free;
4954 : }
4955 :
4956 3440 : result = winreg_get_printer_internal(p->mem_ctx,
4957 : get_session_info_system(),
4958 : p->msg_ctx,
4959 : lp_const_servicename(snum),
4960 : &info2);
4961 3440 : if (!W_ERROR_IS_OK(result)) {
4962 0 : goto err_info_free;
4963 : }
4964 :
4965 3440 : switch (r->in.level) {
4966 236 : case 0:
4967 236 : result = construct_printer_info0(p->mem_ctx,
4968 : get_session_info_system(),
4969 : p->msg_ctx,
4970 : info2,
4971 : Printer->servername,
4972 236 : &r->out.info->info0,
4973 : snum);
4974 236 : break;
4975 88 : case 1:
4976 88 : result = construct_printer_info1(p->mem_ctx, info2,
4977 : PRINTER_ENUM_ICON8,
4978 : Printer->servername,
4979 88 : &r->out.info->info1, snum);
4980 88 : break;
4981 932 : case 2:
4982 932 : result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4983 : Printer->servername,
4984 932 : &r->out.info->info2, snum);
4985 932 : break;
4986 144 : case 3:
4987 144 : result = construct_printer_info3(p->mem_ctx, info2,
4988 : Printer->servername,
4989 144 : &r->out.info->info3, snum);
4990 144 : break;
4991 88 : case 4:
4992 88 : result = construct_printer_info4(p->mem_ctx, info2,
4993 : Printer->servername,
4994 88 : &r->out.info->info4, snum);
4995 88 : break;
4996 88 : case 5:
4997 88 : result = construct_printer_info5(p->mem_ctx, info2,
4998 : Printer->servername,
4999 88 : &r->out.info->info5, snum);
5000 88 : break;
5001 88 : case 6:
5002 88 : result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
5003 : Printer->servername,
5004 88 : &r->out.info->info6, snum);
5005 88 : break;
5006 112 : case 7:
5007 112 : result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
5008 : Printer->servername,
5009 112 : &r->out.info->info7, snum);
5010 112 : break;
5011 1664 : case 8:
5012 1664 : result = construct_printer_info8(p->mem_ctx, info2,
5013 : Printer->servername,
5014 1664 : &r->out.info->info8, snum);
5015 1664 : break;
5016 0 : default:
5017 0 : result = WERR_INVALID_LEVEL;
5018 0 : break;
5019 : }
5020 3440 : TALLOC_FREE(info2);
5021 :
5022 3440 : if (!W_ERROR_IS_OK(result)) {
5023 0 : DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
5024 : r->in.level, win_errstr(result)));
5025 0 : goto err_info_free;
5026 : }
5027 3440 : done:
5028 3480 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
5029 : r->out.info, r->in.level);
5030 3480 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5031 :
5032 3480 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5033 :
5034 32 : err_info_free:
5035 32 : TALLOC_FREE(r->out.info);
5036 32 : return result;
5037 : }
5038 :
5039 : /********************************************************************
5040 : ********************************************************************/
5041 :
5042 : #define FILL_DRIVER_STRING(mem_ctx, in, out) \
5043 : do { \
5044 : if (in && strlen(in)) { \
5045 : out = talloc_strdup(mem_ctx, in); \
5046 : } else { \
5047 : out = talloc_strdup(mem_ctx, ""); \
5048 : } \
5049 : W_ERROR_HAVE_NO_MEMORY(out); \
5050 : } while (0);
5051 :
5052 : #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
5053 : do { \
5054 : if (in && strlen(in)) { \
5055 : out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
5056 : } else { \
5057 : out = talloc_strdup(mem_ctx, ""); \
5058 : } \
5059 : W_ERROR_HAVE_NO_MEMORY(out); \
5060 : } while (0);
5061 :
5062 0 : static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
5063 : const char **string_array,
5064 : const char ***presult,
5065 : const char *cservername,
5066 : const char *arch,
5067 : int version)
5068 : {
5069 0 : size_t i;
5070 0 : size_t num_strings = 0;
5071 0 : const char **array = NULL;
5072 :
5073 0 : if (string_array == NULL) {
5074 0 : return WERR_INVALID_PARAMETER;
5075 : }
5076 :
5077 0 : for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
5078 0 : const char *str = NULL;
5079 :
5080 0 : if (cservername == NULL || arch == NULL) {
5081 0 : FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
5082 : } else {
5083 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
5084 : }
5085 :
5086 0 : if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5087 0 : TALLOC_FREE(array);
5088 0 : return WERR_NOT_ENOUGH_MEMORY;
5089 : }
5090 : }
5091 :
5092 0 : if (i > 0) {
5093 0 : ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5094 : &array, &num_strings);
5095 : }
5096 :
5097 0 : if (presult != NULL) {
5098 0 : *presult = array;
5099 : } else {
5100 0 : talloc_free(array);
5101 : }
5102 :
5103 0 : return WERR_OK;
5104 : }
5105 :
5106 : /********************************************************************
5107 : * fill a spoolss_DriverInfo1 struct
5108 : ********************************************************************/
5109 :
5110 0 : static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5111 : struct spoolss_DriverInfo1 *r,
5112 : const struct spoolss_DriverInfo8 *driver,
5113 : const char *servername)
5114 : {
5115 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5116 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5117 :
5118 0 : return WERR_OK;
5119 : }
5120 :
5121 : /********************************************************************
5122 : * fill a spoolss_DriverInfo2 struct
5123 : ********************************************************************/
5124 :
5125 0 : static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5126 : struct spoolss_DriverInfo2 *r,
5127 : const struct spoolss_DriverInfo8 *driver,
5128 : const char *servername)
5129 :
5130 : {
5131 0 : const char *cservername = canon_servername(servername);
5132 :
5133 0 : r->version = driver->version;
5134 :
5135 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5136 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5137 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5138 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5139 :
5140 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5141 : driver->architecture,
5142 : driver->version,
5143 : driver->driver_path,
5144 0 : r->driver_path);
5145 :
5146 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5147 : driver->architecture,
5148 : driver->version,
5149 : driver->data_file,
5150 0 : r->data_file);
5151 :
5152 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5153 : driver->architecture,
5154 : driver->version,
5155 : driver->config_file,
5156 0 : r->config_file);
5157 :
5158 0 : return WERR_OK;
5159 : }
5160 :
5161 : /********************************************************************
5162 : * fill a spoolss_DriverInfo3 struct
5163 : ********************************************************************/
5164 :
5165 0 : static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5166 : struct spoolss_DriverInfo3 *r,
5167 : const struct spoolss_DriverInfo8 *driver,
5168 : const char *servername)
5169 : {
5170 0 : const char *cservername = canon_servername(servername);
5171 :
5172 0 : r->version = driver->version;
5173 :
5174 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5175 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5176 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5177 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5178 :
5179 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5180 : driver->architecture,
5181 : driver->version,
5182 : driver->driver_path,
5183 0 : r->driver_path);
5184 :
5185 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5186 : driver->architecture,
5187 : driver->version,
5188 : driver->data_file,
5189 0 : r->data_file);
5190 :
5191 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5192 : driver->architecture,
5193 : driver->version,
5194 : driver->config_file,
5195 0 : r->config_file);
5196 :
5197 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5198 : driver->architecture,
5199 : driver->version,
5200 : driver->help_file,
5201 0 : r->help_file);
5202 :
5203 0 : FILL_DRIVER_STRING(mem_ctx,
5204 : driver->monitor_name,
5205 0 : r->monitor_name);
5206 :
5207 0 : FILL_DRIVER_STRING(mem_ctx,
5208 : driver->default_datatype,
5209 0 : r->default_datatype);
5210 :
5211 0 : return string_array_from_driver_info(mem_ctx,
5212 0 : driver->dependent_files,
5213 : &r->dependent_files,
5214 : cservername,
5215 0 : driver->architecture,
5216 0 : driver->version);
5217 : }
5218 :
5219 : /********************************************************************
5220 : * fill a spoolss_DriverInfo4 struct
5221 : ********************************************************************/
5222 :
5223 0 : static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5224 : struct spoolss_DriverInfo4 *r,
5225 : const struct spoolss_DriverInfo8 *driver,
5226 : const char *servername)
5227 : {
5228 0 : const char *cservername = canon_servername(servername);
5229 0 : WERROR result;
5230 :
5231 0 : r->version = driver->version;
5232 :
5233 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5234 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5235 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5236 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5237 :
5238 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5239 : driver->architecture,
5240 : driver->version,
5241 : driver->driver_path,
5242 0 : r->driver_path);
5243 :
5244 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5245 : driver->architecture,
5246 : driver->version,
5247 : driver->data_file,
5248 0 : r->data_file);
5249 :
5250 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5251 : driver->architecture,
5252 : driver->version,
5253 : driver->config_file,
5254 0 : r->config_file);
5255 :
5256 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5257 : driver->architecture,
5258 : driver->version,
5259 : driver->help_file,
5260 0 : r->help_file);
5261 :
5262 0 : result = string_array_from_driver_info(mem_ctx,
5263 0 : driver->dependent_files,
5264 : &r->dependent_files,
5265 : cservername,
5266 0 : driver->architecture,
5267 0 : driver->version);
5268 0 : if (!W_ERROR_IS_OK(result)) {
5269 0 : return result;
5270 : }
5271 :
5272 0 : FILL_DRIVER_STRING(mem_ctx,
5273 : driver->monitor_name,
5274 0 : r->monitor_name);
5275 :
5276 0 : FILL_DRIVER_STRING(mem_ctx,
5277 : driver->default_datatype,
5278 0 : r->default_datatype);
5279 :
5280 :
5281 0 : result = string_array_from_driver_info(mem_ctx,
5282 0 : driver->previous_names,
5283 : &r->previous_names,
5284 : NULL, NULL, 0);
5285 :
5286 0 : return result;
5287 : }
5288 :
5289 : /********************************************************************
5290 : * fill a spoolss_DriverInfo5 struct
5291 : ********************************************************************/
5292 :
5293 0 : static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5294 : struct spoolss_DriverInfo5 *r,
5295 : const struct spoolss_DriverInfo8 *driver,
5296 : const char *servername)
5297 : {
5298 0 : const char *cservername = canon_servername(servername);
5299 :
5300 0 : r->version = driver->version;
5301 :
5302 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5303 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5304 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5305 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5306 :
5307 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5308 : driver->architecture,
5309 : driver->version,
5310 : driver->driver_path,
5311 0 : r->driver_path);
5312 :
5313 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5314 : driver->architecture,
5315 : driver->version,
5316 : driver->data_file,
5317 0 : r->data_file);
5318 :
5319 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5320 : driver->architecture,
5321 : driver->version,
5322 : driver->config_file,
5323 0 : r->config_file);
5324 :
5325 0 : r->driver_attributes = 0;
5326 0 : r->config_version = 0;
5327 0 : r->driver_version = 0;
5328 :
5329 0 : return WERR_OK;
5330 : }
5331 : /********************************************************************
5332 : * fill a spoolss_DriverInfo6 struct
5333 : ********************************************************************/
5334 :
5335 0 : static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5336 : struct spoolss_DriverInfo6 *r,
5337 : const struct spoolss_DriverInfo8 *driver,
5338 : const char *servername)
5339 : {
5340 0 : const char *cservername = canon_servername(servername);
5341 0 : WERROR result;
5342 :
5343 0 : r->version = driver->version;
5344 :
5345 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5346 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5347 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5348 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5349 :
5350 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5351 : driver->architecture,
5352 : driver->version,
5353 : driver->driver_path,
5354 0 : r->driver_path);
5355 :
5356 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5357 : driver->architecture,
5358 : driver->version,
5359 : driver->data_file,
5360 0 : r->data_file);
5361 :
5362 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5363 : driver->architecture,
5364 : driver->version,
5365 : driver->config_file,
5366 0 : r->config_file);
5367 :
5368 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5369 : driver->architecture,
5370 : driver->version,
5371 : driver->help_file,
5372 0 : r->help_file);
5373 :
5374 0 : FILL_DRIVER_STRING(mem_ctx,
5375 : driver->monitor_name,
5376 0 : r->monitor_name);
5377 :
5378 0 : FILL_DRIVER_STRING(mem_ctx,
5379 : driver->default_datatype,
5380 0 : r->default_datatype);
5381 :
5382 0 : result = string_array_from_driver_info(mem_ctx,
5383 0 : driver->dependent_files,
5384 : &r->dependent_files,
5385 : cservername,
5386 0 : driver->architecture,
5387 0 : driver->version);
5388 0 : if (!W_ERROR_IS_OK(result)) {
5389 0 : return result;
5390 : }
5391 :
5392 0 : result = string_array_from_driver_info(mem_ctx,
5393 0 : driver->previous_names,
5394 : &r->previous_names,
5395 : NULL, NULL, 0);
5396 0 : if (!W_ERROR_IS_OK(result)) {
5397 0 : return result;
5398 : }
5399 :
5400 0 : r->driver_date = driver->driver_date;
5401 0 : r->driver_version = driver->driver_version;
5402 :
5403 0 : FILL_DRIVER_STRING(mem_ctx,
5404 : driver->manufacturer_name,
5405 0 : r->manufacturer_name);
5406 0 : FILL_DRIVER_STRING(mem_ctx,
5407 : driver->manufacturer_url,
5408 0 : r->manufacturer_url);
5409 0 : FILL_DRIVER_STRING(mem_ctx,
5410 : driver->hardware_id,
5411 0 : r->hardware_id);
5412 0 : FILL_DRIVER_STRING(mem_ctx,
5413 : driver->provider,
5414 0 : r->provider);
5415 :
5416 0 : return WERR_OK;
5417 : }
5418 :
5419 : /********************************************************************
5420 : * fill a spoolss_DriverInfo8 struct
5421 : ********************************************************************/
5422 :
5423 0 : static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5424 : struct spoolss_DriverInfo8 *r,
5425 : const struct spoolss_DriverInfo8 *driver,
5426 : const char *servername)
5427 : {
5428 0 : const char *cservername = canon_servername(servername);
5429 0 : WERROR result;
5430 :
5431 0 : r->version = driver->version;
5432 :
5433 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5434 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5435 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5436 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5437 :
5438 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5439 : driver->architecture,
5440 : driver->version,
5441 : driver->driver_path,
5442 0 : r->driver_path);
5443 :
5444 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5445 : driver->architecture,
5446 : driver->version,
5447 : driver->data_file,
5448 0 : r->data_file);
5449 :
5450 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5451 : driver->architecture,
5452 : driver->version,
5453 : driver->config_file,
5454 0 : r->config_file);
5455 :
5456 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5457 : driver->architecture,
5458 : driver->version,
5459 : driver->help_file,
5460 0 : r->help_file);
5461 :
5462 0 : FILL_DRIVER_STRING(mem_ctx,
5463 : driver->monitor_name,
5464 0 : r->monitor_name);
5465 :
5466 0 : FILL_DRIVER_STRING(mem_ctx,
5467 : driver->default_datatype,
5468 0 : r->default_datatype);
5469 :
5470 0 : result = string_array_from_driver_info(mem_ctx,
5471 0 : driver->dependent_files,
5472 : &r->dependent_files,
5473 : cservername,
5474 0 : driver->architecture,
5475 0 : driver->version);
5476 0 : if (!W_ERROR_IS_OK(result)) {
5477 0 : return result;
5478 : }
5479 :
5480 0 : result = string_array_from_driver_info(mem_ctx,
5481 0 : driver->previous_names,
5482 : &r->previous_names,
5483 : NULL, NULL, 0);
5484 0 : if (!W_ERROR_IS_OK(result)) {
5485 0 : return result;
5486 : }
5487 :
5488 0 : r->driver_date = driver->driver_date;
5489 0 : r->driver_version = driver->driver_version;
5490 :
5491 0 : FILL_DRIVER_STRING(mem_ctx,
5492 : driver->manufacturer_name,
5493 0 : r->manufacturer_name);
5494 0 : FILL_DRIVER_STRING(mem_ctx,
5495 : driver->manufacturer_url,
5496 0 : r->manufacturer_url);
5497 0 : FILL_DRIVER_STRING(mem_ctx,
5498 : driver->hardware_id,
5499 0 : r->hardware_id);
5500 0 : FILL_DRIVER_STRING(mem_ctx,
5501 : driver->provider,
5502 0 : r->provider);
5503 :
5504 0 : FILL_DRIVER_STRING(mem_ctx,
5505 : driver->print_processor,
5506 0 : r->print_processor);
5507 0 : FILL_DRIVER_STRING(mem_ctx,
5508 : driver->vendor_setup,
5509 0 : r->vendor_setup);
5510 :
5511 0 : result = string_array_from_driver_info(mem_ctx,
5512 0 : driver->color_profiles,
5513 : &r->color_profiles,
5514 : NULL, NULL, 0);
5515 0 : if (!W_ERROR_IS_OK(result)) {
5516 0 : return result;
5517 : }
5518 :
5519 0 : FILL_DRIVER_STRING(mem_ctx,
5520 : driver->inf_path,
5521 0 : r->inf_path);
5522 :
5523 0 : r->printer_driver_attributes = driver->printer_driver_attributes;
5524 :
5525 0 : result = string_array_from_driver_info(mem_ctx,
5526 0 : driver->core_driver_dependencies,
5527 : &r->core_driver_dependencies,
5528 : NULL, NULL, 0);
5529 0 : if (!W_ERROR_IS_OK(result)) {
5530 0 : return result;
5531 : }
5532 :
5533 0 : r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5534 0 : r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5535 :
5536 0 : return WERR_OK;
5537 : }
5538 :
5539 : #if 0 /* disabled until marshalling issues are resolved - gd */
5540 : /********************************************************************
5541 : ********************************************************************/
5542 :
5543 : static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5544 : struct spoolss_DriverFileInfo *r,
5545 : const char *cservername,
5546 : const char *file_name,
5547 : enum spoolss_DriverFileType file_type,
5548 : uint32_t file_version)
5549 : {
5550 : r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5551 : cservername, file_name);
5552 : W_ERROR_HAVE_NO_MEMORY(r->file_name);
5553 : r->file_type = file_type;
5554 : r->file_version = file_version;
5555 :
5556 : return WERR_OK;
5557 : }
5558 :
5559 : /********************************************************************
5560 : ********************************************************************/
5561 :
5562 : static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5563 : const struct spoolss_DriverInfo8 *driver,
5564 : const char *cservername,
5565 : struct spoolss_DriverFileInfo **info_p,
5566 : uint32_t *count_p)
5567 : {
5568 : struct spoolss_DriverFileInfo *info = NULL;
5569 : uint32_t count = 0;
5570 : WERROR result;
5571 : uint32_t i;
5572 :
5573 : *info_p = NULL;
5574 : *count_p = 0;
5575 :
5576 : if (strlen(driver->driver_path)) {
5577 : info = talloc_realloc(mem_ctx, info,
5578 : struct spoolss_DriverFileInfo,
5579 : count + 1);
5580 : W_ERROR_HAVE_NO_MEMORY(info);
5581 : result = fill_spoolss_DriverFileInfo(info,
5582 : &info[count],
5583 : cservername,
5584 : driver->driver_path,
5585 : SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5586 : 0);
5587 : W_ERROR_NOT_OK_RETURN(result);
5588 : count++;
5589 : }
5590 :
5591 : if (strlen(driver->config_file)) {
5592 : info = talloc_realloc(mem_ctx, info,
5593 : struct spoolss_DriverFileInfo,
5594 : count + 1);
5595 : W_ERROR_HAVE_NO_MEMORY(info);
5596 : result = fill_spoolss_DriverFileInfo(info,
5597 : &info[count],
5598 : cservername,
5599 : driver->config_file,
5600 : SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5601 : 0);
5602 : W_ERROR_NOT_OK_RETURN(result);
5603 : count++;
5604 : }
5605 :
5606 : if (strlen(driver->data_file)) {
5607 : info = talloc_realloc(mem_ctx, info,
5608 : struct spoolss_DriverFileInfo,
5609 : count + 1);
5610 : W_ERROR_HAVE_NO_MEMORY(info);
5611 : result = fill_spoolss_DriverFileInfo(info,
5612 : &info[count],
5613 : cservername,
5614 : driver->data_file,
5615 : SPOOLSS_DRIVER_FILE_TYPE_DATA,
5616 : 0);
5617 : W_ERROR_NOT_OK_RETURN(result);
5618 : count++;
5619 : }
5620 :
5621 : if (strlen(driver->help_file)) {
5622 : info = talloc_realloc(mem_ctx, info,
5623 : struct spoolss_DriverFileInfo,
5624 : count + 1);
5625 : W_ERROR_HAVE_NO_MEMORY(info);
5626 : result = fill_spoolss_DriverFileInfo(info,
5627 : &info[count],
5628 : cservername,
5629 : driver->help_file,
5630 : SPOOLSS_DRIVER_FILE_TYPE_HELP,
5631 : 0);
5632 : W_ERROR_NOT_OK_RETURN(result);
5633 : count++;
5634 : }
5635 :
5636 : for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5637 : info = talloc_realloc(mem_ctx, info,
5638 : struct spoolss_DriverFileInfo,
5639 : count + 1);
5640 : W_ERROR_HAVE_NO_MEMORY(info);
5641 : result = fill_spoolss_DriverFileInfo(info,
5642 : &info[count],
5643 : cservername,
5644 : driver->dependent_files[i],
5645 : SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5646 : 0);
5647 : W_ERROR_NOT_OK_RETURN(result);
5648 : count++;
5649 : }
5650 :
5651 : *info_p = info;
5652 : *count_p = count;
5653 :
5654 : return WERR_OK;
5655 : }
5656 :
5657 : /********************************************************************
5658 : * fill a spoolss_DriverInfo101 struct
5659 : ********************************************************************/
5660 :
5661 : static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5662 : struct spoolss_DriverInfo101 *r,
5663 : const struct spoolss_DriverInfo8 *driver,
5664 : const char *servername)
5665 : {
5666 : const char *cservername = canon_servername(servername);
5667 : WERROR result;
5668 :
5669 : r->version = driver->version;
5670 :
5671 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5672 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5673 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5674 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5675 :
5676 : result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5677 : cservername,
5678 : &r->file_info,
5679 : &r->file_count);
5680 : if (!W_ERROR_IS_OK(result)) {
5681 : return result;
5682 : }
5683 :
5684 : FILL_DRIVER_STRING(mem_ctx,
5685 : driver->monitor_name,
5686 : r->monitor_name);
5687 :
5688 : FILL_DRIVER_STRING(mem_ctx,
5689 : driver->default_datatype,
5690 : r->default_datatype);
5691 :
5692 : result = string_array_from_driver_info(mem_ctx,
5693 : driver->previous_names,
5694 : &r->previous_names,
5695 : NULL, NULL, 0);
5696 : if (!W_ERROR_IS_OK(result)) {
5697 : return result;
5698 : }
5699 :
5700 : r->driver_date = driver->driver_date;
5701 : r->driver_version = driver->driver_version;
5702 :
5703 : FILL_DRIVER_STRING(mem_ctx,
5704 : driver->manufacturer_name,
5705 : r->manufacturer_name);
5706 : FILL_DRIVER_STRING(mem_ctx,
5707 : driver->manufacturer_url,
5708 : r->manufacturer_url);
5709 : FILL_DRIVER_STRING(mem_ctx,
5710 : driver->hardware_id,
5711 : r->hardware_id);
5712 : FILL_DRIVER_STRING(mem_ctx,
5713 : driver->provider,
5714 : r->provider);
5715 :
5716 : return WERR_OK;
5717 : }
5718 : #endif
5719 : /********************************************************************
5720 : ********************************************************************/
5721 :
5722 4 : static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5723 : const struct auth_session_info *session_info,
5724 : struct messaging_context *msg_ctx,
5725 : uint32_t level,
5726 : union spoolss_DriverInfo *r,
5727 : int snum,
5728 : const char *servername,
5729 : const char *architecture,
5730 : uint32_t version)
5731 : {
5732 4 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5733 0 : struct spoolss_DriverInfo8 *driver;
5734 0 : WERROR result;
5735 0 : struct dcerpc_binding_handle *b;
5736 4 : TALLOC_CTX *tmp_ctx = NULL;
5737 :
5738 4 : if (level == 101) {
5739 4 : return WERR_INVALID_LEVEL;
5740 : }
5741 :
5742 0 : tmp_ctx = talloc_new(mem_ctx);
5743 0 : if (!tmp_ctx) {
5744 0 : return WERR_NOT_ENOUGH_MEMORY;
5745 : }
5746 :
5747 0 : result = winreg_printer_binding_handle(tmp_ctx,
5748 : session_info,
5749 : msg_ctx,
5750 : &b);
5751 0 : if (!W_ERROR_IS_OK(result)) {
5752 0 : goto done;
5753 : }
5754 :
5755 0 : result = winreg_get_printer(tmp_ctx, b,
5756 : lp_const_servicename(snum),
5757 : &pinfo2);
5758 0 : if (!W_ERROR_IS_OK(result)) {
5759 0 : DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
5760 : lp_const_servicename(snum), win_errstr(result));
5761 0 : result = WERR_INVALID_PRINTER_NAME;
5762 0 : goto done;
5763 : }
5764 :
5765 0 : if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
5766 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5767 0 : goto done;
5768 : }
5769 :
5770 0 : DBG_INFO("Construct printer driver [%s] for [%s]\n",
5771 : pinfo2->drivername,
5772 : pinfo2->sharename);
5773 :
5774 0 : result = winreg_get_driver(tmp_ctx, b,
5775 : architecture,
5776 0 : pinfo2->drivername, version, &driver);
5777 :
5778 0 : DBG_INFO("winreg_get_driver() status: %s\n",
5779 : win_errstr(result));
5780 :
5781 0 : if (!W_ERROR_IS_OK(result)) {
5782 : /*
5783 : * Is this a W2k client ?
5784 : */
5785 :
5786 0 : if (version < 3) {
5787 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5788 0 : goto done;
5789 : }
5790 :
5791 : /* Yes - try again with a WinNT driver. */
5792 0 : version = 2;
5793 0 : result = winreg_get_driver(tmp_ctx, b,
5794 : architecture,
5795 0 : pinfo2->drivername,
5796 : version, &driver);
5797 0 : DEBUG(8,("construct_printer_driver_level: status: %s\n",
5798 : win_errstr(result)));
5799 0 : if (!W_ERROR_IS_OK(result)) {
5800 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5801 0 : goto done;
5802 : }
5803 : }
5804 :
5805 : /* these are allocated on mem_ctx and not tmp_ctx because they are
5806 : * the 'return value' and need to outlive this call */
5807 0 : switch (level) {
5808 0 : case 1:
5809 0 : result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5810 0 : break;
5811 0 : case 2:
5812 0 : result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5813 0 : break;
5814 0 : case 3:
5815 0 : result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5816 0 : break;
5817 0 : case 4:
5818 0 : result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5819 0 : break;
5820 0 : case 5:
5821 0 : result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5822 0 : break;
5823 0 : case 6:
5824 0 : result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5825 0 : break;
5826 0 : case 8:
5827 0 : result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5828 0 : break;
5829 : #if 0 /* disabled until marshalling issues are resolved - gd */
5830 : case 101:
5831 : result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5832 : break;
5833 : #endif
5834 0 : default:
5835 0 : result = WERR_INVALID_LEVEL;
5836 0 : break;
5837 : }
5838 :
5839 0 : done:
5840 0 : talloc_free(tmp_ctx);
5841 0 : return result;
5842 : }
5843 :
5844 : /****************************************************************
5845 : _spoolss_GetPrinterDriver2
5846 : ****************************************************************/
5847 :
5848 4 : WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5849 : struct spoolss_GetPrinterDriver2 *r)
5850 : {
5851 0 : struct printer_handle *printer;
5852 0 : WERROR result;
5853 4 : uint32_t version = r->in.client_major_version;
5854 :
5855 0 : int snum;
5856 :
5857 : /* that's an [in out] buffer */
5858 :
5859 4 : if (!r->in.buffer && (r->in.offered != 0)) {
5860 0 : result = WERR_INVALID_PARAMETER;
5861 0 : goto err_info_free;
5862 : }
5863 :
5864 4 : DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5865 :
5866 4 : if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5867 0 : DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5868 0 : result = WERR_INVALID_PRINTER_NAME;
5869 0 : goto err_info_free;
5870 : }
5871 :
5872 4 : *r->out.needed = 0;
5873 4 : *r->out.server_major_version = 0;
5874 4 : *r->out.server_minor_version = 0;
5875 :
5876 4 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5877 0 : result = WERR_INVALID_HANDLE;
5878 0 : goto err_info_free;
5879 : }
5880 :
5881 4 : if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5882 0 : DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5883 : "downgrading to v3\n"));
5884 0 : version = SPOOLSS_DRIVER_VERSION_200X;
5885 : }
5886 :
5887 4 : result = construct_printer_driver_info_level(p->mem_ctx,
5888 : get_session_info_system(),
5889 : p->msg_ctx,
5890 : r->in.level, r->out.info,
5891 : snum, printer->servername,
5892 : r->in.architecture,
5893 : version);
5894 4 : if (!W_ERROR_IS_OK(result)) {
5895 4 : goto err_info_free;
5896 : }
5897 :
5898 0 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5899 : r->out.info, r->in.level);
5900 0 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5901 :
5902 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5903 :
5904 4 : err_info_free:
5905 4 : TALLOC_FREE(r->out.info);
5906 4 : return result;
5907 : }
5908 :
5909 :
5910 : /****************************************************************
5911 : _spoolss_StartPagePrinter
5912 : ****************************************************************/
5913 :
5914 1920 : WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5915 : struct spoolss_StartPagePrinter *r)
5916 : {
5917 1920 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5918 :
5919 1920 : if (!Printer) {
5920 0 : DEBUG(3,("_spoolss_StartPagePrinter: "
5921 : "Error in startpageprinter printer handle\n"));
5922 0 : return WERR_INVALID_HANDLE;
5923 : }
5924 :
5925 1920 : Printer->page_started = true;
5926 1920 : return WERR_OK;
5927 : }
5928 :
5929 : /****************************************************************
5930 : _spoolss_EndPagePrinter
5931 : ****************************************************************/
5932 :
5933 1920 : WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5934 : struct spoolss_EndPagePrinter *r)
5935 : {
5936 0 : int snum;
5937 :
5938 1920 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5939 :
5940 1920 : if (!Printer) {
5941 0 : DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5942 : OUR_HANDLE(r->in.handle)));
5943 0 : return WERR_INVALID_HANDLE;
5944 : }
5945 :
5946 1920 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5947 0 : return WERR_INVALID_HANDLE;
5948 :
5949 1920 : Printer->page_started = false;
5950 1920 : print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5951 :
5952 1920 : return WERR_OK;
5953 : }
5954 :
5955 : /****************************************************************
5956 : _spoolss_StartDocPrinter
5957 : ****************************************************************/
5958 :
5959 668 : WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5960 : struct spoolss_StartDocPrinter *r)
5961 : {
5962 668 : struct dcesrv_call_state *dce_call = p->dce_call;
5963 668 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
5964 0 : const struct tsocket_address *remote_address =
5965 668 : dcesrv_connection_get_remote_address(dcesrv_conn);
5966 0 : struct auth_session_info *session_info =
5967 668 : dcesrv_call_session_info(dce_call);
5968 0 : struct spoolss_DocumentInfo1 *info_1;
5969 0 : int snum;
5970 668 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5971 0 : WERROR werr;
5972 0 : char *rhost;
5973 0 : int rc;
5974 :
5975 668 : if (!Printer) {
5976 0 : DEBUG(2,("_spoolss_StartDocPrinter: "
5977 : "Invalid handle (%s:%u:%u)\n",
5978 : OUR_HANDLE(r->in.handle)));
5979 0 : return WERR_INVALID_HANDLE;
5980 : }
5981 :
5982 668 : if (Printer->jobid) {
5983 0 : DEBUG(2, ("_spoolss_StartDocPrinter: "
5984 : "StartDocPrinter called twice! "
5985 : "(existing jobid = %d)\n", Printer->jobid));
5986 0 : return WERR_INVALID_HANDLE;
5987 : }
5988 :
5989 668 : if (r->in.info_ctr->level != 1) {
5990 0 : return WERR_INVALID_LEVEL;
5991 : }
5992 :
5993 668 : info_1 = r->in.info_ctr->info.info1;
5994 :
5995 : /*
5996 : * a nice thing with NT is it doesn't listen to what you tell it.
5997 : * when asked to send _only_ RAW data, it tries to send data
5998 : * in EMF format.
5999 : *
6000 : * So I add checks like in NT Server ...
6001 : */
6002 :
6003 668 : if (info_1->datatype) {
6004 : /*
6005 : * The v4 driver model used in Windows 8 declares print jobs
6006 : * intended to bypass the XPS processing layer by setting
6007 : * datatype to "XPS_PASS" instead of "RAW".
6008 : */
6009 668 : if ((strcmp(info_1->datatype, "RAW") != 0)
6010 224 : && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
6011 0 : *r->out.job_id = 0;
6012 0 : return WERR_INVALID_DATATYPE;
6013 : }
6014 : }
6015 :
6016 : /* get the share number of the printer */
6017 668 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6018 0 : return WERR_INVALID_HANDLE;
6019 : }
6020 :
6021 668 : rc = get_remote_hostname(remote_address,
6022 : &rhost,
6023 : p->mem_ctx);
6024 668 : if (rc < 0) {
6025 0 : return WERR_NOT_ENOUGH_MEMORY;
6026 : }
6027 668 : if (strequal(rhost,"UNKNOWN")) {
6028 668 : rhost = tsocket_address_inet_addr_string(remote_address,
6029 : p->mem_ctx);
6030 668 : if (rhost == NULL) {
6031 0 : return WERR_NOT_ENOUGH_MEMORY;
6032 : }
6033 : }
6034 :
6035 668 : werr = print_job_start(session_info,
6036 : p->msg_ctx,
6037 : rhost,
6038 : snum,
6039 : info_1->document_name,
6040 : info_1->output_file,
6041 : Printer->devmode,
6042 : &Printer->jobid);
6043 :
6044 : /* An error occurred in print_job_start() so return an appropriate
6045 : NT error code. */
6046 :
6047 668 : if (!W_ERROR_IS_OK(werr)) {
6048 0 : return werr;
6049 : }
6050 :
6051 668 : Printer->document_started = true;
6052 668 : *r->out.job_id = Printer->jobid;
6053 :
6054 668 : return WERR_OK;
6055 : }
6056 :
6057 : /****************************************************************
6058 : _spoolss_EndDocPrinter
6059 : ****************************************************************/
6060 :
6061 668 : WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
6062 : struct spoolss_EndDocPrinter *r)
6063 : {
6064 668 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6065 0 : NTSTATUS status;
6066 0 : int snum;
6067 :
6068 668 : if (!Printer) {
6069 0 : DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
6070 : OUR_HANDLE(r->in.handle)));
6071 0 : return WERR_INVALID_HANDLE;
6072 : }
6073 :
6074 668 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6075 0 : return WERR_INVALID_HANDLE;
6076 : }
6077 :
6078 668 : Printer->document_started = false;
6079 668 : status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
6080 668 : if (!NT_STATUS_IS_OK(status)) {
6081 292 : DEBUG(2, ("_spoolss_EndDocPrinter: "
6082 : "print_job_end failed [%s]\n",
6083 : nt_errstr(status)));
6084 : }
6085 :
6086 668 : Printer->jobid = 0;
6087 668 : return ntstatus_to_werror(status);
6088 : }
6089 :
6090 : /****************************************************************
6091 : _spoolss_WritePrinter
6092 : ****************************************************************/
6093 :
6094 1920 : WERROR _spoolss_WritePrinter(struct pipes_struct *p,
6095 : struct spoolss_WritePrinter *r)
6096 : {
6097 0 : ssize_t buffer_written;
6098 0 : int snum;
6099 1920 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6100 :
6101 1920 : if (!Printer) {
6102 0 : DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6103 : OUR_HANDLE(r->in.handle)));
6104 0 : *r->out.num_written = r->in._data_size;
6105 0 : return WERR_INVALID_HANDLE;
6106 : }
6107 :
6108 1920 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6109 0 : return WERR_INVALID_HANDLE;
6110 :
6111 : /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
6112 1920 : buffer_written = print_job_write(global_event_context(),p->msg_ctx,
6113 : snum, Printer->jobid,
6114 1920 : (const char *)r->in.data.data,
6115 1920 : (size_t)r->in._data_size);
6116 1920 : if (buffer_written == (ssize_t)-1) {
6117 0 : *r->out.num_written = 0;
6118 0 : if (errno == ENOSPC)
6119 0 : return WERR_NO_SPOOL_SPACE;
6120 : else
6121 0 : return WERR_ACCESS_DENIED;
6122 : }
6123 :
6124 1920 : *r->out.num_written = r->in._data_size;
6125 :
6126 1920 : return WERR_OK;
6127 : }
6128 :
6129 : /********************************************************************
6130 : * api_spoolss_getprinter
6131 : * called from the spoolss dispatcher
6132 : *
6133 : ********************************************************************/
6134 :
6135 104 : static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6136 : struct pipes_struct *p)
6137 : {
6138 104 : struct dcesrv_call_state *dce_call = p->dce_call;
6139 0 : struct auth_session_info *session_info =
6140 104 : dcesrv_call_session_info(dce_call);
6141 0 : int snum;
6142 104 : WERROR errcode = WERR_INVALID_FUNCTION;
6143 104 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6144 :
6145 104 : if (!Printer) {
6146 0 : DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6147 : OUR_HANDLE(handle)));
6148 0 : return WERR_INVALID_HANDLE;
6149 : }
6150 :
6151 104 : if (!get_printer_snum(p, handle, &snum, NULL))
6152 0 : return WERR_INVALID_HANDLE;
6153 :
6154 104 : switch (command) {
6155 52 : case SPOOLSS_PRINTER_CONTROL_PAUSE:
6156 52 : errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6157 52 : break;
6158 40 : case SPOOLSS_PRINTER_CONTROL_RESUME:
6159 : case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6160 40 : errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6161 40 : break;
6162 12 : case SPOOLSS_PRINTER_CONTROL_PURGE:
6163 12 : errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6164 12 : break;
6165 0 : default:
6166 0 : return WERR_INVALID_LEVEL;
6167 : }
6168 :
6169 104 : return errcode;
6170 : }
6171 :
6172 :
6173 : /****************************************************************
6174 : _spoolss_AbortPrinter
6175 : * From MSDN: "Deletes printer's spool file if printer is configured
6176 : * for spooling"
6177 : ****************************************************************/
6178 :
6179 0 : WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6180 : struct spoolss_AbortPrinter *r)
6181 : {
6182 0 : struct dcesrv_call_state *dce_call = p->dce_call;
6183 0 : struct auth_session_info *session_info =
6184 0 : dcesrv_call_session_info(dce_call);
6185 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6186 0 : int snum;
6187 0 : WERROR errcode = WERR_OK;
6188 :
6189 0 : if (!Printer) {
6190 0 : DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6191 : OUR_HANDLE(r->in.handle)));
6192 0 : return WERR_INVALID_HANDLE;
6193 : }
6194 :
6195 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6196 0 : return WERR_INVALID_HANDLE;
6197 :
6198 0 : if (!Printer->document_started) {
6199 0 : return WERR_SPL_NO_STARTDOC;
6200 : }
6201 :
6202 0 : errcode = print_job_delete(session_info,
6203 : p->msg_ctx,
6204 : snum,
6205 : Printer->jobid);
6206 :
6207 0 : return errcode;
6208 : }
6209 :
6210 : /********************************************************************
6211 : * called by spoolss_api_setprinter
6212 : * when updating a printer description
6213 : ********************************************************************/
6214 :
6215 120 : static WERROR update_printer_sec(struct policy_handle *handle,
6216 : struct pipes_struct *p,
6217 : struct sec_desc_buf *secdesc_ctr)
6218 : {
6219 120 : struct spoolss_security_descriptor *new_secdesc = NULL;
6220 120 : struct spoolss_security_descriptor *old_secdesc = NULL;
6221 120 : const char *printer = NULL;
6222 0 : WERROR result;
6223 120 : int snum = -1;
6224 120 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6225 0 : struct dcerpc_binding_handle *b;
6226 120 : TALLOC_CTX *tmp_ctx = NULL;
6227 120 : bool ok = false;
6228 :
6229 120 : if (!Printer) {
6230 0 : DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6231 : OUR_HANDLE(handle)));
6232 :
6233 0 : result = WERR_INVALID_HANDLE;
6234 0 : goto done;
6235 : }
6236 :
6237 120 : if (secdesc_ctr == NULL) {
6238 0 : DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6239 0 : result = WERR_INVALID_PARAMETER;
6240 0 : goto done;
6241 : }
6242 :
6243 120 : switch (Printer->printer_type) {
6244 8 : case SPLHND_SERVER:
6245 8 : break;
6246 112 : case SPLHND_PRINTER:
6247 112 : if (!get_printer_snum(p, handle, &snum, NULL)) {
6248 0 : DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6249 : OUR_HANDLE(handle)));
6250 0 : result = WERR_INVALID_HANDLE;
6251 0 : goto done;
6252 : }
6253 112 : printer = lp_const_servicename(snum);
6254 112 : break;
6255 0 : default:
6256 0 : break;
6257 : }
6258 :
6259 : /* Check the user has permissions to change the security
6260 : descriptor. By experimentation with two NT machines, the user
6261 : requires Full Access to the printer to change security
6262 : information. */
6263 :
6264 120 : switch (Printer->printer_type) {
6265 8 : case SPLHND_SERVER:
6266 8 : ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6267 8 : break;
6268 112 : case SPLHND_PRINTER:
6269 112 : ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6270 112 : break;
6271 0 : default:
6272 0 : break;
6273 : }
6274 :
6275 120 : if (!ok) {
6276 0 : DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6277 : "(access_granted: 0x%08x)\n", Printer->access_granted));
6278 0 : result = WERR_ACCESS_DENIED;
6279 0 : goto done;
6280 : }
6281 :
6282 120 : tmp_ctx = talloc_new(p->mem_ctx);
6283 120 : if (!tmp_ctx) {
6284 0 : return WERR_NOT_ENOUGH_MEMORY;
6285 : }
6286 :
6287 120 : result = winreg_printer_binding_handle(tmp_ctx,
6288 : get_session_info_system(),
6289 : p->msg_ctx,
6290 : &b);
6291 120 : if (!W_ERROR_IS_OK(result)) {
6292 0 : goto done;
6293 : }
6294 :
6295 : /* NT seems to like setting the security descriptor even though
6296 : nothing may have actually changed. */
6297 :
6298 120 : if (printer != NULL) {
6299 112 : result = winreg_get_printer_secdesc(tmp_ctx, b,
6300 : printer,
6301 : &old_secdesc);
6302 : } else {
6303 8 : result = winreg_get_printserver_secdesc(tmp_ctx, b,
6304 : &old_secdesc);
6305 : }
6306 120 : if (!W_ERROR_IS_OK(result)) {
6307 0 : DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6308 0 : result = WERR_INVALID_HANDLE;
6309 0 : goto done;
6310 : }
6311 :
6312 120 : if (DEBUGLEVEL >= 10) {
6313 0 : struct dom_sid_buf buf;
6314 0 : struct security_acl *the_acl;
6315 0 : int i;
6316 :
6317 0 : the_acl = old_secdesc->dacl;
6318 0 : DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6319 : printer, the_acl->num_aces));
6320 :
6321 0 : for (i = 0; i < the_acl->num_aces; i++) {
6322 0 : DEBUG(10, ("%s 0x%08x\n",
6323 : dom_sid_str_buf(
6324 : &the_acl->aces[i].trustee,
6325 : &buf),
6326 : the_acl->aces[i].access_mask));
6327 : }
6328 :
6329 0 : the_acl = secdesc_ctr->sd->dacl;
6330 :
6331 0 : if (the_acl) {
6332 0 : DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6333 : printer, the_acl->num_aces));
6334 :
6335 0 : for (i = 0; i < the_acl->num_aces; i++) {
6336 0 : DEBUG(10, ("%s 0x%08x\n",
6337 : dom_sid_str_buf(
6338 : &the_acl->aces[i].trustee,
6339 : &buf),
6340 : the_acl->aces[i].access_mask));
6341 : }
6342 : } else {
6343 0 : DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6344 : }
6345 : }
6346 :
6347 120 : new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6348 120 : if (new_secdesc == NULL) {
6349 0 : result = WERR_NOT_ENOUGH_MEMORY;
6350 0 : goto done;
6351 : }
6352 :
6353 120 : if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6354 56 : result = WERR_OK;
6355 56 : goto done;
6356 : }
6357 :
6358 64 : if (printer != NULL) {
6359 56 : result = winreg_set_printer_secdesc(tmp_ctx, b,
6360 : printer,
6361 : new_secdesc);
6362 : } else {
6363 8 : result = winreg_set_printserver_secdesc(tmp_ctx, b,
6364 : new_secdesc);
6365 : }
6366 :
6367 120 : done:
6368 120 : talloc_free(tmp_ctx);
6369 120 : return result;
6370 : }
6371 :
6372 : /********************************************************************
6373 : Canonicalize printer info from a client
6374 : ********************************************************************/
6375 :
6376 100 : static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6377 : struct spoolss_SetPrinterInfo2 *info2,
6378 : int snum)
6379 : {
6380 0 : fstring printername;
6381 0 : const char *p;
6382 :
6383 100 : DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6384 : "portname=%s drivername=%s comment=%s location=%s\n",
6385 : info2->servername, info2->printername, info2->sharename,
6386 : info2->portname, info2->drivername, info2->comment,
6387 : info2->location));
6388 :
6389 : /* we force some elements to "correct" values */
6390 100 : info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6391 100 : if (info2->servername == NULL) {
6392 0 : return false;
6393 : }
6394 100 : info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6395 100 : if (info2->sharename == NULL) {
6396 0 : return false;
6397 : }
6398 :
6399 : /* check to see if we allow printername != sharename */
6400 100 : if (lp_force_printername(snum)) {
6401 0 : info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6402 : lp_netbios_name(), info2->sharename);
6403 : } else {
6404 : /* make sure printername is in \\server\printername format */
6405 100 : fstrcpy(printername, info2->printername);
6406 100 : p = printername;
6407 100 : if ( printername[0] == '\\' && printername[1] == '\\' ) {
6408 56 : if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6409 56 : p++;
6410 : }
6411 :
6412 100 : info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6413 : lp_netbios_name(), p);
6414 : }
6415 100 : if (info2->printername == NULL) {
6416 0 : return false;
6417 : }
6418 :
6419 100 : info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6420 100 : info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6421 :
6422 100 : return true;
6423 : }
6424 :
6425 : /****************************************************************************
6426 : ****************************************************************************/
6427 :
6428 0 : static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6429 : {
6430 0 : const struct loadparm_substitution *lp_sub =
6431 0 : loadparm_s3_global_substitution();
6432 0 : char *cmd = lp_addport_command(talloc_tos(), lp_sub);
6433 0 : char *command = NULL;
6434 0 : int ret;
6435 0 : bool is_print_op = false;
6436 :
6437 0 : if ( !*cmd ) {
6438 0 : return WERR_ACCESS_DENIED;
6439 : }
6440 :
6441 0 : command = talloc_asprintf(ctx,
6442 : "%s \"%s\" \"%s\"", cmd, portname, uri );
6443 0 : if (!command) {
6444 0 : return WERR_NOT_ENOUGH_MEMORY;
6445 : }
6446 :
6447 0 : if ( token )
6448 0 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6449 :
6450 0 : DEBUG(10,("Running [%s]\n", command));
6451 :
6452 : /********* BEGIN SePrintOperatorPrivilege **********/
6453 :
6454 0 : if ( is_print_op )
6455 0 : become_root();
6456 :
6457 0 : ret = smbrun(command, NULL, NULL);
6458 :
6459 0 : if ( is_print_op )
6460 0 : unbecome_root();
6461 :
6462 : /********* END SePrintOperatorPrivilege **********/
6463 :
6464 0 : DEBUGADD(10,("returned [%d]\n", ret));
6465 :
6466 0 : TALLOC_FREE(command);
6467 :
6468 0 : if ( ret != 0 ) {
6469 0 : return WERR_ACCESS_DENIED;
6470 : }
6471 :
6472 0 : return WERR_OK;
6473 : }
6474 :
6475 : /****************************************************************************
6476 : ****************************************************************************/
6477 :
6478 4902 : static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6479 : int snum)
6480 : {
6481 : /*
6482 : * As we do not know if we are embedded in the file server process
6483 : * or not, we have to pretend that all shares are in use.
6484 : */
6485 4902 : return true;
6486 : }
6487 :
6488 66 : static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6489 : struct spoolss_SetPrinterInfo2 *info2,
6490 : const char *remote_machine,
6491 : struct messaging_context *msg_ctx)
6492 : {
6493 0 : const struct loadparm_substitution *lp_sub =
6494 66 : loadparm_s3_global_substitution();
6495 66 : char *cmd = lp_addprinter_command(talloc_tos(), lp_sub);
6496 0 : char **qlines;
6497 66 : char *command = NULL;
6498 0 : int numlines;
6499 0 : int ret;
6500 0 : int fd;
6501 66 : bool is_print_op = false;
6502 :
6503 66 : if (!remote_machine) {
6504 0 : return false;
6505 : }
6506 :
6507 66 : command = talloc_asprintf(ctx,
6508 : "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6509 : cmd, info2->printername, info2->sharename,
6510 : info2->portname, info2->drivername,
6511 : info2->location, info2->comment, remote_machine);
6512 66 : if (!command) {
6513 0 : return false;
6514 : }
6515 :
6516 66 : if ( token )
6517 66 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6518 :
6519 66 : DEBUG(10,("Running [%s]\n", command));
6520 :
6521 : /********* BEGIN SePrintOperatorPrivilege **********/
6522 :
6523 66 : if ( is_print_op )
6524 0 : become_root();
6525 :
6526 66 : ret = smbrun(command, &fd, NULL);
6527 66 : if (ret == 0) {
6528 : /* Tell everyone we updated smb.conf. */
6529 66 : messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
6530 : }
6531 :
6532 66 : if ( is_print_op )
6533 0 : unbecome_root();
6534 :
6535 : /********* END SePrintOperatorPrivilege **********/
6536 :
6537 66 : DEBUGADD(10,("returned [%d]\n", ret));
6538 :
6539 66 : TALLOC_FREE(command);
6540 :
6541 66 : if ( ret != 0 ) {
6542 0 : if (fd != -1)
6543 0 : close(fd);
6544 0 : return false;
6545 : }
6546 :
6547 : /* reload our services immediately */
6548 66 : become_root();
6549 66 : reload_services(NULL, spoolss_conn_snum_used, false);
6550 66 : unbecome_root();
6551 :
6552 66 : numlines = 0;
6553 : /* Get lines and convert them back to dos-codepage */
6554 66 : qlines = fd_lines_load(fd, &numlines, 0, NULL);
6555 66 : DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6556 66 : close(fd);
6557 :
6558 : /* Set the portname to what the script says the portname should be. */
6559 : /* but don't require anything to be return from the script exit a good error code */
6560 :
6561 66 : if (numlines) {
6562 : /* Set the portname to what the script says the portname should be. */
6563 0 : info2->portname = talloc_strdup(ctx, qlines[0]);
6564 0 : DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6565 : }
6566 :
6567 66 : TALLOC_FREE(qlines);
6568 66 : return true;
6569 : }
6570 :
6571 100 : static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6572 : const struct auth_session_info *session_info,
6573 : struct messaging_context *msg_ctx,
6574 : int snum,
6575 : struct spoolss_SetPrinterInfo2 *printer,
6576 : struct spoolss_PrinterInfo2 *old_printer)
6577 : {
6578 100 : bool force_update = (old_printer == NULL);
6579 0 : const char *dnsdomname;
6580 0 : const char *longname;
6581 0 : const char *uncname;
6582 0 : const char *spooling;
6583 0 : DATA_BLOB buffer;
6584 100 : WERROR result = WERR_OK;
6585 0 : struct dcerpc_binding_handle *b;
6586 0 : TALLOC_CTX *tmp_ctx;
6587 0 : bool ok;
6588 :
6589 100 : tmp_ctx = talloc_new(mem_ctx);
6590 100 : if (!tmp_ctx) {
6591 0 : return WERR_NOT_ENOUGH_MEMORY;
6592 : }
6593 :
6594 100 : result = winreg_printer_binding_handle(tmp_ctx,
6595 : session_info,
6596 : msg_ctx,
6597 : &b);
6598 100 : if (!W_ERROR_IS_OK(result)) {
6599 0 : goto done;
6600 : }
6601 :
6602 100 : if (printer->drivername != NULL &&
6603 84 : (force_update ||
6604 84 : !strequal(printer->drivername, old_printer->drivername))) {
6605 24 : ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6606 24 : if (!ok) {
6607 0 : DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6608 0 : result = WERR_INVALID_DATA;
6609 0 : goto done;
6610 : }
6611 24 : result = winreg_set_printer_dataex(tmp_ctx, b,
6612 : printer->sharename,
6613 : SPOOL_DSSPOOLER_KEY,
6614 : SPOOL_REG_DRIVERNAME,
6615 : REG_SZ,
6616 : buffer.data,
6617 24 : buffer.length);
6618 24 : if (!W_ERROR_IS_OK(result)) {
6619 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6620 0 : goto done;
6621 : }
6622 :
6623 24 : if (!force_update) {
6624 8 : DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6625 : printer->drivername));
6626 :
6627 8 : notify_printer_driver(global_event_context(), msg_ctx,
6628 8 : snum, printer->drivername ?
6629 : printer->drivername : "");
6630 : }
6631 : }
6632 :
6633 100 : if (printer->comment != NULL &&
6634 84 : (force_update ||
6635 84 : !strequal(printer->comment, old_printer->comment))) {
6636 34 : ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6637 34 : if (!ok) {
6638 0 : DEBUG(0, ("comment data corrupted\n"));
6639 0 : result = WERR_INVALID_DATA;
6640 0 : goto done;
6641 : }
6642 34 : result = winreg_set_printer_dataex(tmp_ctx, b,
6643 : printer->sharename,
6644 : SPOOL_DSSPOOLER_KEY,
6645 : SPOOL_REG_DESCRIPTION,
6646 : REG_SZ,
6647 : buffer.data,
6648 34 : buffer.length);
6649 34 : if (!W_ERROR_IS_OK(result)) {
6650 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6651 0 : goto done;
6652 : }
6653 :
6654 34 : if (!force_update) {
6655 34 : notify_printer_comment(global_event_context(), msg_ctx,
6656 34 : snum, printer->comment ?
6657 : printer->comment : "");
6658 : }
6659 : }
6660 :
6661 100 : if (printer->sharename != NULL &&
6662 84 : (force_update ||
6663 84 : !strequal(printer->sharename, old_printer->sharename))) {
6664 16 : ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6665 16 : if (!ok) {
6666 0 : DEBUG(0, ("sharename data corrupted\n"));
6667 0 : result = WERR_INVALID_DATA;
6668 0 : goto done;
6669 : }
6670 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6671 : printer->sharename,
6672 : SPOOL_DSSPOOLER_KEY,
6673 : SPOOL_REG_PRINTSHARENAME,
6674 : REG_SZ,
6675 : buffer.data,
6676 16 : buffer.length);
6677 16 : if (!W_ERROR_IS_OK(result)) {
6678 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6679 0 : goto done;
6680 : }
6681 :
6682 16 : if (!force_update) {
6683 0 : notify_printer_sharename(global_event_context(),
6684 : msg_ctx,
6685 0 : snum, printer->sharename ?
6686 : printer->sharename : "");
6687 : }
6688 :
6689 : /* name change, purge any cache entries for the old */
6690 16 : prune_printername_cache();
6691 : }
6692 :
6693 100 : if (printer->printername != NULL &&
6694 84 : (force_update ||
6695 84 : !strequal(printer->printername, old_printer->printername))) {
6696 0 : const char *p;
6697 :
6698 100 : p = strrchr(printer->printername, '\\' );
6699 100 : if (p != NULL) {
6700 100 : p++;
6701 : } else {
6702 0 : p = printer->printername;
6703 : }
6704 :
6705 100 : ok = push_reg_sz(tmp_ctx, &buffer, p);
6706 100 : if (!ok) {
6707 0 : DEBUG(0, ("printername data corrupted\n"));
6708 0 : result = WERR_INVALID_DATA;
6709 0 : goto done;
6710 : }
6711 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6712 : printer->sharename,
6713 : SPOOL_DSSPOOLER_KEY,
6714 : SPOOL_REG_PRINTERNAME,
6715 : REG_SZ,
6716 : buffer.data,
6717 100 : buffer.length);
6718 100 : if (!W_ERROR_IS_OK(result)) {
6719 0 : DBG_ERR("Failed to set %s\n", SPOOL_REG_PRINTERNAME);
6720 0 : goto done;
6721 : }
6722 :
6723 100 : if (!force_update) {
6724 84 : notify_printer_printername(global_event_context(),
6725 : msg_ctx, snum, p ? p : "");
6726 : }
6727 :
6728 : /* name change, purge any cache entries for the old */
6729 100 : prune_printername_cache();
6730 : }
6731 :
6732 100 : if (printer->portname != NULL &&
6733 84 : (force_update ||
6734 84 : !strequal(printer->portname, old_printer->portname))) {
6735 16 : ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6736 16 : if (!ok) {
6737 0 : DEBUG(0, ("portname data corrupted\n"));
6738 0 : result = WERR_INVALID_DATA;
6739 0 : goto done;
6740 : }
6741 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6742 : printer->sharename,
6743 : SPOOL_DSSPOOLER_KEY,
6744 : SPOOL_REG_PORTNAME,
6745 : REG_SZ,
6746 : buffer.data,
6747 16 : buffer.length);
6748 16 : if (!W_ERROR_IS_OK(result)) {
6749 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6750 0 : goto done;
6751 : }
6752 :
6753 16 : if (!force_update) {
6754 0 : notify_printer_port(global_event_context(),
6755 0 : msg_ctx, snum, printer->portname ?
6756 : printer->portname : "");
6757 : }
6758 : }
6759 :
6760 100 : if (printer->location != NULL &&
6761 84 : (force_update ||
6762 84 : !strequal(printer->location, old_printer->location))) {
6763 8 : ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6764 8 : if (!ok) {
6765 0 : DEBUG(0, ("location data corrupted\n"));
6766 0 : result = WERR_INVALID_DATA;
6767 0 : goto done;
6768 : }
6769 8 : result = winreg_set_printer_dataex(tmp_ctx, b,
6770 : printer->sharename,
6771 : SPOOL_DSSPOOLER_KEY,
6772 : SPOOL_REG_LOCATION,
6773 : REG_SZ,
6774 : buffer.data,
6775 8 : buffer.length);
6776 8 : if (!W_ERROR_IS_OK(result)) {
6777 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6778 0 : goto done;
6779 : }
6780 :
6781 8 : if (!force_update) {
6782 8 : notify_printer_location(global_event_context(),
6783 : msg_ctx, snum,
6784 8 : printer->location ?
6785 : printer->location : "");
6786 : }
6787 : }
6788 :
6789 100 : if (printer->sepfile != NULL &&
6790 84 : (force_update ||
6791 84 : !strequal(printer->sepfile, old_printer->sepfile))) {
6792 0 : ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6793 0 : if (!ok) {
6794 0 : DEBUG(0, ("sepfile data corrupted\n"));
6795 0 : result = WERR_INVALID_DATA;
6796 0 : goto done;
6797 : }
6798 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6799 : printer->sharename,
6800 : SPOOL_DSSPOOLER_KEY,
6801 : SPOOL_REG_PRINTSEPARATORFILE,
6802 : REG_SZ,
6803 : buffer.data,
6804 0 : buffer.length);
6805 0 : if (!W_ERROR_IS_OK(result)) {
6806 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6807 0 : goto done;
6808 : }
6809 :
6810 0 : if (!force_update) {
6811 0 : notify_printer_sepfile(global_event_context(),
6812 : msg_ctx, snum,
6813 0 : printer->sepfile ?
6814 : printer->sepfile : "");
6815 : }
6816 : }
6817 :
6818 100 : if (printer->starttime != 0 &&
6819 0 : (force_update ||
6820 0 : printer->starttime != old_printer->starttime)) {
6821 0 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6822 0 : SIVAL(buffer.data, 0, printer->starttime);
6823 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6824 : printer->sharename,
6825 : SPOOL_DSSPOOLER_KEY,
6826 : SPOOL_REG_PRINTSTARTTIME,
6827 : REG_DWORD,
6828 : buffer.data,
6829 0 : buffer.length);
6830 0 : if (!W_ERROR_IS_OK(result)) {
6831 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6832 0 : goto done;
6833 : }
6834 : }
6835 :
6836 100 : if (printer->untiltime != 0 &&
6837 0 : (force_update ||
6838 0 : printer->untiltime != old_printer->untiltime)) {
6839 0 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6840 0 : SIVAL(buffer.data, 0, printer->untiltime);
6841 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6842 : printer->sharename,
6843 : SPOOL_DSSPOOLER_KEY,
6844 : SPOOL_REG_PRINTENDTIME,
6845 : REG_DWORD,
6846 : buffer.data,
6847 0 : buffer.length);
6848 0 : if (!W_ERROR_IS_OK(result)) {
6849 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6850 0 : goto done;
6851 : }
6852 : }
6853 :
6854 100 : if (force_update || printer->priority != old_printer->priority) {
6855 16 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6856 16 : SIVAL(buffer.data, 0, printer->priority);
6857 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6858 : printer->sharename,
6859 : SPOOL_DSSPOOLER_KEY,
6860 : SPOOL_REG_PRIORITY,
6861 : REG_DWORD,
6862 : buffer.data,
6863 16 : buffer.length);
6864 16 : if (!W_ERROR_IS_OK(result)) {
6865 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6866 0 : goto done;
6867 : }
6868 : }
6869 :
6870 100 : if (force_update || printer->attributes != old_printer->attributes) {
6871 16 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6872 16 : SIVAL(buffer.data, 0, (printer->attributes &
6873 : PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6874 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6875 : printer->sharename,
6876 : SPOOL_DSSPOOLER_KEY,
6877 : SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6878 : REG_DWORD,
6879 : buffer.data,
6880 16 : buffer.length);
6881 16 : if (!W_ERROR_IS_OK(result)) {
6882 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6883 0 : goto done;
6884 : }
6885 :
6886 16 : switch (printer->attributes & 0x3) {
6887 16 : case 0:
6888 16 : spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6889 16 : break;
6890 0 : case 1:
6891 0 : spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6892 0 : break;
6893 0 : case 2:
6894 0 : spooling = SPOOL_REGVAL_PRINTDIRECT;
6895 0 : break;
6896 0 : default:
6897 0 : spooling = "unknown";
6898 : }
6899 16 : ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6900 16 : if (!ok) {
6901 0 : DEBUG(0, ("printSpooling data corrupted\n"));
6902 0 : result = WERR_INVALID_DATA;
6903 0 : goto done;
6904 : }
6905 16 : winreg_set_printer_dataex(tmp_ctx, b,
6906 : printer->sharename,
6907 : SPOOL_DSSPOOLER_KEY,
6908 : SPOOL_REG_PRINTSPOOLING,
6909 : REG_SZ,
6910 : buffer.data,
6911 16 : buffer.length);
6912 : }
6913 :
6914 100 : ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6915 100 : if (!ok) {
6916 0 : DEBUG(0, ("shortServerName data corrupted\n"));
6917 0 : result = WERR_INVALID_DATA;
6918 0 : goto done;
6919 : }
6920 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6921 : printer->sharename,
6922 : SPOOL_DSSPOOLER_KEY,
6923 : SPOOL_REG_SHORTSERVERNAME,
6924 : REG_SZ,
6925 : buffer.data,
6926 100 : buffer.length);
6927 100 : if (!W_ERROR_IS_OK(result)) {
6928 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6929 0 : goto done;
6930 : }
6931 :
6932 100 : dnsdomname = get_mydnsfullname();
6933 100 : if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6934 100 : longname = talloc_strdup(tmp_ctx, dnsdomname);
6935 : } else {
6936 0 : longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6937 : }
6938 100 : if (longname == NULL) {
6939 0 : result = WERR_NOT_ENOUGH_MEMORY;
6940 0 : goto done;
6941 : }
6942 :
6943 100 : ok = push_reg_sz(tmp_ctx, &buffer, longname);
6944 100 : if (!ok) {
6945 0 : DEBUG(0, ("longname data corrupted\n"));
6946 0 : result = WERR_INVALID_DATA;
6947 0 : goto done;
6948 : }
6949 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6950 : printer->sharename,
6951 : SPOOL_DSSPOOLER_KEY,
6952 : SPOOL_REG_SERVERNAME,
6953 : REG_SZ,
6954 : buffer.data,
6955 100 : buffer.length);
6956 100 : if (!W_ERROR_IS_OK(result)) {
6957 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6958 0 : goto done;
6959 : }
6960 :
6961 100 : uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6962 : lp_netbios_name(), printer->sharename);
6963 100 : ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6964 100 : if (!ok) {
6965 0 : DEBUG(0, ("uncName data corrupted\n"));
6966 0 : result = WERR_INVALID_DATA;
6967 0 : goto done;
6968 : }
6969 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6970 : printer->sharename,
6971 : SPOOL_DSSPOOLER_KEY,
6972 : SPOOL_REG_UNCNAME,
6973 : REG_SZ,
6974 : buffer.data,
6975 100 : buffer.length);
6976 100 : if (!W_ERROR_IS_OK(result)) {
6977 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6978 0 : goto done;
6979 : }
6980 :
6981 100 : done:
6982 100 : talloc_free(tmp_ctx);
6983 100 : return result;
6984 : }
6985 :
6986 : /********************************************************************
6987 : * Called by spoolss_api_setprinter
6988 : * when updating a printer description.
6989 : ********************************************************************/
6990 :
6991 84 : static WERROR update_printer(struct pipes_struct *p,
6992 : struct policy_handle *handle,
6993 : struct spoolss_SetPrinterInfoCtr *info_ctr,
6994 : struct spoolss_DeviceMode *devmode)
6995 : {
6996 84 : struct dcesrv_call_state *dce_call = p->dce_call;
6997 84 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
6998 0 : const struct tsocket_address *remote_address =
6999 84 : dcesrv_connection_get_remote_address(dcesrv_conn);
7000 0 : struct auth_session_info *session_info =
7001 84 : dcesrv_call_session_info(dce_call);
7002 84 : uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
7003 84 : struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
7004 0 : struct spoolss_PrinterInfo2 *old_printer;
7005 84 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7006 0 : const struct loadparm_substitution *lp_sub =
7007 84 : loadparm_s3_global_substitution();
7008 0 : int snum;
7009 84 : WERROR result = WERR_OK;
7010 0 : TALLOC_CTX *tmp_ctx;
7011 0 : struct dcerpc_binding_handle *b;
7012 :
7013 84 : DEBUG(8,("update_printer\n"));
7014 :
7015 84 : tmp_ctx = talloc_new(p->mem_ctx);
7016 84 : if (tmp_ctx == NULL) {
7017 0 : return WERR_NOT_ENOUGH_MEMORY;
7018 : }
7019 :
7020 84 : if (!Printer) {
7021 0 : result = WERR_INVALID_HANDLE;
7022 0 : goto done;
7023 : }
7024 :
7025 84 : if (!get_printer_snum(p, handle, &snum, NULL)) {
7026 0 : result = WERR_INVALID_HANDLE;
7027 0 : goto done;
7028 : }
7029 :
7030 84 : result = winreg_printer_binding_handle(tmp_ctx,
7031 : get_session_info_system(),
7032 : p->msg_ctx,
7033 : &b);
7034 84 : if (!W_ERROR_IS_OK(result)) {
7035 0 : goto done;
7036 : }
7037 :
7038 84 : result = winreg_get_printer(tmp_ctx, b,
7039 : lp_const_servicename(snum),
7040 : &old_printer);
7041 84 : if (!W_ERROR_IS_OK(result)) {
7042 0 : result = WERR_INVALID_HANDLE;
7043 0 : goto done;
7044 : }
7045 :
7046 : /* Do sanity check on the requested changes for Samba */
7047 84 : if (!check_printer_ok(tmp_ctx, printer, snum)) {
7048 0 : result = WERR_INVALID_PARAMETER;
7049 0 : goto done;
7050 : }
7051 :
7052 : /* FIXME!!! If the driver has changed we really should verify that
7053 : it is installed before doing much else --jerry */
7054 :
7055 : /* Check calling user has permission to update printer description */
7056 84 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7057 0 : DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7058 0 : result = WERR_ACCESS_DENIED;
7059 0 : goto done;
7060 : }
7061 :
7062 : /* Call addprinter hook */
7063 : /* Check changes to see if this is really needed */
7064 :
7065 84 : if (*lp_addprinter_command(talloc_tos(), lp_sub) &&
7066 84 : (!strequal(printer->drivername, old_printer->drivername) ||
7067 76 : !strequal(printer->comment, old_printer->comment) ||
7068 42 : !strequal(printer->portname, old_printer->portname) ||
7069 42 : !strequal(printer->location, old_printer->location)) )
7070 : {
7071 0 : char *raddr;
7072 :
7073 50 : raddr = tsocket_address_inet_addr_string(remote_address,
7074 : p->mem_ctx);
7075 50 : if (raddr == NULL) {
7076 0 : result = WERR_NOT_ENOUGH_MEMORY;
7077 0 : goto done;
7078 : }
7079 :
7080 : /* add_printer_hook() will call reload_services() */
7081 50 : if (!add_printer_hook(tmp_ctx, session_info->security_token,
7082 : printer, raddr,
7083 : p->msg_ctx)) {
7084 0 : result = WERR_ACCESS_DENIED;
7085 0 : goto done;
7086 : }
7087 : }
7088 :
7089 84 : result = update_dsspooler(tmp_ctx,
7090 : get_session_info_system(),
7091 : p->msg_ctx,
7092 : snum,
7093 : printer,
7094 : old_printer);
7095 84 : if (!W_ERROR_IS_OK(result)) {
7096 0 : goto done;
7097 : }
7098 :
7099 84 : printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
7100 :
7101 84 : if (devmode == NULL) {
7102 76 : printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
7103 : }
7104 84 : result = winreg_update_printer(tmp_ctx, b,
7105 : printer->sharename,
7106 : printer_mask,
7107 : printer,
7108 : devmode,
7109 : NULL);
7110 :
7111 84 : done:
7112 84 : talloc_free(tmp_ctx);
7113 :
7114 84 : return result;
7115 : }
7116 :
7117 : /****************************************************************************
7118 : ****************************************************************************/
7119 8 : static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
7120 : struct policy_handle *handle,
7121 : struct spoolss_SetPrinterInfo7 *info7)
7122 : {
7123 : #ifdef HAVE_ADS
7124 0 : const struct loadparm_substitution *lp_sub =
7125 6 : loadparm_s3_global_substitution();
7126 6 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7127 0 : WERROR result;
7128 0 : int snum;
7129 0 : struct printer_handle *Printer;
7130 :
7131 6 : if ( lp_security() != SEC_ADS ) {
7132 6 : return WERR_INVALID_LEVEL;
7133 : }
7134 :
7135 0 : Printer = find_printer_index_by_hnd(p, handle);
7136 :
7137 0 : DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
7138 :
7139 0 : if (!Printer)
7140 0 : return WERR_INVALID_HANDLE;
7141 :
7142 0 : if (!get_printer_snum(p, handle, &snum, NULL))
7143 0 : return WERR_INVALID_HANDLE;
7144 :
7145 0 : result = winreg_get_printer_internal(p->mem_ctx,
7146 : get_session_info_system(),
7147 : p->msg_ctx,
7148 0 : lp_servicename(talloc_tos(), lp_sub, snum),
7149 : &pinfo2);
7150 0 : if (!W_ERROR_IS_OK(result)) {
7151 0 : return WERR_INVALID_HANDLE;
7152 : }
7153 :
7154 0 : nt_printer_publish(pinfo2,
7155 : get_session_info_system(),
7156 : p->msg_ctx,
7157 : pinfo2,
7158 0 : info7->action);
7159 :
7160 0 : TALLOC_FREE(pinfo2);
7161 0 : return WERR_OK;
7162 : #else
7163 2 : return WERR_INVALID_LEVEL;
7164 : #endif
7165 : }
7166 :
7167 : /********************************************************************
7168 : ********************************************************************/
7169 :
7170 296 : static WERROR update_printer_devmode(struct pipes_struct *p,
7171 : struct policy_handle *handle,
7172 : struct spoolss_DeviceMode *devmode)
7173 : {
7174 0 : int snum;
7175 296 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7176 296 : uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7177 :
7178 296 : DEBUG(8,("update_printer_devmode\n"));
7179 :
7180 296 : if (!Printer) {
7181 0 : return WERR_INVALID_HANDLE;
7182 : }
7183 :
7184 296 : if (!get_printer_snum(p, handle, &snum, NULL)) {
7185 0 : return WERR_INVALID_HANDLE;
7186 : }
7187 :
7188 : /* Check calling user has permission to update printer description */
7189 296 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7190 0 : DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7191 0 : return WERR_ACCESS_DENIED;
7192 : }
7193 :
7194 296 : return winreg_update_printer_internal(p->mem_ctx,
7195 : get_session_info_system(),
7196 : p->msg_ctx,
7197 : lp_const_servicename(snum),
7198 : info2_mask,
7199 : NULL,
7200 : devmode,
7201 : NULL);
7202 : }
7203 :
7204 :
7205 : /****************************************************************
7206 : _spoolss_SetPrinter
7207 : ****************************************************************/
7208 :
7209 584 : WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7210 : struct spoolss_SetPrinter *r)
7211 : {
7212 0 : WERROR result;
7213 :
7214 584 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7215 :
7216 584 : if (!Printer) {
7217 0 : DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7218 : OUR_HANDLE(r->in.handle)));
7219 0 : return WERR_INVALID_HANDLE;
7220 : }
7221 :
7222 : /* check the level */
7223 584 : switch (r->in.info_ctr->level) {
7224 104 : case 0:
7225 104 : return control_printer(r->in.handle, r->in.command, p);
7226 84 : case 2:
7227 84 : result = update_printer(p, r->in.handle,
7228 : r->in.info_ctr,
7229 84 : r->in.devmode_ctr->devmode);
7230 84 : if (!W_ERROR_IS_OK(result))
7231 0 : return result;
7232 84 : if (r->in.secdesc_ctr->sd)
7233 28 : result = update_printer_sec(r->in.handle, p,
7234 : r->in.secdesc_ctr);
7235 84 : return result;
7236 92 : case 3:
7237 92 : return update_printer_sec(r->in.handle, p,
7238 : r->in.secdesc_ctr);
7239 0 : case 4: {
7240 0 : struct spoolss_PrinterInfo2 *old_printer;
7241 0 : struct spoolss_SetPrinterInfo2 *set_old_printer;
7242 0 : struct spoolss_SetPrinterInfoCtr *info_ctr;
7243 0 : struct dcerpc_binding_handle *b;
7244 0 : int snum;
7245 0 : TALLOC_CTX *tmp_ctx;
7246 :
7247 0 : tmp_ctx = talloc_new(p->mem_ctx);
7248 0 : if (tmp_ctx == NULL) {
7249 0 : return WERR_NOT_ENOUGH_MEMORY;
7250 : }
7251 :
7252 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7253 0 : TALLOC_FREE(tmp_ctx);
7254 0 : return WERR_INVALID_HANDLE;
7255 : }
7256 :
7257 0 : result = winreg_printer_binding_handle(tmp_ctx,
7258 : get_session_info_system(),
7259 : p->msg_ctx,
7260 : &b);
7261 0 : if (!W_ERROR_IS_OK(result)) {
7262 0 : TALLOC_FREE(tmp_ctx);
7263 0 : return result;
7264 : }
7265 :
7266 0 : result = winreg_get_printer(tmp_ctx, b,
7267 : lp_const_servicename(snum),
7268 : &old_printer);
7269 0 : if (!W_ERROR_IS_OK(result)) {
7270 0 : TALLOC_FREE(tmp_ctx);
7271 0 : return WERR_INVALID_HANDLE;
7272 : }
7273 :
7274 0 : old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7275 0 : if (old_printer->servername == NULL) {
7276 0 : TALLOC_FREE(tmp_ctx);
7277 0 : return WERR_NOT_ENOUGH_MEMORY;
7278 : }
7279 :
7280 0 : old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7281 0 : if (old_printer->printername == NULL) {
7282 0 : TALLOC_FREE(tmp_ctx);
7283 0 : return WERR_NOT_ENOUGH_MEMORY;
7284 : }
7285 :
7286 0 : old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7287 :
7288 0 : set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7289 0 : if (set_old_printer == NULL) {
7290 0 : TALLOC_FREE(tmp_ctx);
7291 0 : return WERR_NOT_ENOUGH_MEMORY;
7292 : }
7293 :
7294 0 : spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7295 :
7296 0 : info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7297 0 : if (info_ctr == NULL) {
7298 0 : TALLOC_FREE(tmp_ctx);
7299 0 : return WERR_NOT_ENOUGH_MEMORY;
7300 : }
7301 :
7302 0 : info_ctr->level = 2;
7303 0 : info_ctr->info.info2 = set_old_printer;
7304 :
7305 0 : result = update_printer(p, r->in.handle,
7306 : info_ctr,
7307 0 : r->in.devmode_ctr->devmode);
7308 :
7309 0 : if (!W_ERROR_IS_OK(result)) {
7310 0 : TALLOC_FREE(tmp_ctx);
7311 0 : return result;
7312 : }
7313 :
7314 0 : if (r->in.secdesc_ctr->sd) {
7315 0 : result = update_printer_sec(r->in.handle, p,
7316 : r->in.secdesc_ctr);
7317 : }
7318 :
7319 0 : TALLOC_FREE(tmp_ctx);
7320 0 : return result;
7321 : }
7322 8 : case 7:
7323 8 : return publish_or_unpublish_printer(p, r->in.handle,
7324 8 : r->in.info_ctr->info.info7);
7325 296 : case 8:
7326 296 : return update_printer_devmode(p, r->in.handle,
7327 296 : r->in.devmode_ctr->devmode);
7328 0 : default:
7329 0 : return WERR_INVALID_LEVEL;
7330 : }
7331 : }
7332 :
7333 : /****************************************************************
7334 : _spoolss_FindClosePrinterNotify
7335 : ****************************************************************/
7336 :
7337 0 : WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7338 : struct spoolss_FindClosePrinterNotify *r)
7339 : {
7340 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7341 :
7342 0 : if (!Printer) {
7343 0 : DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7344 : "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7345 0 : return WERR_INVALID_HANDLE;
7346 : }
7347 :
7348 0 : if (Printer->notify.cli_chan != NULL &&
7349 0 : Printer->notify.cli_chan->active_connections > 0) {
7350 0 : int snum = -1;
7351 :
7352 0 : if (Printer->printer_type == SPLHND_PRINTER) {
7353 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7354 0 : return WERR_INVALID_HANDLE;
7355 : }
7356 : }
7357 :
7358 0 : srv_spoolss_replycloseprinter(snum, Printer);
7359 : }
7360 :
7361 0 : Printer->notify.flags=0;
7362 0 : Printer->notify.options=0;
7363 0 : Printer->notify.localmachine[0]='\0';
7364 0 : Printer->notify.printerlocal=0;
7365 0 : TALLOC_FREE(Printer->notify.option);
7366 :
7367 0 : return WERR_OK;
7368 : }
7369 :
7370 : /****************************************************************
7371 : _spoolss_AddJob
7372 : ****************************************************************/
7373 :
7374 16 : WERROR _spoolss_AddJob(struct pipes_struct *p,
7375 : struct spoolss_AddJob *r)
7376 : {
7377 16 : if (!r->in.buffer && (r->in.offered != 0)) {
7378 0 : return WERR_INVALID_PARAMETER;
7379 : }
7380 :
7381 : /* this is what a NT server returns for AddJob. AddJob must fail on
7382 : * non-local printers */
7383 :
7384 16 : if (r->in.level != 1) {
7385 8 : return WERR_INVALID_LEVEL;
7386 : }
7387 :
7388 8 : return WERR_INVALID_PARAMETER;
7389 : }
7390 :
7391 : /****************************************************************************
7392 : fill_job_info1
7393 : ****************************************************************************/
7394 :
7395 320 : static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7396 : struct spoolss_JobInfo1 *r,
7397 : const print_queue_struct *queue,
7398 : uint32_t jobid,
7399 : int position, int snum,
7400 : struct spoolss_PrinterInfo2 *pinfo2)
7401 : {
7402 0 : const struct loadparm_substitution *lp_sub =
7403 320 : loadparm_s3_global_substitution();
7404 0 : struct tm *t;
7405 :
7406 320 : t = gmtime(&queue->time);
7407 :
7408 320 : r->job_id = jobid;
7409 :
7410 320 : r->printer_name = lp_servicename(mem_ctx, lp_sub, snum);
7411 320 : W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7412 320 : r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7413 320 : W_ERROR_HAVE_NO_MEMORY(r->server_name);
7414 320 : r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7415 320 : W_ERROR_HAVE_NO_MEMORY(r->user_name);
7416 320 : r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7417 320 : W_ERROR_HAVE_NO_MEMORY(r->document_name);
7418 320 : r->data_type = talloc_strdup(mem_ctx, "RAW");
7419 320 : W_ERROR_HAVE_NO_MEMORY(r->data_type);
7420 320 : r->text_status = talloc_strdup(mem_ctx, "");
7421 320 : W_ERROR_HAVE_NO_MEMORY(r->text_status);
7422 :
7423 320 : r->status = nt_printj_status(queue->status);
7424 320 : r->priority = queue->priority;
7425 320 : r->position = position;
7426 320 : r->total_pages = queue->page_count;
7427 320 : r->pages_printed = 0; /* ??? */
7428 :
7429 320 : init_systemtime(&r->submitted, t);
7430 :
7431 320 : return WERR_OK;
7432 : }
7433 :
7434 : /****************************************************************************
7435 : fill_job_info2
7436 : ****************************************************************************/
7437 :
7438 66 : static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7439 : struct spoolss_JobInfo2 *r,
7440 : const print_queue_struct *queue,
7441 : uint32_t jobid,
7442 : int position, int snum,
7443 : struct spoolss_PrinterInfo2 *pinfo2,
7444 : struct spoolss_DeviceMode *devmode)
7445 : {
7446 0 : const struct loadparm_substitution *lp_sub =
7447 66 : loadparm_s3_global_substitution();
7448 0 : struct tm *t;
7449 :
7450 66 : t = gmtime(&queue->time);
7451 :
7452 66 : r->job_id = jobid;
7453 :
7454 66 : r->printer_name = lp_servicename(mem_ctx, lp_sub, snum);
7455 66 : W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7456 66 : r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7457 66 : W_ERROR_HAVE_NO_MEMORY(r->server_name);
7458 66 : r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7459 66 : W_ERROR_HAVE_NO_MEMORY(r->user_name);
7460 66 : r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7461 66 : W_ERROR_HAVE_NO_MEMORY(r->document_name);
7462 66 : r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7463 66 : W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7464 66 : r->data_type = talloc_strdup(mem_ctx, "RAW");
7465 66 : W_ERROR_HAVE_NO_MEMORY(r->data_type);
7466 66 : r->print_processor = talloc_strdup(mem_ctx, "winprint");
7467 66 : W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7468 66 : r->parameters = talloc_strdup(mem_ctx, "");
7469 66 : W_ERROR_HAVE_NO_MEMORY(r->parameters);
7470 66 : r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7471 66 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7472 :
7473 66 : r->devmode = devmode;
7474 :
7475 66 : r->text_status = talloc_strdup(mem_ctx, "");
7476 66 : W_ERROR_HAVE_NO_MEMORY(r->text_status);
7477 :
7478 66 : r->secdesc = NULL;
7479 :
7480 66 : r->status = nt_printj_status(queue->status);
7481 66 : r->priority = queue->priority;
7482 66 : r->position = position;
7483 66 : r->start_time = 0;
7484 66 : r->until_time = 0;
7485 66 : r->total_pages = queue->page_count;
7486 66 : r->size = queue->size;
7487 66 : init_systemtime(&r->submitted, t);
7488 66 : r->time = 0;
7489 66 : r->pages_printed = 0; /* ??? */
7490 :
7491 66 : return WERR_OK;
7492 : }
7493 :
7494 : /****************************************************************************
7495 : Enumjobs at level 1.
7496 : ****************************************************************************/
7497 :
7498 24 : static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7499 : const print_queue_struct *queue,
7500 : uint32_t num_queues, int snum,
7501 : struct spoolss_PrinterInfo2 *pinfo2,
7502 : union spoolss_JobInfo **info_p,
7503 : uint32_t *count)
7504 : {
7505 0 : union spoolss_JobInfo *info;
7506 0 : int i;
7507 24 : WERROR result = WERR_OK;
7508 0 : uint32_t num_filled;
7509 0 : struct tdb_print_db *pdb;
7510 :
7511 24 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7512 24 : if (info == NULL) {
7513 0 : result = WERR_NOT_ENOUGH_MEMORY;
7514 0 : goto err_out;
7515 : }
7516 :
7517 24 : pdb = get_print_db_byname(pinfo2->sharename);
7518 24 : if (pdb == NULL) {
7519 0 : result = WERR_INVALID_PARAMETER;
7520 0 : goto err_info_free;
7521 : }
7522 :
7523 24 : num_filled = 0;
7524 216 : for (i = 0; i < num_queues; i++) {
7525 192 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7526 192 : if (jobid == (uint32_t)-1) {
7527 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7528 0 : continue;
7529 : }
7530 :
7531 192 : result = fill_job_info1(info,
7532 192 : &info[num_filled].info1,
7533 192 : &queue[i],
7534 : jobid,
7535 : i,
7536 : snum,
7537 : pinfo2);
7538 192 : if (!W_ERROR_IS_OK(result)) {
7539 0 : goto err_pdb_drop;
7540 : }
7541 :
7542 192 : num_filled++;
7543 : }
7544 :
7545 24 : release_print_db(pdb);
7546 24 : *info_p = info;
7547 24 : *count = num_filled;
7548 :
7549 24 : return WERR_OK;
7550 :
7551 0 : err_pdb_drop:
7552 0 : release_print_db(pdb);
7553 0 : err_info_free:
7554 0 : TALLOC_FREE(info);
7555 0 : err_out:
7556 0 : *count = 0;
7557 0 : return result;
7558 : }
7559 :
7560 : /****************************************************************************
7561 : Enumjobs at level 2.
7562 : ****************************************************************************/
7563 :
7564 10 : static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7565 : const print_queue_struct *queue,
7566 : uint32_t num_queues, int snum,
7567 : struct spoolss_PrinterInfo2 *pinfo2,
7568 : union spoolss_JobInfo **info_p,
7569 : uint32_t *count)
7570 : {
7571 0 : union spoolss_JobInfo *info;
7572 0 : int i;
7573 10 : WERROR result = WERR_OK;
7574 0 : uint32_t num_filled;
7575 0 : struct tdb_print_db *pdb;
7576 :
7577 10 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7578 10 : if (info == NULL) {
7579 0 : result = WERR_NOT_ENOUGH_MEMORY;
7580 0 : goto err_out;
7581 : }
7582 :
7583 10 : pdb = get_print_db_byname(pinfo2->sharename);
7584 10 : if (pdb == NULL) {
7585 0 : result = WERR_INVALID_PARAMETER;
7586 0 : goto err_info_free;
7587 : }
7588 :
7589 10 : num_filled = 0;
7590 76 : for (i = 0; i< num_queues; i++) {
7591 0 : struct spoolss_DeviceMode *devmode;
7592 66 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7593 66 : if (jobid == (uint32_t)-1) {
7594 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7595 0 : continue;
7596 : }
7597 :
7598 66 : result = spoolss_create_default_devmode(info,
7599 : pinfo2->printername,
7600 : &devmode);
7601 66 : if (!W_ERROR_IS_OK(result)) {
7602 0 : DEBUG(3, ("Can't proceed w/o a devmode!\n"));
7603 0 : goto err_pdb_drop;
7604 : }
7605 :
7606 66 : result = fill_job_info2(info,
7607 66 : &info[num_filled].info2,
7608 66 : &queue[i],
7609 : jobid,
7610 : i,
7611 : snum,
7612 : pinfo2,
7613 : devmode);
7614 66 : if (!W_ERROR_IS_OK(result)) {
7615 0 : goto err_pdb_drop;
7616 : }
7617 66 : num_filled++;
7618 : }
7619 :
7620 10 : release_print_db(pdb);
7621 10 : *info_p = info;
7622 10 : *count = num_filled;
7623 :
7624 10 : return WERR_OK;
7625 :
7626 0 : err_pdb_drop:
7627 0 : release_print_db(pdb);
7628 0 : err_info_free:
7629 0 : TALLOC_FREE(info);
7630 0 : err_out:
7631 0 : *count = 0;
7632 0 : return result;
7633 : }
7634 :
7635 : /****************************************************************************
7636 : Enumjobs at level 3.
7637 : ****************************************************************************/
7638 :
7639 0 : static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7640 : const print_queue_struct *queue,
7641 : uint32_t num_queues, int snum,
7642 : struct spoolss_PrinterInfo2 *pinfo2,
7643 : union spoolss_JobInfo **info_p,
7644 : uint32_t *count)
7645 : {
7646 0 : union spoolss_JobInfo *info;
7647 0 : int i;
7648 0 : WERROR result = WERR_OK;
7649 0 : uint32_t num_filled;
7650 0 : struct tdb_print_db *pdb;
7651 :
7652 0 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7653 0 : if (info == NULL) {
7654 0 : result = WERR_NOT_ENOUGH_MEMORY;
7655 0 : goto err_out;
7656 : }
7657 :
7658 0 : pdb = get_print_db_byname(pinfo2->sharename);
7659 0 : if (pdb == NULL) {
7660 0 : result = WERR_INVALID_PARAMETER;
7661 0 : goto err_info_free;
7662 : }
7663 :
7664 0 : num_filled = 0;
7665 0 : for (i = 0; i < num_queues; i++) {
7666 0 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7667 0 : if (jobid == (uint32_t)-1) {
7668 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7669 0 : continue;
7670 : }
7671 :
7672 0 : info[num_filled].info3.job_id = jobid;
7673 : /* next_job_id is overwritten on next iteration */
7674 0 : info[num_filled].info3.next_job_id = 0;
7675 0 : info[num_filled].info3.reserved = 0;
7676 :
7677 0 : if (num_filled > 0) {
7678 0 : info[num_filled - 1].info3.next_job_id = jobid;
7679 : }
7680 0 : num_filled++;
7681 : }
7682 :
7683 0 : release_print_db(pdb);
7684 0 : *info_p = info;
7685 0 : *count = num_filled;
7686 :
7687 0 : return WERR_OK;
7688 :
7689 0 : err_info_free:
7690 0 : TALLOC_FREE(info);
7691 0 : err_out:
7692 0 : *count = 0;
7693 0 : return result;
7694 : }
7695 :
7696 : /****************************************************************
7697 : _spoolss_EnumJobs
7698 : ****************************************************************/
7699 :
7700 95 : WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7701 : struct spoolss_EnumJobs *r)
7702 : {
7703 0 : WERROR result;
7704 95 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7705 0 : int snum;
7706 0 : print_status_struct prt_status;
7707 95 : print_queue_struct *queue = NULL;
7708 0 : uint32_t count;
7709 :
7710 : /* that's an [in out] buffer */
7711 :
7712 95 : if (!r->in.buffer && (r->in.offered != 0)) {
7713 0 : return WERR_INVALID_PARAMETER;
7714 : }
7715 :
7716 95 : if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7717 12 : DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7718 12 : return WERR_INVALID_LEVEL;
7719 : }
7720 :
7721 83 : DEBUG(4,("_spoolss_EnumJobs\n"));
7722 :
7723 83 : *r->out.needed = 0;
7724 83 : *r->out.count = 0;
7725 83 : *r->out.info = NULL;
7726 :
7727 : /* lookup the printer snum and tdb entry */
7728 :
7729 83 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7730 0 : return WERR_INVALID_HANDLE;
7731 : }
7732 :
7733 83 : result = winreg_get_printer_internal(p->mem_ctx,
7734 : get_session_info_system(),
7735 : p->msg_ctx,
7736 : lp_const_servicename(snum),
7737 : &pinfo2);
7738 83 : if (!W_ERROR_IS_OK(result)) {
7739 0 : return result;
7740 : }
7741 :
7742 83 : count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7743 83 : DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7744 : count, prt_status.status, prt_status.message));
7745 :
7746 83 : if (count == 0) {
7747 49 : SAFE_FREE(queue);
7748 49 : TALLOC_FREE(pinfo2);
7749 49 : return WERR_OK;
7750 : }
7751 :
7752 34 : switch (r->in.level) {
7753 24 : case 1:
7754 24 : result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7755 : pinfo2, r->out.info, r->out.count);
7756 24 : break;
7757 10 : case 2:
7758 10 : result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7759 : pinfo2, r->out.info, r->out.count);
7760 10 : break;
7761 0 : case 3:
7762 0 : result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7763 : pinfo2, r->out.info, r->out.count);
7764 0 : break;
7765 0 : default:
7766 0 : SMB_ASSERT(false); /* level checked on entry */
7767 : break;
7768 : }
7769 :
7770 34 : SAFE_FREE(queue);
7771 34 : TALLOC_FREE(pinfo2);
7772 :
7773 34 : if (!W_ERROR_IS_OK(result)) {
7774 0 : return result;
7775 : }
7776 :
7777 34 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7778 : spoolss_EnumJobs,
7779 : *r->out.info, r->in.level,
7780 : *r->out.count);
7781 34 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7782 34 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7783 :
7784 34 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7785 : }
7786 :
7787 : /****************************************************************
7788 : _spoolss_ScheduleJob
7789 : ****************************************************************/
7790 :
7791 0 : WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7792 : struct spoolss_ScheduleJob *r)
7793 : {
7794 0 : return WERR_OK;
7795 : }
7796 :
7797 : /****************************************************************
7798 : ****************************************************************/
7799 :
7800 32 : static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7801 : struct messaging_context *msg_ctx,
7802 : const char *printer_name,
7803 : uint32_t job_id,
7804 : struct spoolss_SetJobInfo1 *r)
7805 : {
7806 0 : char *old_doc_name;
7807 :
7808 32 : if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7809 0 : return WERR_INVALID_HANDLE;
7810 : }
7811 :
7812 32 : if (strequal(old_doc_name, r->document_name)) {
7813 0 : return WERR_OK;
7814 : }
7815 :
7816 32 : if (!print_job_set_name(global_event_context(), msg_ctx,
7817 : printer_name, job_id, r->document_name)) {
7818 0 : return WERR_INVALID_HANDLE;
7819 : }
7820 :
7821 32 : return WERR_OK;
7822 : }
7823 :
7824 : /****************************************************************
7825 : _spoolss_SetJob
7826 : ****************************************************************/
7827 :
7828 640 : WERROR _spoolss_SetJob(struct pipes_struct *p,
7829 : struct spoolss_SetJob *r)
7830 : {
7831 640 : struct dcesrv_call_state *dce_call = p->dce_call;
7832 0 : struct auth_session_info *session_info =
7833 640 : dcesrv_call_session_info(dce_call);
7834 0 : int snum;
7835 640 : WERROR errcode = WERR_INVALID_FUNCTION;
7836 :
7837 640 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7838 0 : return WERR_INVALID_HANDLE;
7839 : }
7840 :
7841 640 : if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7842 244 : return WERR_INVALID_PRINTER_NAME;
7843 : }
7844 :
7845 396 : switch (r->in.command) {
7846 300 : case SPOOLSS_JOB_CONTROL_CANCEL:
7847 : case SPOOLSS_JOB_CONTROL_DELETE:
7848 300 : errcode = print_job_delete(session_info, p->msg_ctx,
7849 : snum, r->in.job_id);
7850 300 : if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7851 300 : errcode = WERR_OK;
7852 : }
7853 300 : break;
7854 32 : case SPOOLSS_JOB_CONTROL_PAUSE:
7855 32 : errcode = print_job_pause(session_info, p->msg_ctx,
7856 : snum, r->in.job_id);
7857 32 : break;
7858 32 : case SPOOLSS_JOB_CONTROL_RESTART:
7859 : case SPOOLSS_JOB_CONTROL_RESUME:
7860 32 : errcode = print_job_resume(session_info, p->msg_ctx,
7861 : snum, r->in.job_id);
7862 32 : break;
7863 32 : case SPOOLSS_JOB_CONTROL_NOOP:
7864 32 : errcode = WERR_OK;
7865 32 : break;
7866 0 : default:
7867 0 : return WERR_INVALID_LEVEL;
7868 : }
7869 :
7870 396 : if (!W_ERROR_IS_OK(errcode)) {
7871 0 : return errcode;
7872 : }
7873 :
7874 396 : if (r->in.ctr == NULL) {
7875 364 : return errcode;
7876 : }
7877 :
7878 32 : switch (r->in.ctr->level) {
7879 32 : case 1:
7880 32 : errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7881 : lp_const_servicename(snum),
7882 : r->in.job_id,
7883 32 : r->in.ctr->info.info1);
7884 32 : break;
7885 0 : case 2:
7886 : case 3:
7887 : case 4:
7888 : default:
7889 0 : return WERR_INVALID_LEVEL;
7890 : }
7891 :
7892 32 : return errcode;
7893 : }
7894 :
7895 : /****************************************************************************
7896 : Enumerates all printer drivers by level and architecture.
7897 : ****************************************************************************/
7898 :
7899 460 : static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7900 : const struct auth_session_info *session_info,
7901 : struct messaging_context *msg_ctx,
7902 : const char *servername,
7903 : const char *architecture,
7904 : uint32_t level,
7905 : union spoolss_DriverInfo **info_p,
7906 : uint32_t *count_p)
7907 : {
7908 0 : int i;
7909 0 : uint32_t version;
7910 0 : struct spoolss_DriverInfo8 *driver;
7911 460 : union spoolss_DriverInfo *info = NULL;
7912 460 : uint32_t count = 0;
7913 460 : WERROR result = WERR_OK;
7914 0 : uint32_t num_drivers;
7915 0 : const char **drivers;
7916 0 : struct dcerpc_binding_handle *b;
7917 460 : TALLOC_CTX *tmp_ctx = NULL;
7918 :
7919 460 : *count_p = 0;
7920 460 : *info_p = NULL;
7921 :
7922 460 : tmp_ctx = talloc_new(mem_ctx);
7923 460 : if (!tmp_ctx) {
7924 0 : return WERR_NOT_ENOUGH_MEMORY;
7925 : }
7926 :
7927 460 : result = winreg_printer_binding_handle(tmp_ctx,
7928 : session_info,
7929 : msg_ctx,
7930 : &b);
7931 460 : if (!W_ERROR_IS_OK(result)) {
7932 0 : goto out;
7933 : }
7934 :
7935 2300 : for (version=0; version<DRIVER_MAX_VERSION; version++) {
7936 1840 : result = winreg_get_driver_list(tmp_ctx, b,
7937 : architecture, version,
7938 : &num_drivers, &drivers);
7939 1840 : if (!W_ERROR_IS_OK(result)) {
7940 0 : goto out;
7941 : }
7942 1840 : DEBUG(4, ("we have:[%d] drivers in environment"
7943 : " [%s] and version [%d]\n",
7944 : num_drivers, architecture, version));
7945 :
7946 1840 : if (num_drivers != 0) {
7947 0 : info = talloc_realloc(tmp_ctx, info,
7948 : union spoolss_DriverInfo,
7949 : count + num_drivers);
7950 0 : if (!info) {
7951 0 : DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7952 : "failed to enlarge driver info buffer!\n"));
7953 0 : result = WERR_NOT_ENOUGH_MEMORY;
7954 0 : goto out;
7955 : }
7956 : }
7957 :
7958 1840 : for (i = 0; i < num_drivers; i++) {
7959 0 : DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7960 :
7961 0 : result = winreg_get_driver(tmp_ctx, b,
7962 0 : architecture, drivers[i],
7963 : version, &driver);
7964 0 : if (!W_ERROR_IS_OK(result)) {
7965 0 : goto out;
7966 : }
7967 :
7968 0 : switch (level) {
7969 0 : case 1:
7970 0 : result = fill_printer_driver_info1(info, &info[count+i].info1,
7971 : driver, servername);
7972 0 : break;
7973 0 : case 2:
7974 0 : result = fill_printer_driver_info2(info, &info[count+i].info2,
7975 : driver, servername);
7976 0 : break;
7977 0 : case 3:
7978 0 : result = fill_printer_driver_info3(info, &info[count+i].info3,
7979 : driver, servername);
7980 0 : break;
7981 0 : case 4:
7982 0 : result = fill_printer_driver_info4(info, &info[count+i].info4,
7983 : driver, servername);
7984 0 : break;
7985 0 : case 5:
7986 0 : result = fill_printer_driver_info5(info, &info[count+i].info5,
7987 : driver, servername);
7988 0 : break;
7989 0 : case 6:
7990 0 : result = fill_printer_driver_info6(info, &info[count+i].info6,
7991 : driver, servername);
7992 0 : break;
7993 0 : case 8:
7994 0 : result = fill_printer_driver_info8(info, &info[count+i].info8,
7995 : driver, servername);
7996 0 : break;
7997 0 : default:
7998 0 : result = WERR_INVALID_LEVEL;
7999 0 : break;
8000 : }
8001 :
8002 0 : TALLOC_FREE(driver);
8003 :
8004 0 : if (!W_ERROR_IS_OK(result)) {
8005 0 : goto out;
8006 : }
8007 : }
8008 :
8009 1840 : count += num_drivers;
8010 1840 : TALLOC_FREE(drivers);
8011 : }
8012 :
8013 460 : out:
8014 460 : if (W_ERROR_IS_OK(result)) {
8015 460 : *info_p = talloc_move(mem_ctx, &info);
8016 460 : *count_p = count;
8017 : }
8018 :
8019 460 : talloc_free(tmp_ctx);
8020 460 : return result;
8021 : }
8022 :
8023 : /****************************************************************************
8024 : Enumerates all printer drivers by level.
8025 : ****************************************************************************/
8026 :
8027 108 : static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
8028 : const struct auth_session_info *session_info,
8029 : struct messaging_context *msg_ctx,
8030 : const char *servername,
8031 : const char *architecture,
8032 : uint32_t level,
8033 : union spoolss_DriverInfo **info_p,
8034 : uint32_t *count_p)
8035 : {
8036 0 : uint32_t a,i;
8037 108 : WERROR result = WERR_OK;
8038 :
8039 108 : if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
8040 :
8041 440 : for (a=0; archi_table[a].long_archi != NULL; a++) {
8042 :
8043 396 : union spoolss_DriverInfo *info = NULL;
8044 396 : uint32_t count = 0;
8045 :
8046 396 : result = enumprinterdrivers_level_by_architecture(mem_ctx,
8047 : session_info,
8048 : msg_ctx,
8049 : servername,
8050 396 : archi_table[a].long_archi,
8051 : level,
8052 : &info,
8053 : &count);
8054 396 : if (!W_ERROR_IS_OK(result)) {
8055 0 : continue;
8056 : }
8057 :
8058 396 : for (i=0; i < count; i++) {
8059 0 : ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
8060 : info[i], info_p, count_p);
8061 : }
8062 : }
8063 :
8064 44 : return result;
8065 : }
8066 :
8067 64 : return enumprinterdrivers_level_by_architecture(mem_ctx,
8068 : session_info,
8069 : msg_ctx,
8070 : servername,
8071 : architecture,
8072 : level,
8073 : info_p,
8074 : count_p);
8075 : }
8076 :
8077 : /****************************************************************
8078 : _spoolss_EnumPrinterDrivers
8079 : ****************************************************************/
8080 :
8081 108 : WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
8082 : struct spoolss_EnumPrinterDrivers *r)
8083 : {
8084 0 : const char *cservername;
8085 0 : WERROR result;
8086 :
8087 : /* that's an [in out] buffer */
8088 :
8089 108 : if (!r->in.buffer && (r->in.offered != 0)) {
8090 0 : return WERR_INVALID_PARAMETER;
8091 : }
8092 :
8093 108 : DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
8094 :
8095 108 : *r->out.needed = 0;
8096 108 : *r->out.count = 0;
8097 108 : *r->out.info = NULL;
8098 :
8099 108 : cservername = canon_servername(r->in.server);
8100 :
8101 108 : if (!is_myname_or_ipaddr(cservername)) {
8102 0 : return WERR_UNKNOWN_PRINTER_DRIVER;
8103 : }
8104 :
8105 108 : result = enumprinterdrivers_level(p->mem_ctx,
8106 : get_session_info_system(),
8107 : p->msg_ctx,
8108 : cservername,
8109 : r->in.environment,
8110 : r->in.level,
8111 : r->out.info,
8112 : r->out.count);
8113 108 : if (!W_ERROR_IS_OK(result)) {
8114 0 : return result;
8115 : }
8116 :
8117 108 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8118 : spoolss_EnumPrinterDrivers,
8119 : *r->out.info, r->in.level,
8120 : *r->out.count);
8121 108 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8122 108 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8123 :
8124 108 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8125 : }
8126 :
8127 : /****************************************************************
8128 : _spoolss_EnumForms
8129 : ****************************************************************/
8130 :
8131 560 : WERROR _spoolss_EnumForms(struct pipes_struct *p,
8132 : struct spoolss_EnumForms *r)
8133 : {
8134 0 : WERROR result;
8135 :
8136 560 : *r->out.count = 0;
8137 560 : *r->out.needed = 0;
8138 560 : *r->out.info = NULL;
8139 :
8140 : /* that's an [in out] buffer */
8141 :
8142 560 : if (!r->in.buffer && (r->in.offered != 0) ) {
8143 0 : return WERR_INVALID_PARAMETER;
8144 : }
8145 :
8146 560 : DEBUG(4,("_spoolss_EnumForms\n"));
8147 560 : DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8148 560 : DEBUGADD(5,("Info level [%d]\n", r->in.level));
8149 :
8150 560 : switch (r->in.level) {
8151 536 : case 1:
8152 536 : result = winreg_printer_enumforms1_internal(p->mem_ctx,
8153 : get_session_info_system(),
8154 : p->msg_ctx,
8155 : r->out.count,
8156 : r->out.info);
8157 536 : break;
8158 24 : default:
8159 24 : result = WERR_INVALID_LEVEL;
8160 24 : break;
8161 : }
8162 :
8163 560 : if (!W_ERROR_IS_OK(result)) {
8164 24 : return result;
8165 : }
8166 :
8167 536 : if (*r->out.count == 0) {
8168 0 : return WERR_NO_MORE_ITEMS;
8169 : }
8170 :
8171 536 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8172 : spoolss_EnumForms,
8173 : *r->out.info, r->in.level,
8174 : *r->out.count);
8175 536 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8176 536 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8177 :
8178 536 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8179 : }
8180 :
8181 : /****************************************************************
8182 : _spoolss_GetForm
8183 : ****************************************************************/
8184 :
8185 5040 : WERROR _spoolss_GetForm(struct pipes_struct *p,
8186 : struct spoolss_GetForm *r)
8187 : {
8188 0 : WERROR result;
8189 :
8190 : /* that's an [in out] buffer */
8191 :
8192 5040 : if (!r->in.buffer && (r->in.offered != 0)) {
8193 0 : TALLOC_FREE(r->out.info);
8194 0 : return WERR_INVALID_PARAMETER;
8195 : }
8196 :
8197 5040 : DEBUG(4,("_spoolss_GetForm\n"));
8198 5040 : DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8199 5040 : DEBUGADD(5,("Info level [%d]\n", r->in.level));
8200 :
8201 5040 : switch (r->in.level) {
8202 5040 : case 1:
8203 5040 : result = winreg_printer_getform1_internal(p->mem_ctx,
8204 : get_session_info_system(),
8205 : p->msg_ctx,
8206 : r->in.form_name,
8207 5040 : &r->out.info->info1);
8208 5040 : break;
8209 0 : default:
8210 0 : result = WERR_INVALID_LEVEL;
8211 0 : break;
8212 : }
8213 :
8214 5040 : if (!W_ERROR_IS_OK(result)) {
8215 0 : TALLOC_FREE(r->out.info);
8216 0 : return result;
8217 : }
8218 :
8219 5040 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8220 : r->out.info, r->in.level);
8221 5040 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8222 :
8223 5040 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8224 : }
8225 :
8226 : /****************************************************************************
8227 : ****************************************************************************/
8228 :
8229 8 : static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8230 : struct spoolss_PortInfo1 *r,
8231 : const char *name)
8232 : {
8233 8 : r->port_name = talloc_strdup(mem_ctx, name);
8234 8 : W_ERROR_HAVE_NO_MEMORY(r->port_name);
8235 :
8236 8 : return WERR_OK;
8237 : }
8238 :
8239 : /****************************************************************************
8240 : TODO: This probably needs distinguish between TCP/IP and Local ports
8241 : somehow.
8242 : ****************************************************************************/
8243 :
8244 16 : static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8245 : struct spoolss_PortInfo2 *r,
8246 : const char *name)
8247 : {
8248 16 : r->port_name = talloc_strdup(mem_ctx, name);
8249 16 : W_ERROR_HAVE_NO_MEMORY(r->port_name);
8250 :
8251 16 : r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8252 16 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8253 :
8254 16 : r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8255 16 : W_ERROR_HAVE_NO_MEMORY(r->description);
8256 :
8257 16 : r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8258 16 : r->reserved = 0;
8259 :
8260 16 : return WERR_OK;
8261 : }
8262 :
8263 :
8264 : /****************************************************************************
8265 : wrapper around the enum ports command
8266 : ****************************************************************************/
8267 :
8268 24 : static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8269 : {
8270 0 : const struct loadparm_substitution *lp_sub =
8271 24 : loadparm_s3_global_substitution();
8272 24 : char *cmd = lp_enumports_command(talloc_tos(), lp_sub);
8273 24 : char **qlines = NULL;
8274 24 : char *command = NULL;
8275 0 : int numlines;
8276 0 : int ret;
8277 0 : int fd;
8278 :
8279 24 : *count = 0;
8280 24 : *lines = NULL;
8281 :
8282 : /* if no hook then just fill in the default port */
8283 :
8284 24 : if ( !*cmd ) {
8285 24 : if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8286 0 : return WERR_NOT_ENOUGH_MEMORY;
8287 : }
8288 24 : if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8289 0 : TALLOC_FREE(qlines);
8290 0 : return WERR_NOT_ENOUGH_MEMORY;
8291 : }
8292 24 : qlines[1] = NULL;
8293 24 : numlines = 1;
8294 : }
8295 : else {
8296 : /* we have a valid enumport command */
8297 :
8298 0 : command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8299 0 : if (!command) {
8300 0 : return WERR_NOT_ENOUGH_MEMORY;
8301 : }
8302 :
8303 0 : DEBUG(10,("Running [%s]\n", command));
8304 0 : ret = smbrun(command, &fd, NULL);
8305 0 : DEBUG(10,("Returned [%d]\n", ret));
8306 0 : TALLOC_FREE(command);
8307 0 : if (ret != 0) {
8308 0 : if (fd != -1) {
8309 0 : close(fd);
8310 : }
8311 0 : return WERR_ACCESS_DENIED;
8312 : }
8313 :
8314 0 : numlines = 0;
8315 0 : qlines = fd_lines_load(fd, &numlines, 0, NULL);
8316 0 : DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8317 0 : close(fd);
8318 : }
8319 :
8320 24 : *count = numlines;
8321 24 : *lines = qlines;
8322 :
8323 24 : return WERR_OK;
8324 : }
8325 :
8326 : /****************************************************************************
8327 : enumports level 1.
8328 : ****************************************************************************/
8329 :
8330 8 : static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8331 : union spoolss_PortInfo **info_p,
8332 : uint32_t *count)
8333 : {
8334 8 : union spoolss_PortInfo *info = NULL;
8335 8 : int i=0;
8336 8 : WERROR result = WERR_OK;
8337 8 : char **qlines = NULL;
8338 8 : int numlines = 0;
8339 :
8340 8 : result = enumports_hook(talloc_tos(), &numlines, &qlines );
8341 8 : if (!W_ERROR_IS_OK(result)) {
8342 0 : goto out;
8343 : }
8344 :
8345 8 : if (numlines) {
8346 8 : info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8347 8 : if (!info) {
8348 0 : DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8349 0 : result = WERR_NOT_ENOUGH_MEMORY;
8350 0 : goto out;
8351 : }
8352 :
8353 16 : for (i=0; i<numlines; i++) {
8354 8 : DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8355 8 : result = fill_port_1(info, &info[i].info1, qlines[i]);
8356 8 : if (!W_ERROR_IS_OK(result)) {
8357 0 : goto out;
8358 : }
8359 : }
8360 : }
8361 8 : TALLOC_FREE(qlines);
8362 :
8363 0 : out:
8364 8 : if (!W_ERROR_IS_OK(result)) {
8365 0 : TALLOC_FREE(info);
8366 0 : TALLOC_FREE(qlines);
8367 0 : *count = 0;
8368 0 : *info_p = NULL;
8369 0 : return result;
8370 : }
8371 :
8372 8 : *info_p = info;
8373 8 : *count = numlines;
8374 :
8375 8 : return WERR_OK;
8376 : }
8377 :
8378 : /****************************************************************************
8379 : enumports level 2.
8380 : ****************************************************************************/
8381 :
8382 16 : static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8383 : union spoolss_PortInfo **info_p,
8384 : uint32_t *count)
8385 : {
8386 16 : union spoolss_PortInfo *info = NULL;
8387 16 : int i=0;
8388 16 : WERROR result = WERR_OK;
8389 16 : char **qlines = NULL;
8390 16 : int numlines = 0;
8391 :
8392 16 : result = enumports_hook(talloc_tos(), &numlines, &qlines );
8393 16 : if (!W_ERROR_IS_OK(result)) {
8394 0 : goto out;
8395 : }
8396 :
8397 16 : if (numlines) {
8398 16 : info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8399 16 : if (!info) {
8400 0 : DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8401 0 : result = WERR_NOT_ENOUGH_MEMORY;
8402 0 : goto out;
8403 : }
8404 :
8405 32 : for (i=0; i<numlines; i++) {
8406 16 : DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8407 16 : result = fill_port_2(info, &info[i].info2, qlines[i]);
8408 16 : if (!W_ERROR_IS_OK(result)) {
8409 0 : goto out;
8410 : }
8411 : }
8412 : }
8413 16 : TALLOC_FREE(qlines);
8414 :
8415 0 : out:
8416 16 : if (!W_ERROR_IS_OK(result)) {
8417 0 : TALLOC_FREE(info);
8418 0 : TALLOC_FREE(qlines);
8419 0 : *count = 0;
8420 0 : *info_p = NULL;
8421 0 : return result;
8422 : }
8423 :
8424 16 : *info_p = info;
8425 16 : *count = numlines;
8426 :
8427 16 : return WERR_OK;
8428 : }
8429 :
8430 : /****************************************************************
8431 : _spoolss_EnumPorts
8432 : ****************************************************************/
8433 :
8434 24 : WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8435 : struct spoolss_EnumPorts *r)
8436 : {
8437 0 : WERROR result;
8438 :
8439 : /* that's an [in out] buffer */
8440 :
8441 24 : if (!r->in.buffer && (r->in.offered != 0)) {
8442 0 : return WERR_INVALID_PARAMETER;
8443 : }
8444 :
8445 24 : DEBUG(4,("_spoolss_EnumPorts\n"));
8446 :
8447 24 : *r->out.count = 0;
8448 24 : *r->out.needed = 0;
8449 24 : *r->out.info = NULL;
8450 :
8451 24 : switch (r->in.level) {
8452 8 : case 1:
8453 8 : result = enumports_level_1(p->mem_ctx, r->out.info,
8454 : r->out.count);
8455 8 : break;
8456 16 : case 2:
8457 16 : result = enumports_level_2(p->mem_ctx, r->out.info,
8458 : r->out.count);
8459 16 : break;
8460 0 : default:
8461 0 : return WERR_INVALID_LEVEL;
8462 : }
8463 :
8464 24 : if (!W_ERROR_IS_OK(result)) {
8465 0 : return result;
8466 : }
8467 :
8468 24 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8469 : spoolss_EnumPorts,
8470 : *r->out.info, r->in.level,
8471 : *r->out.count);
8472 24 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8473 24 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8474 :
8475 24 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8476 : }
8477 :
8478 : /****************************************************************************
8479 : ****************************************************************************/
8480 :
8481 96 : static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8482 : const char *server,
8483 : struct spoolss_SetPrinterInfoCtr *info_ctr,
8484 : struct spoolss_DeviceMode *devmode,
8485 : struct security_descriptor *secdesc,
8486 : struct spoolss_UserLevelCtr *user_ctr,
8487 : struct policy_handle *handle)
8488 : {
8489 96 : struct dcesrv_call_state *dce_call = p->dce_call;
8490 96 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
8491 0 : const struct tsocket_address *remote_address =
8492 96 : dcesrv_connection_get_remote_address(dcesrv_conn);
8493 0 : struct auth_session_info *session_info =
8494 96 : dcesrv_call_session_info(dce_call);
8495 96 : struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8496 96 : uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8497 0 : const struct loadparm_substitution *lp_sub =
8498 96 : loadparm_s3_global_substitution();
8499 0 : int snum;
8500 96 : WERROR err = WERR_OK;
8501 :
8502 : /* samba does not have a concept of local, non-shared printers yet, so
8503 : * make sure we always setup sharename - gd */
8504 96 : if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8505 96 : (info2->printername != NULL && info2->printername[0] != '\0')) {
8506 80 : DEBUG(5, ("spoolss_addprinterex_level_2: "
8507 : "no sharename has been set, setting printername %s as sharename\n",
8508 : info2->printername));
8509 80 : info2->sharename = info2->printername;
8510 : }
8511 :
8512 : /* check to see if the printer already exists */
8513 96 : if ((snum = print_queue_snum(info2->sharename)) != -1) {
8514 16 : DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8515 : info2->sharename));
8516 16 : return WERR_PRINTER_ALREADY_EXISTS;
8517 : }
8518 :
8519 80 : if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8520 80 : if ((snum = print_queue_snum(info2->printername)) != -1) {
8521 0 : DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8522 : info2->printername));
8523 0 : return WERR_PRINTER_ALREADY_EXISTS;
8524 : }
8525 : }
8526 :
8527 : /* validate printer info struct */
8528 80 : if (!info2->printername || strlen(info2->printername) == 0) {
8529 16 : return WERR_INVALID_PRINTER_NAME;
8530 : }
8531 64 : if (!info2->portname || strlen(info2->portname) == 0) {
8532 16 : return WERR_UNKNOWN_PORT;
8533 : }
8534 48 : if (!info2->drivername || strlen(info2->drivername) == 0) {
8535 16 : return WERR_UNKNOWN_PRINTER_DRIVER;
8536 : }
8537 32 : if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8538 16 : return WERR_UNKNOWN_PRINTPROCESSOR;
8539 : }
8540 :
8541 : /* FIXME!!! smbd should check to see if the driver is installed before
8542 : trying to add a printer like this --jerry */
8543 :
8544 16 : if (*lp_addprinter_command(talloc_tos(), lp_sub) ) {
8545 0 : char *raddr;
8546 :
8547 16 : raddr = tsocket_address_inet_addr_string(remote_address,
8548 : p->mem_ctx);
8549 16 : if (raddr == NULL) {
8550 0 : return WERR_NOT_ENOUGH_MEMORY;
8551 : }
8552 :
8553 16 : if ( !add_printer_hook(p->mem_ctx, session_info->security_token,
8554 : info2, raddr,
8555 : p->msg_ctx) ) {
8556 0 : return WERR_ACCESS_DENIED;
8557 : }
8558 : } else {
8559 0 : DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8560 : "smb.conf parameter \"addprinter command\" is defined. This "
8561 : "parameter must exist for this call to succeed\n",
8562 : info2->sharename ));
8563 : }
8564 :
8565 16 : if ((snum = print_queue_snum(info2->sharename)) == -1) {
8566 0 : return WERR_ACCESS_DENIED;
8567 : }
8568 :
8569 : /* you must be a printer admin to add a new printer */
8570 16 : if (!W_ERROR_IS_OK(print_access_check(session_info,
8571 : p->msg_ctx,
8572 : snum,
8573 : PRINTER_ACCESS_ADMINISTER))) {
8574 0 : return WERR_ACCESS_DENIED;
8575 : }
8576 :
8577 : /*
8578 : * Do sanity check on the requested changes for Samba.
8579 : */
8580 :
8581 16 : if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8582 0 : return WERR_INVALID_PARAMETER;
8583 : }
8584 :
8585 16 : if (devmode == NULL) {
8586 16 : info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
8587 : }
8588 :
8589 16 : err = update_dsspooler(p->mem_ctx,
8590 : get_session_info_system(),
8591 : p->msg_ctx,
8592 : 0,
8593 : info2,
8594 : NULL);
8595 16 : if (!W_ERROR_IS_OK(err)) {
8596 0 : return err;
8597 : }
8598 :
8599 16 : err = winreg_update_printer_internal(p->mem_ctx,
8600 : get_session_info_system(),
8601 : p->msg_ctx,
8602 : info2->sharename,
8603 : info2_mask,
8604 : info2,
8605 : devmode,
8606 : secdesc);
8607 16 : if (!W_ERROR_IS_OK(err)) {
8608 0 : return err;
8609 : }
8610 :
8611 16 : err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8612 16 : if (!W_ERROR_IS_OK(err)) {
8613 : /* Handle open failed - remove addition. */
8614 0 : ZERO_STRUCTP(handle);
8615 0 : return err;
8616 : }
8617 :
8618 16 : return WERR_OK;
8619 : }
8620 :
8621 : /****************************************************************
8622 : _spoolss_AddPrinterEx
8623 : ****************************************************************/
8624 :
8625 96 : WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8626 : struct spoolss_AddPrinterEx *r)
8627 : {
8628 96 : switch (r->in.info_ctr->level) {
8629 0 : case 1:
8630 : /* we don't handle yet */
8631 : /* but I know what to do ... */
8632 0 : return WERR_INVALID_LEVEL;
8633 96 : case 2:
8634 96 : return spoolss_addprinterex_level_2(p, r->in.server,
8635 : r->in.info_ctr,
8636 96 : r->in.devmode_ctr->devmode,
8637 96 : r->in.secdesc_ctr->sd,
8638 : r->in.userlevel_ctr,
8639 : r->out.handle);
8640 0 : default:
8641 0 : return WERR_INVALID_LEVEL;
8642 : }
8643 : }
8644 :
8645 : /****************************************************************
8646 : _spoolss_AddPrinter
8647 : ****************************************************************/
8648 :
8649 72 : WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8650 : struct spoolss_AddPrinter *r)
8651 : {
8652 0 : struct spoolss_AddPrinterEx a;
8653 0 : struct spoolss_UserLevelCtr userlevel_ctr;
8654 :
8655 72 : ZERO_STRUCT(userlevel_ctr);
8656 :
8657 72 : userlevel_ctr.level = 1;
8658 :
8659 72 : a.in.server = r->in.server;
8660 72 : a.in.info_ctr = r->in.info_ctr;
8661 72 : a.in.devmode_ctr = r->in.devmode_ctr;
8662 72 : a.in.secdesc_ctr = r->in.secdesc_ctr;
8663 72 : a.in.userlevel_ctr = &userlevel_ctr;
8664 72 : a.out.handle = r->out.handle;
8665 :
8666 72 : return _spoolss_AddPrinterEx(p, &a);
8667 : }
8668 :
8669 : /****************************************************************
8670 : _spoolss_AddPrinterDriverEx
8671 : ****************************************************************/
8672 :
8673 0 : WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8674 : struct spoolss_AddPrinterDriverEx *r)
8675 : {
8676 0 : struct dcesrv_call_state *dce_call = p->dce_call;
8677 0 : struct auth_session_info *session_info =
8678 0 : dcesrv_call_session_info(dce_call);
8679 0 : WERROR err = WERR_OK;
8680 0 : const char *driver_name = NULL;
8681 0 : const char *driver_directory = NULL;
8682 0 : uint32_t version;
8683 :
8684 : /*
8685 : * we only support the semantics of AddPrinterDriver()
8686 : * i.e. only copy files that are newer than existing ones
8687 : */
8688 :
8689 0 : if (r->in.flags == 0) {
8690 0 : return WERR_INVALID_PARAMETER;
8691 : }
8692 :
8693 0 : if (!(r->in.flags & APD_COPY_ALL_FILES) &&
8694 0 : !(r->in.flags & APD_COPY_NEW_FILES)) {
8695 0 : return WERR_ACCESS_DENIED;
8696 : }
8697 :
8698 : /* FIXME */
8699 0 : if (r->in.info_ctr->level != 3 &&
8700 0 : r->in.info_ctr->level != 6 &&
8701 0 : r->in.info_ctr->level != 8) {
8702 0 : DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8703 : r->in.info_ctr->level));
8704 0 : return WERR_INVALID_LEVEL;
8705 : }
8706 :
8707 0 : DEBUG(5,("Cleaning driver's information\n"));
8708 0 : err = clean_up_driver_struct(p->mem_ctx,
8709 : session_info,
8710 0 : r->in.info_ctr,
8711 : r->in.flags,
8712 : &driver_directory);
8713 0 : if (!W_ERROR_IS_OK(err)) {
8714 0 : DBG_ERR("clean_up_driver_struct failed - %s\n",
8715 : win_errstr(err));
8716 0 : goto done;
8717 : }
8718 :
8719 0 : DEBUG(5,("Moving driver to final destination\n"));
8720 0 : err = move_driver_to_download_area(session_info,
8721 0 : r->in.info_ctr,
8722 : driver_directory);
8723 0 : if (!W_ERROR_IS_OK(err)) {
8724 0 : DBG_ERR("move_driver_to_download_area failed - %s\n",
8725 : win_errstr(err));
8726 0 : goto done;
8727 : }
8728 :
8729 0 : err = winreg_add_driver_internal(p->mem_ctx,
8730 : get_session_info_system(),
8731 : p->msg_ctx,
8732 : r->in.info_ctr,
8733 : &driver_name,
8734 : &version);
8735 0 : if (!W_ERROR_IS_OK(err)) {
8736 0 : DBG_ERR("winreg_add_driver_internal failed - %s\n",
8737 : win_errstr(err));
8738 0 : goto done;
8739 : }
8740 :
8741 : /*
8742 : * I think this is where the DrvUpgradePrinter() hook would be
8743 : * be called in a driver's interface DLL on a Windows NT 4.0/2k
8744 : * server. Right now, we just need to send ourselves a message
8745 : * to update each printer bound to this driver. --jerry
8746 : */
8747 :
8748 0 : if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8749 0 : DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8750 : __func__, driver_name));
8751 : }
8752 :
8753 0 : done:
8754 0 : return err;
8755 : }
8756 :
8757 : /****************************************************************
8758 : _spoolss_AddPrinterDriver
8759 : ****************************************************************/
8760 :
8761 0 : WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8762 : struct spoolss_AddPrinterDriver *r)
8763 : {
8764 0 : struct spoolss_AddPrinterDriverEx a;
8765 :
8766 0 : switch (r->in.info_ctr->level) {
8767 0 : case 2:
8768 : case 3:
8769 : case 4:
8770 : case 5:
8771 0 : break;
8772 0 : default:
8773 0 : return WERR_INVALID_LEVEL;
8774 : }
8775 :
8776 0 : a.in.servername = r->in.servername;
8777 0 : a.in.info_ctr = r->in.info_ctr;
8778 0 : a.in.flags = APD_COPY_NEW_FILES;
8779 :
8780 0 : return _spoolss_AddPrinterDriverEx(p, &a);
8781 : }
8782 :
8783 : /****************************************************************************
8784 : ****************************************************************************/
8785 :
8786 : struct _spoolss_paths {
8787 : int type;
8788 : const char *share;
8789 : const char *dir;
8790 : };
8791 :
8792 : enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8793 :
8794 : static const struct _spoolss_paths spoolss_paths[]= {
8795 : { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8796 : { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8797 : };
8798 :
8799 208 : static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8800 : const char *servername,
8801 : const char *environment,
8802 : int component,
8803 : char **path)
8804 : {
8805 208 : const char *pservername = NULL;
8806 0 : const char *long_archi;
8807 0 : const char *short_archi;
8808 :
8809 208 : *path = NULL;
8810 :
8811 : /* environment may be empty */
8812 208 : if (environment && strlen(environment)) {
8813 208 : long_archi = environment;
8814 : } else {
8815 0 : long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8816 : "spoolss", "architecture",
8817 : GLOBAL_SPOOLSS_ARCHITECTURE);
8818 : }
8819 :
8820 : /* servername may be empty */
8821 208 : if (servername && strlen(servername)) {
8822 144 : pservername = canon_servername(servername);
8823 :
8824 144 : if (!is_myname_or_ipaddr(pservername)) {
8825 0 : return WERR_INVALID_PARAMETER;
8826 : }
8827 : }
8828 :
8829 208 : if (!(short_archi = get_short_archi(long_archi))) {
8830 0 : return WERR_INVALID_ENVIRONMENT;
8831 : }
8832 :
8833 208 : switch (component) {
8834 208 : case SPOOLSS_PRTPROCS_PATH:
8835 : case SPOOLSS_DRIVER_PATH:
8836 208 : if (pservername) {
8837 144 : *path = talloc_asprintf(mem_ctx,
8838 : "\\\\%s\\%s\\%s",
8839 : pservername,
8840 144 : spoolss_paths[component].share,
8841 : short_archi);
8842 : } else {
8843 64 : *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8844 : SPOOLSS_DEFAULT_SERVER_PATH,
8845 64 : spoolss_paths[component].dir,
8846 : short_archi);
8847 : }
8848 208 : break;
8849 0 : default:
8850 0 : return WERR_INVALID_PARAMETER;
8851 : }
8852 :
8853 208 : if (!*path) {
8854 0 : return WERR_NOT_ENOUGH_MEMORY;
8855 : }
8856 :
8857 208 : return WERR_OK;
8858 : }
8859 :
8860 : /****************************************************************************
8861 : ****************************************************************************/
8862 :
8863 168 : static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8864 : const char *servername,
8865 : const char *environment,
8866 : struct spoolss_DriverDirectoryInfo1 *r)
8867 : {
8868 0 : WERROR werr;
8869 168 : char *path = NULL;
8870 :
8871 168 : werr = compose_spoolss_server_path(mem_ctx,
8872 : servername,
8873 : environment,
8874 : SPOOLSS_DRIVER_PATH,
8875 : &path);
8876 168 : if (!W_ERROR_IS_OK(werr)) {
8877 0 : return werr;
8878 : }
8879 :
8880 168 : DEBUG(4,("printer driver directory: [%s]\n", path));
8881 :
8882 168 : r->directory_name = path;
8883 :
8884 168 : return WERR_OK;
8885 : }
8886 :
8887 : /****************************************************************
8888 : _spoolss_GetPrinterDriverDirectory
8889 : ****************************************************************/
8890 :
8891 168 : WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8892 : struct spoolss_GetPrinterDriverDirectory *r)
8893 : {
8894 0 : WERROR werror;
8895 :
8896 : /* that's an [in out] buffer */
8897 :
8898 168 : if (!r->in.buffer && (r->in.offered != 0)) {
8899 0 : TALLOC_FREE(r->out.info);
8900 0 : return WERR_INVALID_PARAMETER;
8901 : }
8902 :
8903 168 : DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8904 : r->in.level));
8905 :
8906 168 : *r->out.needed = 0;
8907 :
8908 : /* r->in.level is ignored */
8909 :
8910 168 : werror = getprinterdriverdir_level_1(p->mem_ctx,
8911 : r->in.server,
8912 : r->in.environment,
8913 168 : &r->out.info->info1);
8914 168 : if (!W_ERROR_IS_OK(werror)) {
8915 0 : TALLOC_FREE(r->out.info);
8916 0 : return werror;
8917 : }
8918 :
8919 168 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8920 : r->out.info, r->in.level);
8921 168 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8922 :
8923 168 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8924 : }
8925 :
8926 : /****************************************************************
8927 : _spoolss_EnumPrinterData
8928 : ****************************************************************/
8929 :
8930 152 : WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8931 : struct spoolss_EnumPrinterData *r)
8932 : {
8933 0 : WERROR result;
8934 0 : struct spoolss_EnumPrinterDataEx r2;
8935 0 : uint32_t count;
8936 152 : struct spoolss_PrinterEnumValues *info, *val = NULL;
8937 0 : uint32_t needed;
8938 :
8939 152 : r2.in.handle = r->in.handle;
8940 152 : r2.in.key_name = "PrinterDriverData";
8941 152 : r2.in.offered = 0;
8942 152 : r2.out.count = &count;
8943 152 : r2.out.info = &info;
8944 152 : r2.out.needed = &needed;
8945 :
8946 152 : result = _spoolss_EnumPrinterDataEx(p, &r2);
8947 152 : if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8948 112 : r2.in.offered = needed;
8949 112 : result = _spoolss_EnumPrinterDataEx(p, &r2);
8950 : }
8951 152 : if (!W_ERROR_IS_OK(result)) {
8952 0 : return result;
8953 : }
8954 :
8955 : /*
8956 : * The NT machine wants to know the biggest size of value and data
8957 : *
8958 : * cf: MSDN EnumPrinterData remark section
8959 : */
8960 :
8961 152 : if (!r->in.value_offered && !r->in.data_offered) {
8962 48 : uint32_t biggest_valuesize = 0;
8963 48 : uint32_t biggest_datasize = 0;
8964 0 : int i, name_length;
8965 :
8966 48 : DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8967 :
8968 132 : for (i=0; i<count; i++) {
8969 :
8970 84 : name_length = strlen(info[i].value_name);
8971 84 : if (strlen(info[i].value_name) > biggest_valuesize) {
8972 28 : biggest_valuesize = name_length;
8973 : }
8974 :
8975 84 : if (info[i].data_length > biggest_datasize) {
8976 28 : biggest_datasize = info[i].data_length;
8977 : }
8978 :
8979 84 : DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8980 : biggest_datasize));
8981 : }
8982 :
8983 : /* the value is an UNICODE string but real_value_size is the length
8984 : in bytes including the trailing 0 */
8985 :
8986 48 : *r->out.value_needed = 2 * (1 + biggest_valuesize);
8987 48 : *r->out.data_needed = biggest_datasize;
8988 :
8989 48 : DEBUG(6,("final values: [%d], [%d]\n",
8990 : *r->out.value_needed, *r->out.data_needed));
8991 :
8992 48 : return WERR_OK;
8993 : }
8994 :
8995 104 : if (r->in.enum_index < count) {
8996 84 : val = &info[r->in.enum_index];
8997 : }
8998 :
8999 104 : if (val == NULL) {
9000 : /* out_value should default to "" or else NT4 has
9001 : problems unmarshalling the response */
9002 :
9003 20 : if (r->in.value_offered) {
9004 20 : *r->out.value_needed = 1;
9005 20 : r->out.value_name = talloc_strdup(r, "");
9006 20 : if (!r->out.value_name) {
9007 0 : return WERR_NOT_ENOUGH_MEMORY;
9008 : }
9009 : } else {
9010 0 : r->out.value_name = NULL;
9011 0 : *r->out.value_needed = 0;
9012 : }
9013 :
9014 : /* the data is counted in bytes */
9015 :
9016 20 : *r->out.data_needed = r->in.data_offered;
9017 :
9018 20 : result = WERR_NO_MORE_ITEMS;
9019 : } else {
9020 : /*
9021 : * the value is:
9022 : * - counted in bytes in the request
9023 : * - counted in UNICODE chars in the max reply
9024 : * - counted in bytes in the real size
9025 : *
9026 : * take a pause *before* coding not *during* coding
9027 : */
9028 :
9029 : /* name */
9030 84 : if (r->in.value_offered) {
9031 84 : r->out.value_name = talloc_strdup(r, val->value_name);
9032 84 : if (!r->out.value_name) {
9033 0 : return WERR_NOT_ENOUGH_MEMORY;
9034 : }
9035 84 : *r->out.value_needed = val->value_name_len;
9036 : } else {
9037 0 : r->out.value_name = NULL;
9038 0 : *r->out.value_needed = 0;
9039 : }
9040 :
9041 : /* type */
9042 :
9043 84 : *r->out.type = val->type;
9044 :
9045 : /* data - counted in bytes */
9046 :
9047 : /*
9048 : * See the section "Dynamically Typed Query Parameters"
9049 : * in MS-RPRN.
9050 : */
9051 :
9052 84 : if (r->out.data && val->data && val->data->data &&
9053 84 : val->data_length && r->in.data_offered) {
9054 84 : memcpy(r->out.data, val->data->data,
9055 84 : MIN(val->data_length,r->in.data_offered));
9056 : }
9057 :
9058 84 : *r->out.data_needed = val->data_length;
9059 :
9060 84 : result = WERR_OK;
9061 : }
9062 :
9063 104 : return result;
9064 : }
9065 :
9066 : /****************************************************************
9067 : _spoolss_SetPrinterData
9068 : ****************************************************************/
9069 :
9070 168 : WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
9071 : struct spoolss_SetPrinterData *r)
9072 : {
9073 0 : struct spoolss_SetPrinterDataEx r2;
9074 :
9075 168 : r2.in.handle = r->in.handle;
9076 168 : r2.in.key_name = "PrinterDriverData";
9077 168 : r2.in.value_name = r->in.value_name;
9078 168 : r2.in.type = r->in.type;
9079 168 : r2.in.data = r->in.data;
9080 168 : r2.in.offered = r->in.offered;
9081 :
9082 168 : return _spoolss_SetPrinterDataEx(p, &r2);
9083 : }
9084 :
9085 : /****************************************************************
9086 : _spoolss_ResetPrinter
9087 : ****************************************************************/
9088 :
9089 0 : WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
9090 : struct spoolss_ResetPrinter *r)
9091 : {
9092 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9093 0 : int snum;
9094 :
9095 0 : DEBUG(5,("_spoolss_ResetPrinter\n"));
9096 :
9097 : /*
9098 : * All we do is to check to see if the handle and queue is valid.
9099 : * This call really doesn't mean anything to us because we only
9100 : * support RAW printing. --jerry
9101 : */
9102 :
9103 0 : if (!Printer) {
9104 0 : DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
9105 : OUR_HANDLE(r->in.handle)));
9106 0 : return WERR_INVALID_HANDLE;
9107 : }
9108 :
9109 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9110 0 : return WERR_INVALID_HANDLE;
9111 :
9112 :
9113 : /* blindly return success */
9114 0 : return WERR_OK;
9115 : }
9116 :
9117 : /****************************************************************
9118 : _spoolss_DeletePrinterData
9119 : ****************************************************************/
9120 :
9121 168 : WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
9122 : struct spoolss_DeletePrinterData *r)
9123 : {
9124 0 : struct spoolss_DeletePrinterDataEx r2;
9125 :
9126 168 : r2.in.handle = r->in.handle;
9127 168 : r2.in.key_name = "PrinterDriverData";
9128 168 : r2.in.value_name = r->in.value_name;
9129 :
9130 168 : return _spoolss_DeletePrinterDataEx(p, &r2);
9131 : }
9132 :
9133 : /****************************************************************
9134 : _spoolss_AddForm
9135 : ****************************************************************/
9136 :
9137 576 : WERROR _spoolss_AddForm(struct pipes_struct *p,
9138 : struct spoolss_AddForm *r)
9139 : {
9140 576 : struct dcesrv_call_state *dce_call = p->dce_call;
9141 0 : struct auth_session_info *session_info =
9142 576 : dcesrv_call_session_info(dce_call);
9143 0 : struct spoolss_AddFormInfo1 *form;
9144 576 : int snum = -1;
9145 576 : WERROR status = WERR_OK;
9146 576 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9147 0 : struct dcerpc_binding_handle *b;
9148 576 : TALLOC_CTX *tmp_ctx = NULL;
9149 :
9150 576 : DEBUG(5,("_spoolss_AddForm\n"));
9151 :
9152 576 : if (!Printer) {
9153 0 : DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
9154 : OUR_HANDLE(r->in.handle)));
9155 0 : return WERR_INVALID_HANDLE;
9156 : }
9157 :
9158 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9159 : and not a printer admin, then fail */
9160 :
9161 576 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
9162 0 : !security_token_has_privilege(session_info->security_token,
9163 : SEC_PRIV_PRINT_OPERATOR)) {
9164 0 : DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
9165 0 : return WERR_ACCESS_DENIED;
9166 : }
9167 :
9168 576 : if (r->in.info_ctr->level != 1) {
9169 0 : return WERR_INVALID_LEVEL;
9170 : }
9171 :
9172 576 : form = r->in.info_ctr->info.info1;
9173 576 : if (!form) {
9174 0 : return WERR_INVALID_PARAMETER;
9175 : }
9176 :
9177 576 : switch (form->flags) {
9178 480 : case SPOOLSS_FORM_USER:
9179 : case SPOOLSS_FORM_BUILTIN:
9180 : case SPOOLSS_FORM_PRINTER:
9181 480 : break;
9182 96 : default:
9183 96 : return WERR_INVALID_PARAMETER;
9184 : }
9185 :
9186 480 : tmp_ctx = talloc_new(p->mem_ctx);
9187 480 : if (!tmp_ctx) {
9188 0 : return WERR_NOT_ENOUGH_MEMORY;
9189 : }
9190 :
9191 480 : status = winreg_printer_binding_handle(tmp_ctx,
9192 : get_session_info_system(),
9193 : p->msg_ctx,
9194 : &b);
9195 480 : if (!W_ERROR_IS_OK(status)) {
9196 0 : goto done;
9197 : }
9198 :
9199 480 : status = winreg_printer_addform1(tmp_ctx, b, form);
9200 480 : if (!W_ERROR_IS_OK(status)) {
9201 384 : goto done;
9202 : }
9203 :
9204 : /*
9205 : * ChangeID must always be set if this is a printer
9206 : */
9207 96 : if (Printer->printer_type == SPLHND_PRINTER) {
9208 80 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9209 0 : status = WERR_INVALID_HANDLE;
9210 0 : goto done;
9211 : }
9212 :
9213 80 : status = winreg_printer_update_changeid(tmp_ctx, b,
9214 : lp_const_servicename(snum));
9215 : }
9216 :
9217 16 : done:
9218 480 : talloc_free(tmp_ctx);
9219 480 : return status;
9220 : }
9221 :
9222 : /****************************************************************
9223 : _spoolss_DeleteForm
9224 : ****************************************************************/
9225 :
9226 384 : WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9227 : struct spoolss_DeleteForm *r)
9228 : {
9229 384 : struct dcesrv_call_state *dce_call = p->dce_call;
9230 0 : struct auth_session_info *session_info =
9231 384 : dcesrv_call_session_info(dce_call);
9232 384 : const char *form_name = r->in.form_name;
9233 384 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9234 384 : int snum = -1;
9235 384 : WERROR status = WERR_OK;
9236 0 : struct dcerpc_binding_handle *b;
9237 384 : TALLOC_CTX *tmp_ctx = NULL;
9238 :
9239 384 : DEBUG(5,("_spoolss_DeleteForm\n"));
9240 :
9241 384 : if (!Printer) {
9242 0 : DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9243 : OUR_HANDLE(r->in.handle)));
9244 0 : return WERR_INVALID_HANDLE;
9245 : }
9246 :
9247 384 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
9248 0 : !security_token_has_privilege(session_info->security_token,
9249 : SEC_PRIV_PRINT_OPERATOR)) {
9250 0 : DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9251 0 : return WERR_ACCESS_DENIED;
9252 : }
9253 :
9254 384 : tmp_ctx = talloc_new(p->mem_ctx);
9255 384 : if (!tmp_ctx) {
9256 0 : return WERR_NOT_ENOUGH_MEMORY;
9257 : }
9258 :
9259 384 : status = winreg_printer_binding_handle(tmp_ctx,
9260 : get_session_info_system(),
9261 : p->msg_ctx,
9262 : &b);
9263 384 : if (!W_ERROR_IS_OK(status)) {
9264 0 : goto done;
9265 : }
9266 :
9267 384 : status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9268 384 : if (!W_ERROR_IS_OK(status)) {
9269 288 : goto done;
9270 : }
9271 :
9272 : /*
9273 : * ChangeID must always be set if this is a printer
9274 : */
9275 96 : if (Printer->printer_type == SPLHND_PRINTER) {
9276 80 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9277 0 : status = WERR_INVALID_HANDLE;
9278 0 : goto done;
9279 : }
9280 :
9281 80 : status = winreg_printer_update_changeid(tmp_ctx, b,
9282 : lp_const_servicename(snum));
9283 : }
9284 :
9285 16 : done:
9286 384 : talloc_free(tmp_ctx);
9287 384 : return status;
9288 : }
9289 :
9290 : /****************************************************************
9291 : _spoolss_SetForm
9292 : ****************************************************************/
9293 :
9294 80 : WERROR _spoolss_SetForm(struct pipes_struct *p,
9295 : struct spoolss_SetForm *r)
9296 : {
9297 80 : struct dcesrv_call_state *dce_call = p->dce_call;
9298 0 : struct auth_session_info *session_info =
9299 80 : dcesrv_call_session_info(dce_call);
9300 0 : struct spoolss_AddFormInfo1 *form;
9301 80 : const char *form_name = r->in.form_name;
9302 80 : int snum = -1;
9303 80 : WERROR status = WERR_OK;
9304 0 : struct dcerpc_binding_handle *b;
9305 80 : TALLOC_CTX *tmp_ctx = NULL;
9306 :
9307 80 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9308 :
9309 80 : DEBUG(5,("_spoolss_SetForm\n"));
9310 :
9311 80 : if (!Printer) {
9312 0 : DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9313 : OUR_HANDLE(r->in.handle)));
9314 0 : return WERR_INVALID_HANDLE;
9315 : }
9316 :
9317 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9318 : and not a printer admin, then fail */
9319 :
9320 80 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
9321 0 : !security_token_has_privilege(session_info->security_token,
9322 : SEC_PRIV_PRINT_OPERATOR)) {
9323 0 : DEBUG(2,("_spoolss_SetForm: denied by insufficient permissions.\n"));
9324 0 : return WERR_ACCESS_DENIED;
9325 : }
9326 :
9327 80 : if (r->in.info_ctr->level != 1) {
9328 0 : return WERR_INVALID_LEVEL;
9329 : }
9330 :
9331 80 : form = r->in.info_ctr->info.info1;
9332 80 : if (!form) {
9333 0 : return WERR_INVALID_PARAMETER;
9334 : }
9335 :
9336 80 : tmp_ctx = talloc_new(p->mem_ctx);
9337 80 : if (!tmp_ctx) {
9338 0 : return WERR_NOT_ENOUGH_MEMORY;
9339 : }
9340 :
9341 80 : status = winreg_printer_binding_handle(tmp_ctx,
9342 : get_session_info_system(),
9343 : p->msg_ctx,
9344 : &b);
9345 80 : if (!W_ERROR_IS_OK(status)) {
9346 0 : goto done;
9347 : }
9348 :
9349 80 : status = winreg_printer_setform1(tmp_ctx, b,
9350 : form_name,
9351 : form);
9352 80 : if (!W_ERROR_IS_OK(status)) {
9353 0 : goto done;
9354 : }
9355 :
9356 : /*
9357 : * ChangeID must always be set if this is a printer
9358 : */
9359 80 : if (Printer->printer_type == SPLHND_PRINTER) {
9360 80 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9361 0 : status = WERR_INVALID_HANDLE;
9362 0 : goto done;
9363 : }
9364 :
9365 80 : status = winreg_printer_update_changeid(tmp_ctx, b,
9366 : lp_const_servicename(snum));
9367 : }
9368 :
9369 0 : done:
9370 80 : talloc_free(tmp_ctx);
9371 80 : return status;
9372 : }
9373 :
9374 : /****************************************************************************
9375 : fill_print_processor1
9376 : ****************************************************************************/
9377 :
9378 24 : static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9379 : struct spoolss_PrintProcessorInfo1 *r,
9380 : const char *print_processor_name)
9381 : {
9382 24 : r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9383 24 : W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9384 :
9385 24 : return WERR_OK;
9386 : }
9387 :
9388 : /****************************************************************************
9389 : enumprintprocessors level 1.
9390 : ****************************************************************************/
9391 :
9392 24 : static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9393 : union spoolss_PrintProcessorInfo **info_p,
9394 : uint32_t *count)
9395 : {
9396 0 : union spoolss_PrintProcessorInfo *info;
9397 0 : WERROR result;
9398 :
9399 24 : info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9400 24 : W_ERROR_HAVE_NO_MEMORY(info);
9401 :
9402 24 : *count = 1;
9403 :
9404 24 : result = fill_print_processor1(info, &info[0].info1, "winprint");
9405 24 : if (!W_ERROR_IS_OK(result)) {
9406 0 : goto out;
9407 : }
9408 :
9409 24 : out:
9410 24 : if (!W_ERROR_IS_OK(result)) {
9411 0 : TALLOC_FREE(info);
9412 0 : *count = 0;
9413 0 : return result;
9414 : }
9415 :
9416 24 : *info_p = info;
9417 :
9418 24 : return WERR_OK;
9419 : }
9420 :
9421 : /****************************************************************
9422 : _spoolss_EnumPrintProcessors
9423 : ****************************************************************/
9424 :
9425 48 : WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9426 : struct spoolss_EnumPrintProcessors *r)
9427 : {
9428 0 : WERROR result;
9429 :
9430 : /* that's an [in out] buffer */
9431 :
9432 48 : if (!r->in.buffer && (r->in.offered != 0)) {
9433 0 : return WERR_INVALID_PARAMETER;
9434 : }
9435 :
9436 48 : DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9437 :
9438 : /*
9439 : * Enumerate the print processors ...
9440 : *
9441 : * Just reply with "winprint", to keep NT happy
9442 : * and I can use my nice printer checker.
9443 : */
9444 :
9445 48 : *r->out.count = 0;
9446 48 : *r->out.needed = 0;
9447 48 : *r->out.info = NULL;
9448 :
9449 48 : if (!get_short_archi(r->in.environment)) {
9450 4 : return WERR_INVALID_ENVIRONMENT;
9451 : }
9452 :
9453 44 : switch (r->in.level) {
9454 24 : case 1:
9455 24 : result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9456 : r->out.count);
9457 24 : break;
9458 20 : default:
9459 20 : return WERR_INVALID_LEVEL;
9460 : }
9461 :
9462 24 : if (!W_ERROR_IS_OK(result)) {
9463 0 : return result;
9464 : }
9465 :
9466 24 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9467 : spoolss_EnumPrintProcessors,
9468 : *r->out.info, r->in.level,
9469 : *r->out.count);
9470 24 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9471 24 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9472 :
9473 24 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9474 : }
9475 :
9476 : /****************************************************************************
9477 : fill_printprocdatatype1
9478 : ****************************************************************************/
9479 :
9480 16 : static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9481 : struct spoolss_PrintProcDataTypesInfo1 *r,
9482 : const char *name_array)
9483 : {
9484 16 : r->name_array = talloc_strdup(mem_ctx, name_array);
9485 16 : W_ERROR_HAVE_NO_MEMORY(r->name_array);
9486 :
9487 16 : return WERR_OK;
9488 : }
9489 :
9490 : /****************************************************************************
9491 : enumprintprocdatatypes level 1.
9492 : ****************************************************************************/
9493 :
9494 16 : static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9495 : union spoolss_PrintProcDataTypesInfo **info_p,
9496 : uint32_t *count)
9497 : {
9498 0 : WERROR result;
9499 0 : union spoolss_PrintProcDataTypesInfo *info;
9500 :
9501 16 : info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9502 16 : W_ERROR_HAVE_NO_MEMORY(info);
9503 :
9504 16 : *count = 1;
9505 :
9506 16 : result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9507 16 : if (!W_ERROR_IS_OK(result)) {
9508 0 : goto out;
9509 : }
9510 :
9511 16 : out:
9512 16 : if (!W_ERROR_IS_OK(result)) {
9513 0 : TALLOC_FREE(info);
9514 0 : *count = 0;
9515 0 : return result;
9516 : }
9517 :
9518 16 : *info_p = info;
9519 :
9520 16 : return WERR_OK;
9521 : }
9522 :
9523 : /****************************************************************
9524 : _spoolss_EnumPrintProcessorDataTypes
9525 : ****************************************************************/
9526 :
9527 44 : WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9528 : struct spoolss_EnumPrintProcessorDataTypes *r)
9529 : {
9530 0 : WERROR result;
9531 :
9532 : /* that's an [in out] buffer */
9533 :
9534 44 : if (!r->in.buffer && (r->in.offered != 0)) {
9535 0 : return WERR_INVALID_PARAMETER;
9536 : }
9537 :
9538 44 : DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9539 :
9540 44 : *r->out.count = 0;
9541 44 : *r->out.needed = 0;
9542 44 : *r->out.info = NULL;
9543 :
9544 44 : if (r->in.print_processor_name == NULL ||
9545 40 : !strequal(r->in.print_processor_name, "winprint")) {
9546 8 : return WERR_UNKNOWN_PRINTPROCESSOR;
9547 : }
9548 :
9549 36 : switch (r->in.level) {
9550 16 : case 1:
9551 16 : result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9552 : r->out.count);
9553 16 : break;
9554 20 : default:
9555 20 : return WERR_INVALID_LEVEL;
9556 : }
9557 :
9558 16 : if (!W_ERROR_IS_OK(result)) {
9559 0 : return result;
9560 : }
9561 :
9562 16 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9563 : spoolss_EnumPrintProcessorDataTypes,
9564 : *r->out.info, r->in.level,
9565 : *r->out.count);
9566 16 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9567 16 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9568 :
9569 16 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9570 : }
9571 :
9572 : /****************************************************************************
9573 : fill_monitor_1
9574 : ****************************************************************************/
9575 :
9576 16 : static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9577 : struct spoolss_MonitorInfo1 *r,
9578 : const char *monitor_name)
9579 : {
9580 16 : r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9581 16 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9582 :
9583 16 : return WERR_OK;
9584 : }
9585 :
9586 : /****************************************************************************
9587 : fill_monitor_2
9588 : ****************************************************************************/
9589 :
9590 16 : static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9591 : struct spoolss_MonitorInfo2 *r,
9592 : const char *monitor_name,
9593 : const char *environment,
9594 : const char *dll_name)
9595 : {
9596 16 : r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9597 16 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9598 16 : r->environment = talloc_strdup(mem_ctx, environment);
9599 16 : W_ERROR_HAVE_NO_MEMORY(r->environment);
9600 16 : r->dll_name = talloc_strdup(mem_ctx, dll_name);
9601 16 : W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9602 :
9603 16 : return WERR_OK;
9604 : }
9605 :
9606 : /****************************************************************************
9607 : enumprintmonitors level 1.
9608 : ****************************************************************************/
9609 :
9610 8 : static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9611 : union spoolss_MonitorInfo **info_p,
9612 : uint32_t *count)
9613 : {
9614 0 : union spoolss_MonitorInfo *info;
9615 8 : WERROR result = WERR_OK;
9616 :
9617 8 : info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9618 8 : W_ERROR_HAVE_NO_MEMORY(info);
9619 :
9620 8 : *count = 2;
9621 :
9622 8 : result = fill_monitor_1(info, &info[0].info1,
9623 : SPL_LOCAL_PORT);
9624 8 : if (!W_ERROR_IS_OK(result)) {
9625 0 : goto out;
9626 : }
9627 :
9628 8 : result = fill_monitor_1(info, &info[1].info1,
9629 : SPL_TCPIP_PORT);
9630 8 : if (!W_ERROR_IS_OK(result)) {
9631 0 : goto out;
9632 : }
9633 :
9634 8 : out:
9635 8 : if (!W_ERROR_IS_OK(result)) {
9636 0 : TALLOC_FREE(info);
9637 0 : *count = 0;
9638 0 : return result;
9639 : }
9640 :
9641 8 : *info_p = info;
9642 :
9643 8 : return WERR_OK;
9644 : }
9645 :
9646 : /****************************************************************************
9647 : enumprintmonitors level 2.
9648 : ****************************************************************************/
9649 :
9650 8 : static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9651 : union spoolss_MonitorInfo **info_p,
9652 : uint32_t *count)
9653 : {
9654 0 : union spoolss_MonitorInfo *info;
9655 8 : WERROR result = WERR_OK;
9656 0 : const char *architecture;
9657 :
9658 8 : info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9659 8 : W_ERROR_HAVE_NO_MEMORY(info);
9660 :
9661 8 : *count = 2;
9662 :
9663 8 : architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
9664 : "spoolss",
9665 : "architecture",
9666 : GLOBAL_SPOOLSS_ARCHITECTURE);
9667 :
9668 8 : result = fill_monitor_2(info, &info[0].info2,
9669 : SPL_LOCAL_PORT,
9670 : architecture,
9671 : "localmon.dll");
9672 8 : if (!W_ERROR_IS_OK(result)) {
9673 0 : goto out;
9674 : }
9675 :
9676 8 : result = fill_monitor_2(info, &info[1].info2,
9677 : SPL_TCPIP_PORT,
9678 : architecture,
9679 : "tcpmon.dll");
9680 8 : if (!W_ERROR_IS_OK(result)) {
9681 0 : goto out;
9682 : }
9683 :
9684 8 : out:
9685 8 : if (!W_ERROR_IS_OK(result)) {
9686 0 : TALLOC_FREE(info);
9687 0 : *count = 0;
9688 0 : return result;
9689 : }
9690 :
9691 8 : *info_p = info;
9692 :
9693 8 : return WERR_OK;
9694 : }
9695 :
9696 : /****************************************************************
9697 : _spoolss_EnumMonitors
9698 : ****************************************************************/
9699 :
9700 16 : WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9701 : struct spoolss_EnumMonitors *r)
9702 : {
9703 0 : WERROR result;
9704 :
9705 : /* that's an [in out] buffer */
9706 :
9707 16 : if (!r->in.buffer && (r->in.offered != 0)) {
9708 0 : return WERR_INVALID_PARAMETER;
9709 : }
9710 :
9711 16 : DEBUG(5,("_spoolss_EnumMonitors\n"));
9712 :
9713 : /*
9714 : * Enumerate the print monitors ...
9715 : *
9716 : * Just reply with "Local Port", to keep NT happy
9717 : * and I can use my nice printer checker.
9718 : */
9719 :
9720 16 : *r->out.count = 0;
9721 16 : *r->out.needed = 0;
9722 16 : *r->out.info = NULL;
9723 :
9724 16 : switch (r->in.level) {
9725 8 : case 1:
9726 8 : result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9727 : r->out.count);
9728 8 : break;
9729 8 : case 2:
9730 8 : result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9731 : r->out.count);
9732 8 : break;
9733 0 : default:
9734 0 : return WERR_INVALID_LEVEL;
9735 : }
9736 :
9737 16 : if (!W_ERROR_IS_OK(result)) {
9738 0 : return result;
9739 : }
9740 :
9741 16 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9742 : spoolss_EnumMonitors,
9743 : *r->out.info, r->in.level,
9744 : *r->out.count);
9745 16 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9746 16 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9747 :
9748 16 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9749 : }
9750 :
9751 : /****************************************************************************
9752 : ****************************************************************************/
9753 :
9754 128 : static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9755 : const print_queue_struct *queue,
9756 : int count, int snum,
9757 : struct spoolss_PrinterInfo2 *pinfo2,
9758 : uint32_t jobid,
9759 : int sysjob,
9760 : struct spoolss_JobInfo1 *r)
9761 : {
9762 128 : int i = 0;
9763 128 : bool found = false;
9764 :
9765 576 : for (i=0; i<count; i++) {
9766 576 : if (queue[i].sysjob == sysjob) {
9767 128 : found = true;
9768 128 : break;
9769 : }
9770 : }
9771 :
9772 128 : if (found == false) {
9773 : /* NT treats not found as bad param... yet another bad choice */
9774 0 : return WERR_INVALID_PARAMETER;
9775 : }
9776 :
9777 128 : return fill_job_info1(mem_ctx,
9778 : r,
9779 128 : &queue[i],
9780 : jobid,
9781 : i,
9782 : snum,
9783 : pinfo2);
9784 : }
9785 :
9786 : /****************************************************************************
9787 : ****************************************************************************/
9788 :
9789 0 : static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9790 : const print_queue_struct *queue,
9791 : int count, int snum,
9792 : struct spoolss_PrinterInfo2 *pinfo2,
9793 : uint32_t jobid,
9794 : int sysjob,
9795 : struct spoolss_JobInfo2 *r)
9796 : {
9797 0 : int i = 0;
9798 0 : bool found = false;
9799 0 : struct spoolss_DeviceMode *devmode;
9800 0 : WERROR result;
9801 :
9802 0 : for (i=0; i<count; i++) {
9803 0 : if (queue[i].sysjob == sysjob) {
9804 0 : found = true;
9805 0 : break;
9806 : }
9807 : }
9808 :
9809 0 : if (found == false) {
9810 : /* NT treats not found as bad param... yet another bad
9811 : choice */
9812 0 : return WERR_INVALID_PARAMETER;
9813 : }
9814 :
9815 : /*
9816 : * if the print job does not have a DEVMODE associated with it,
9817 : * just use the one for the printer. A NULL devicemode is not
9818 : * a failure condition
9819 : */
9820 :
9821 0 : devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9822 0 : if (!devmode) {
9823 0 : result = spoolss_create_default_devmode(mem_ctx,
9824 : pinfo2->printername,
9825 : &devmode);
9826 0 : if (!W_ERROR_IS_OK(result)) {
9827 0 : DEBUG(3, ("Can't proceed w/o a devmode!\n"));
9828 0 : return result;
9829 : }
9830 : }
9831 :
9832 0 : return fill_job_info2(mem_ctx,
9833 : r,
9834 0 : &queue[i],
9835 : jobid,
9836 : i,
9837 : snum,
9838 : pinfo2,
9839 : devmode);
9840 : }
9841 :
9842 : /****************************************************************
9843 : _spoolss_GetJob
9844 : ****************************************************************/
9845 :
9846 2048 : WERROR _spoolss_GetJob(struct pipes_struct *p,
9847 : struct spoolss_GetJob *r)
9848 : {
9849 2048 : WERROR result = WERR_OK;
9850 2048 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9851 0 : const char *svc_name;
9852 0 : int sysjob;
9853 0 : int snum;
9854 0 : int count;
9855 0 : struct tdb_print_db *pdb;
9856 2048 : print_queue_struct *queue = NULL;
9857 0 : print_status_struct prt_status;
9858 :
9859 : /* that's an [in out] buffer */
9860 :
9861 2048 : if (!r->in.buffer && (r->in.offered != 0)) {
9862 0 : result = WERR_INVALID_PARAMETER;
9863 0 : goto err_jinfo_free;
9864 : }
9865 :
9866 2048 : DEBUG(5,("_spoolss_GetJob\n"));
9867 :
9868 2048 : *r->out.needed = 0;
9869 :
9870 2048 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9871 0 : result = WERR_INVALID_HANDLE;
9872 0 : goto err_jinfo_free;
9873 : }
9874 :
9875 2048 : svc_name = lp_const_servicename(snum);
9876 2048 : if (svc_name == NULL) {
9877 0 : result = WERR_INVALID_PARAMETER;
9878 0 : goto err_jinfo_free;
9879 : }
9880 :
9881 2048 : result = winreg_get_printer_internal(p->mem_ctx,
9882 : get_session_info_system(),
9883 : p->msg_ctx,
9884 : svc_name,
9885 : &pinfo2);
9886 2048 : if (!W_ERROR_IS_OK(result)) {
9887 0 : goto err_jinfo_free;
9888 : }
9889 :
9890 2048 : pdb = get_print_db_byname(svc_name);
9891 2048 : if (pdb == NULL) {
9892 0 : DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9893 0 : result = WERR_INVALID_PARAMETER;
9894 0 : goto err_pinfo_free;
9895 : }
9896 :
9897 2048 : sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9898 2048 : release_print_db(pdb);
9899 2048 : if (sysjob == -1) {
9900 1920 : DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9901 1920 : result = WERR_INVALID_PARAMETER;
9902 1920 : goto err_pinfo_free;
9903 : }
9904 :
9905 128 : count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9906 :
9907 128 : DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9908 : count, prt_status.status, prt_status.message));
9909 :
9910 128 : switch (r->in.level) {
9911 128 : case 1:
9912 128 : result = getjob_level_1(p->mem_ctx,
9913 : queue, count, snum, pinfo2,
9914 : r->in.job_id, sysjob,
9915 128 : &r->out.info->info1);
9916 128 : break;
9917 0 : case 2:
9918 0 : result = getjob_level_2(p->mem_ctx,
9919 : queue, count, snum, pinfo2,
9920 : r->in.job_id, sysjob,
9921 0 : &r->out.info->info2);
9922 0 : break;
9923 0 : default:
9924 0 : result = WERR_INVALID_LEVEL;
9925 0 : break;
9926 : }
9927 :
9928 128 : SAFE_FREE(queue);
9929 128 : TALLOC_FREE(pinfo2);
9930 :
9931 128 : if (!W_ERROR_IS_OK(result)) {
9932 0 : goto err_jinfo_free;
9933 : }
9934 :
9935 128 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9936 : r->in.level);
9937 128 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9938 :
9939 128 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9940 :
9941 1920 : err_pinfo_free:
9942 1920 : TALLOC_FREE(pinfo2);
9943 0 : err_jinfo_free:
9944 1920 : TALLOC_FREE(r->out.info);
9945 1920 : return result;
9946 : }
9947 :
9948 : /****************************************************************
9949 : _spoolss_GetPrinterDataEx
9950 : ****************************************************************/
9951 :
9952 3180 : WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9953 : struct spoolss_GetPrinterDataEx *r)
9954 : {
9955 :
9956 3180 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9957 0 : const char *printer;
9958 3180 : int snum = 0;
9959 3180 : WERROR result = WERR_OK;
9960 0 : DATA_BLOB blob;
9961 3180 : enum winreg_Type val_type = REG_NONE;
9962 3180 : uint8_t *val_data = NULL;
9963 3180 : uint32_t val_size = 0;
9964 0 : struct dcerpc_binding_handle *b;
9965 0 : TALLOC_CTX *tmp_ctx;
9966 :
9967 3180 : DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9968 :
9969 3180 : DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9970 : r->in.key_name, r->in.value_name));
9971 :
9972 : /* in case of problem, return some default values */
9973 :
9974 3180 : *r->out.needed = 0;
9975 3180 : *r->out.type = REG_NONE;
9976 :
9977 3180 : tmp_ctx = talloc_new(p->mem_ctx);
9978 3180 : if (!tmp_ctx) {
9979 0 : return WERR_NOT_ENOUGH_MEMORY;
9980 : }
9981 :
9982 3180 : if (!Printer) {
9983 0 : DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9984 : OUR_HANDLE(r->in.handle)));
9985 0 : result = WERR_INVALID_HANDLE;
9986 0 : goto done;
9987 : }
9988 :
9989 : /* Is the handle to a printer or to the server? */
9990 :
9991 3180 : if (Printer->printer_type == SPLHND_SERVER) {
9992 :
9993 0 : union spoolss_PrinterData data;
9994 :
9995 404 : result = getprinterdata_printer_server(tmp_ctx,
9996 : r->in.value_name,
9997 : r->out.type,
9998 : &data);
9999 404 : if (!W_ERROR_IS_OK(result)) {
10000 4 : goto done;
10001 : }
10002 :
10003 400 : result = push_spoolss_PrinterData(tmp_ctx, &blob,
10004 400 : *r->out.type, &data);
10005 400 : if (!W_ERROR_IS_OK(result)) {
10006 0 : goto done;
10007 : }
10008 :
10009 400 : *r->out.needed = blob.length;
10010 :
10011 400 : if (r->in.offered >= *r->out.needed) {
10012 204 : memcpy(r->out.data, blob.data, blob.length);
10013 : }
10014 :
10015 400 : result = WERR_OK;
10016 400 : goto done;
10017 : }
10018 :
10019 : /* check to see if the keyname is valid */
10020 2776 : if (!strlen(r->in.key_name)) {
10021 0 : result = WERR_INVALID_PARAMETER;
10022 0 : goto done;
10023 : }
10024 :
10025 2776 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10026 0 : result = WERR_INVALID_HANDLE;
10027 0 : goto done;
10028 : }
10029 2776 : printer = lp_const_servicename(snum);
10030 :
10031 2776 : result = winreg_printer_binding_handle(tmp_ctx,
10032 : get_session_info_system(),
10033 : p->msg_ctx,
10034 : &b);
10035 2776 : if (!W_ERROR_IS_OK(result)) {
10036 0 : goto done;
10037 : }
10038 :
10039 : /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
10040 3076 : if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
10041 300 : strequal(r->in.value_name, "ChangeId")) {
10042 128 : *r->out.type = REG_DWORD;
10043 128 : *r->out.needed = 4;
10044 128 : if (r->in.offered >= *r->out.needed) {
10045 64 : uint32_t changeid = 0;
10046 :
10047 64 : result = winreg_printer_get_changeid(tmp_ctx, b,
10048 : printer,
10049 : &changeid);
10050 64 : if (!W_ERROR_IS_OK(result)) {
10051 0 : goto done;
10052 : }
10053 :
10054 64 : SIVAL(r->out.data, 0, changeid);
10055 64 : result = WERR_OK;
10056 : }
10057 128 : goto done;
10058 : }
10059 :
10060 2648 : result = winreg_get_printer_dataex(tmp_ctx, b,
10061 : printer,
10062 : r->in.key_name,
10063 : r->in.value_name,
10064 : &val_type,
10065 : &val_data,
10066 : &val_size);
10067 2648 : if (!W_ERROR_IS_OK(result)) {
10068 4 : goto done;
10069 : }
10070 :
10071 2644 : *r->out.needed = val_size;
10072 2644 : *r->out.type = val_type;
10073 :
10074 2644 : if (r->in.offered >= *r->out.needed) {
10075 1340 : memcpy(r->out.data, val_data, val_size);
10076 : }
10077 :
10078 1304 : done:
10079 : /* NOTE: do not replace type when returning WERR_MORE_DATA */
10080 :
10081 3180 : if (W_ERROR_IS_OK(result)) {
10082 3172 : result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10083 : }
10084 :
10085 3180 : talloc_free(tmp_ctx);
10086 3180 : return result;
10087 : }
10088 :
10089 : /****************************************************************
10090 : _spoolss_SetPrinterDataEx
10091 : ****************************************************************/
10092 :
10093 1368 : WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
10094 : struct spoolss_SetPrinterDataEx *r)
10095 : {
10096 0 : const struct loadparm_substitution *lp_sub =
10097 1368 : loadparm_s3_global_substitution();
10098 1368 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
10099 1368 : int snum = 0;
10100 1368 : WERROR result = WERR_OK;
10101 1368 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10102 0 : char *oid_string;
10103 0 : struct dcerpc_binding_handle *b;
10104 0 : TALLOC_CTX *tmp_ctx;
10105 :
10106 1368 : DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
10107 :
10108 : /* From MSDN documentation of SetPrinterDataEx: pass request to
10109 : SetPrinterData if key is "PrinterDriverData" */
10110 :
10111 1368 : if (!Printer) {
10112 0 : DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
10113 : OUR_HANDLE(r->in.handle)));
10114 0 : return WERR_INVALID_HANDLE;
10115 : }
10116 :
10117 1368 : if (Printer->printer_type == SPLHND_SERVER) {
10118 0 : DEBUG(10,("_spoolss_SetPrinterDataEx: "
10119 : "Not implemented for server handles yet\n"));
10120 0 : return WERR_INVALID_PARAMETER;
10121 : }
10122 :
10123 1368 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10124 0 : return WERR_INVALID_HANDLE;
10125 : }
10126 :
10127 : /*
10128 : * Access check : NT returns "access denied" if you make a
10129 : * SetPrinterData call without the necessary privilege.
10130 : * we were originally returning OK if nothing changed
10131 : * which made Win2k issue **a lot** of SetPrinterData
10132 : * when connecting to a printer --jerry
10133 : */
10134 :
10135 1368 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10136 0 : DEBUG(3, ("_spoolss_SetPrinterDataEx: "
10137 : "change denied by handle access permissions\n"));
10138 0 : return WERR_ACCESS_DENIED;
10139 : }
10140 :
10141 1368 : tmp_ctx = talloc_new(p->mem_ctx);
10142 1368 : if (!tmp_ctx) {
10143 0 : return WERR_NOT_ENOUGH_MEMORY;
10144 : }
10145 :
10146 1368 : result = winreg_printer_binding_handle(tmp_ctx,
10147 : get_session_info_system(),
10148 : p->msg_ctx,
10149 : &b);
10150 1368 : if (!W_ERROR_IS_OK(result)) {
10151 0 : goto done;
10152 : }
10153 :
10154 1368 : result = winreg_get_printer(tmp_ctx, b,
10155 1368 : lp_servicename(talloc_tos(), lp_sub, snum),
10156 : &pinfo2);
10157 1368 : if (!W_ERROR_IS_OK(result)) {
10158 0 : goto done;
10159 : }
10160 :
10161 : /* check for OID in valuename */
10162 :
10163 1368 : oid_string = strchr(r->in.value_name, ',');
10164 1368 : if (oid_string) {
10165 0 : *oid_string = '\0';
10166 0 : oid_string++;
10167 : }
10168 :
10169 : /* save the registry data */
10170 :
10171 1368 : result = winreg_set_printer_dataex(tmp_ctx, b,
10172 1368 : pinfo2->sharename,
10173 : r->in.key_name,
10174 : r->in.value_name,
10175 : r->in.type,
10176 : r->in.data,
10177 : r->in.offered);
10178 :
10179 1368 : if (W_ERROR_IS_OK(result)) {
10180 : /* save the OID if one was specified */
10181 1368 : if (oid_string) {
10182 0 : char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
10183 : r->in.key_name, SPOOL_OID_KEY);
10184 0 : if (!str) {
10185 0 : result = WERR_NOT_ENOUGH_MEMORY;
10186 0 : goto done;
10187 : }
10188 :
10189 : /*
10190 : * I'm not checking the status here on purpose. Don't know
10191 : * if this is right, but I'm returning the status from the
10192 : * previous set_printer_dataex() call. I have no idea if
10193 : * this is right. --jerry
10194 : */
10195 0 : winreg_set_printer_dataex(tmp_ctx, b,
10196 0 : pinfo2->sharename,
10197 : str,
10198 : r->in.value_name,
10199 : REG_SZ,
10200 : (uint8_t *) oid_string,
10201 0 : strlen(oid_string) + 1);
10202 : }
10203 :
10204 1368 : result = winreg_printer_update_changeid(tmp_ctx, b,
10205 : lp_const_servicename(snum));
10206 :
10207 : }
10208 :
10209 0 : done:
10210 1368 : talloc_free(tmp_ctx);
10211 1368 : return result;
10212 : }
10213 :
10214 : /****************************************************************
10215 : _spoolss_DeletePrinterDataEx
10216 : ****************************************************************/
10217 :
10218 1368 : WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10219 : struct spoolss_DeletePrinterDataEx *r)
10220 : {
10221 0 : const char *printer;
10222 1368 : int snum=0;
10223 1368 : WERROR status = WERR_OK;
10224 1368 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10225 :
10226 1368 : DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10227 :
10228 1368 : if (!Printer) {
10229 0 : DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10230 : "Invalid handle (%s:%u:%u).\n",
10231 : OUR_HANDLE(r->in.handle)));
10232 0 : return WERR_INVALID_HANDLE;
10233 : }
10234 :
10235 1368 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10236 0 : DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10237 : "printer properties change denied by handle\n"));
10238 0 : return WERR_ACCESS_DENIED;
10239 : }
10240 :
10241 1368 : if (!r->in.value_name || !r->in.key_name) {
10242 0 : return WERR_NOT_ENOUGH_MEMORY;
10243 : }
10244 :
10245 1368 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10246 0 : return WERR_INVALID_HANDLE;
10247 : }
10248 1368 : printer = lp_const_servicename(snum);
10249 :
10250 1368 : status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10251 : get_session_info_system(),
10252 : p->msg_ctx,
10253 : printer,
10254 : r->in.key_name,
10255 : r->in.value_name);
10256 1368 : if (W_ERROR_IS_OK(status)) {
10257 1368 : status = winreg_printer_update_changeid_internal(p->mem_ctx,
10258 : get_session_info_system(),
10259 : p->msg_ctx,
10260 : printer);
10261 : }
10262 :
10263 1368 : return status;
10264 : }
10265 :
10266 : /****************************************************************
10267 : _spoolss_EnumPrinterKey
10268 : ****************************************************************/
10269 :
10270 3384 : WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10271 : struct spoolss_EnumPrinterKey *r)
10272 : {
10273 0 : uint32_t num_keys;
10274 3384 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10275 3384 : int snum = 0;
10276 3384 : WERROR result = WERR_FILE_NOT_FOUND;
10277 3384 : const char **array = NULL;
10278 0 : DATA_BLOB blob;
10279 :
10280 3384 : DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10281 :
10282 3384 : if (!Printer) {
10283 0 : DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10284 : OUR_HANDLE(r->in.handle)));
10285 0 : return WERR_INVALID_HANDLE;
10286 : }
10287 :
10288 3384 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10289 0 : return WERR_INVALID_HANDLE;
10290 : }
10291 :
10292 3384 : result = winreg_enum_printer_key_internal(p->mem_ctx,
10293 : get_session_info_system(),
10294 : p->msg_ctx,
10295 : lp_const_servicename(snum),
10296 : r->in.key_name,
10297 : &num_keys,
10298 : &array);
10299 3384 : if (!W_ERROR_IS_OK(result)) {
10300 0 : goto done;
10301 : }
10302 :
10303 3384 : if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10304 0 : result = WERR_NOT_ENOUGH_MEMORY;
10305 0 : goto done;
10306 : }
10307 :
10308 3384 : *r->out._ndr_size = r->in.offered / 2;
10309 3384 : *r->out.needed = blob.length;
10310 :
10311 3384 : if (r->in.offered < *r->out.needed) {
10312 1304 : result = WERR_MORE_DATA;
10313 : } else {
10314 2080 : result = WERR_OK;
10315 2080 : r->out.key_buffer->string_array = array;
10316 : }
10317 :
10318 3384 : done:
10319 3384 : if (!W_ERROR_IS_OK(result)) {
10320 1304 : TALLOC_FREE(array);
10321 1304 : if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10322 0 : *r->out.needed = 0;
10323 : }
10324 : }
10325 :
10326 3384 : return result;
10327 : }
10328 :
10329 : /****************************************************************
10330 : _spoolss_DeletePrinterKey
10331 : ****************************************************************/
10332 :
10333 216 : WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10334 : struct spoolss_DeletePrinterKey *r)
10335 : {
10336 216 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10337 216 : int snum=0;
10338 0 : WERROR status;
10339 0 : const char *printer;
10340 0 : struct dcerpc_binding_handle *b;
10341 0 : TALLOC_CTX *tmp_ctx;
10342 :
10343 216 : DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10344 :
10345 216 : if (!Printer) {
10346 0 : DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10347 : OUR_HANDLE(r->in.handle)));
10348 0 : return WERR_INVALID_HANDLE;
10349 : }
10350 :
10351 : /* if keyname == NULL, return error */
10352 216 : if ( !r->in.key_name )
10353 0 : return WERR_INVALID_PARAMETER;
10354 :
10355 216 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10356 0 : return WERR_INVALID_HANDLE;
10357 : }
10358 :
10359 216 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10360 0 : DEBUG(3, ("_spoolss_DeletePrinterKey: "
10361 : "printer properties change denied by handle\n"));
10362 0 : return WERR_ACCESS_DENIED;
10363 : }
10364 :
10365 216 : printer = lp_const_servicename(snum);
10366 :
10367 216 : tmp_ctx = talloc_new(p->mem_ctx);
10368 216 : if (!tmp_ctx) {
10369 0 : return WERR_NOT_ENOUGH_MEMORY;
10370 : }
10371 :
10372 216 : status = winreg_printer_binding_handle(tmp_ctx,
10373 : get_session_info_system(),
10374 : p->msg_ctx,
10375 : &b);
10376 216 : if (!W_ERROR_IS_OK(status)) {
10377 0 : goto done;
10378 : }
10379 :
10380 : /* delete the key and all subkeys */
10381 216 : status = winreg_delete_printer_key(tmp_ctx, b,
10382 : printer,
10383 : r->in.key_name);
10384 216 : if (W_ERROR_IS_OK(status)) {
10385 216 : status = winreg_printer_update_changeid(tmp_ctx, b,
10386 : printer);
10387 : }
10388 :
10389 0 : done:
10390 216 : talloc_free(tmp_ctx);
10391 216 : return status;
10392 : }
10393 :
10394 : /****************************************************************
10395 : _spoolss_EnumPrinterDataEx
10396 : ****************************************************************/
10397 :
10398 2860 : WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10399 : struct spoolss_EnumPrinterDataEx *r)
10400 : {
10401 2860 : uint32_t count = 0;
10402 2860 : struct spoolss_PrinterEnumValues *info = NULL;
10403 2860 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10404 0 : int snum;
10405 0 : WERROR result;
10406 :
10407 2860 : DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10408 :
10409 2860 : *r->out.count = 0;
10410 2860 : *r->out.needed = 0;
10411 2860 : *r->out.info = NULL;
10412 :
10413 2860 : if (!Printer) {
10414 0 : DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10415 : OUR_HANDLE(r->in.handle)));
10416 0 : return WERR_INVALID_HANDLE;
10417 : }
10418 :
10419 : /*
10420 : * first check for a keyname of NULL or "". Win2k seems to send
10421 : * this a lot and we should send back WERR_INVALID_PARAMETER
10422 : * no need to spend time looking up the printer in this case.
10423 : * --jerry
10424 : */
10425 :
10426 2860 : if (!strlen(r->in.key_name)) {
10427 4 : result = WERR_INVALID_PARAMETER;
10428 4 : goto done;
10429 : }
10430 :
10431 2856 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10432 0 : return WERR_INVALID_HANDLE;
10433 : }
10434 :
10435 : /* now look for a match on the key name */
10436 2856 : result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10437 : get_session_info_system(),
10438 : p->msg_ctx,
10439 : lp_const_servicename(snum),
10440 : r->in.key_name,
10441 : &count,
10442 : &info);
10443 2856 : if (!W_ERROR_IS_OK(result)) {
10444 0 : goto done;
10445 : }
10446 :
10447 2856 : *r->out.count = count;
10448 2856 : *r->out.info = info;
10449 :
10450 2860 : done:
10451 2860 : if (!W_ERROR_IS_OK(result)) {
10452 4 : return result;
10453 : }
10454 :
10455 2856 : *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10456 : spoolss_EnumPrinterDataEx,
10457 : *r->out.info,
10458 : *r->out.count);
10459 2856 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10460 2856 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10461 :
10462 2856 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10463 : }
10464 :
10465 : /****************************************************************************
10466 : ****************************************************************************/
10467 :
10468 40 : static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10469 : const char *servername,
10470 : const char *environment,
10471 : struct spoolss_PrintProcessorDirectoryInfo1 *r)
10472 : {
10473 0 : WERROR werr;
10474 40 : char *path = NULL;
10475 :
10476 40 : werr = compose_spoolss_server_path(mem_ctx,
10477 : servername,
10478 : environment,
10479 : SPOOLSS_PRTPROCS_PATH,
10480 : &path);
10481 40 : if (!W_ERROR_IS_OK(werr)) {
10482 0 : return werr;
10483 : }
10484 :
10485 40 : DEBUG(4,("print processor directory: [%s]\n", path));
10486 :
10487 40 : r->directory_name = path;
10488 :
10489 40 : return WERR_OK;
10490 : }
10491 :
10492 : /****************************************************************
10493 : _spoolss_GetPrintProcessorDirectory
10494 : ****************************************************************/
10495 :
10496 40 : WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10497 : struct spoolss_GetPrintProcessorDirectory *r)
10498 : {
10499 0 : WERROR result;
10500 40 : char *prnproc_share = NULL;
10501 40 : bool prnproc_share_exists = false;
10502 0 : int snum;
10503 :
10504 : /* that's an [in out] buffer */
10505 :
10506 40 : if (!r->in.buffer && (r->in.offered != 0)) {
10507 0 : result = WERR_INVALID_PARAMETER;
10508 0 : goto err_info_free;
10509 : }
10510 :
10511 40 : DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10512 : r->in.level));
10513 :
10514 40 : *r->out.needed = 0;
10515 :
10516 : /* r->in.level is ignored */
10517 :
10518 : /* We always should reply with a local print processor directory so that
10519 : * users are not forced to have a [prnproc$] share on the Samba spoolss
10520 : * server, if users decide to do so, lets announce it though - Guenther */
10521 :
10522 40 : snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10523 40 : if (!prnproc_share) {
10524 0 : result = WERR_NOT_ENOUGH_MEMORY;
10525 0 : goto err_info_free;
10526 : }
10527 40 : if (snum != -1) {
10528 0 : prnproc_share_exists = true;
10529 : }
10530 :
10531 40 : result = getprintprocessordirectory_level_1(p->mem_ctx,
10532 : prnproc_share_exists ? r->in.server : NULL,
10533 : r->in.environment,
10534 40 : &r->out.info->info1);
10535 40 : if (!W_ERROR_IS_OK(result)) {
10536 0 : goto err_info_free;
10537 : }
10538 :
10539 40 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10540 : r->out.info, r->in.level);
10541 40 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10542 :
10543 40 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10544 :
10545 0 : err_info_free:
10546 0 : TALLOC_FREE(r->out.info);
10547 0 : return result;
10548 : }
10549 :
10550 : /*******************************************************************
10551 : ********************************************************************/
10552 :
10553 0 : static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10554 : const char *dllname)
10555 : {
10556 0 : enum ndr_err_code ndr_err;
10557 0 : struct spoolss_MonitorUi ui;
10558 :
10559 0 : ui.dll_name = dllname;
10560 :
10561 0 : ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10562 : (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10563 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10564 0 : NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10565 : }
10566 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10567 : }
10568 :
10569 : /*******************************************************************
10570 : Streams the monitor UI DLL name in UNICODE
10571 : *******************************************************************/
10572 :
10573 0 : static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10574 : struct security_token *token, DATA_BLOB *in,
10575 : DATA_BLOB *out, uint32_t *needed)
10576 : {
10577 0 : const char *dllname = "tcpmonui.dll";
10578 :
10579 0 : *needed = (strlen(dllname)+1) * 2;
10580 :
10581 0 : if (out->length < *needed) {
10582 0 : return WERR_INSUFFICIENT_BUFFER;
10583 : }
10584 :
10585 0 : if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10586 0 : return WERR_NOT_ENOUGH_MEMORY;
10587 : }
10588 :
10589 0 : return WERR_OK;
10590 : }
10591 :
10592 : /*******************************************************************
10593 : ********************************************************************/
10594 :
10595 0 : static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10596 : struct spoolss_PortData1 *port1,
10597 : const DATA_BLOB *buf)
10598 : {
10599 0 : enum ndr_err_code ndr_err;
10600 0 : ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10601 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10602 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10603 0 : NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10604 : }
10605 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10606 : }
10607 :
10608 : /*******************************************************************
10609 : ********************************************************************/
10610 :
10611 0 : static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10612 : struct spoolss_PortData2 *port2,
10613 : const DATA_BLOB *buf)
10614 : {
10615 0 : enum ndr_err_code ndr_err;
10616 0 : ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10617 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10618 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10619 0 : NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10620 : }
10621 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10622 : }
10623 :
10624 : /*******************************************************************
10625 : Create a new TCP/IP port
10626 : *******************************************************************/
10627 :
10628 0 : static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10629 : struct security_token *token, DATA_BLOB *in,
10630 : DATA_BLOB *out, uint32_t *needed)
10631 : {
10632 0 : struct spoolss_PortData1 port1;
10633 0 : struct spoolss_PortData2 port2;
10634 0 : char *device_uri = NULL;
10635 0 : uint32_t version;
10636 :
10637 0 : const char *portname;
10638 0 : const char *hostaddress;
10639 0 : const char *queue;
10640 0 : uint32_t port_number;
10641 0 : uint32_t protocol;
10642 :
10643 : /* peek for spoolss_PortData version */
10644 :
10645 0 : if (!in || (in->length < (128 + 4))) {
10646 0 : return WERR_GEN_FAILURE;
10647 : }
10648 :
10649 0 : version = IVAL(in->data, 128);
10650 :
10651 0 : switch (version) {
10652 0 : case 1:
10653 0 : ZERO_STRUCT(port1);
10654 :
10655 0 : if (!pull_port_data_1(mem_ctx, &port1, in)) {
10656 0 : return WERR_NOT_ENOUGH_MEMORY;
10657 : }
10658 :
10659 0 : portname = port1.portname;
10660 0 : hostaddress = port1.hostaddress;
10661 0 : queue = port1.queue;
10662 0 : protocol = port1.protocol;
10663 0 : port_number = port1.port_number;
10664 :
10665 0 : break;
10666 0 : case 2:
10667 0 : ZERO_STRUCT(port2);
10668 :
10669 0 : if (!pull_port_data_2(mem_ctx, &port2, in)) {
10670 0 : return WERR_NOT_ENOUGH_MEMORY;
10671 : }
10672 :
10673 0 : portname = port2.portname;
10674 0 : hostaddress = port2.hostaddress;
10675 0 : queue = port2.queue;
10676 0 : protocol = port2.protocol;
10677 0 : port_number = port2.port_number;
10678 :
10679 0 : break;
10680 0 : default:
10681 0 : DEBUG(1,("xcvtcp_addport: "
10682 : "unknown version of port_data: %d\n", version));
10683 0 : return WERR_UNKNOWN_PORT;
10684 : }
10685 :
10686 : /* create the device URI and call the add_port_hook() */
10687 :
10688 0 : switch (protocol) {
10689 0 : case PROTOCOL_RAWTCP_TYPE:
10690 0 : device_uri = talloc_asprintf(mem_ctx,
10691 : "socket://%s:%d/", hostaddress,
10692 : port_number);
10693 0 : break;
10694 :
10695 0 : case PROTOCOL_LPR_TYPE:
10696 0 : device_uri = talloc_asprintf(mem_ctx,
10697 : "lpr://%s/%s", hostaddress, queue );
10698 0 : break;
10699 :
10700 0 : default:
10701 0 : return WERR_UNKNOWN_PORT;
10702 : }
10703 :
10704 0 : if (!device_uri) {
10705 0 : return WERR_NOT_ENOUGH_MEMORY;
10706 : }
10707 :
10708 0 : return add_port_hook(mem_ctx, token, portname, device_uri);
10709 : }
10710 :
10711 : /*******************************************************************
10712 : *******************************************************************/
10713 :
10714 : struct xcv_api_table xcvtcp_cmds[] = {
10715 : { "MonitorUI", xcvtcp_monitorui },
10716 : { "AddPort", xcvtcp_addport},
10717 : { NULL, NULL }
10718 : };
10719 :
10720 0 : static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10721 : struct security_token *token, const char *command,
10722 : DATA_BLOB *inbuf,
10723 : DATA_BLOB *outbuf,
10724 : uint32_t *needed )
10725 : {
10726 0 : int i;
10727 :
10728 0 : DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10729 :
10730 0 : for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10731 0 : if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10732 0 : return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10733 : }
10734 :
10735 0 : return WERR_INVALID_FUNCTION;
10736 : }
10737 :
10738 : /*******************************************************************
10739 : *******************************************************************/
10740 : #if 0 /* don't support management using the "Local Port" monitor */
10741 :
10742 : static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10743 : struct security_token *token, DATA_BLOB *in,
10744 : DATA_BLOB *out, uint32_t *needed)
10745 : {
10746 : const char *dllname = "localui.dll";
10747 :
10748 : *needed = (strlen(dllname)+1) * 2;
10749 :
10750 : if (out->length < *needed) {
10751 : return WERR_INSUFFICIENT_BUFFER;
10752 : }
10753 :
10754 : if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10755 : return WERR_NOT_ENOUGH_MEMORY;
10756 : }
10757 :
10758 : return WERR_OK;
10759 : }
10760 :
10761 : /*******************************************************************
10762 : *******************************************************************/
10763 :
10764 : struct xcv_api_table xcvlocal_cmds[] = {
10765 : { "MonitorUI", xcvlocal_monitorui },
10766 : { NULL, NULL }
10767 : };
10768 : #else
10769 : struct xcv_api_table xcvlocal_cmds[] = {
10770 : { NULL, NULL }
10771 : };
10772 : #endif
10773 :
10774 :
10775 :
10776 : /*******************************************************************
10777 : *******************************************************************/
10778 :
10779 0 : static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10780 : struct security_token *token, const char *command,
10781 : DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10782 : uint32_t *needed)
10783 : {
10784 0 : int i;
10785 :
10786 0 : DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10787 :
10788 0 : for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10789 0 : if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10790 0 : return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10791 : }
10792 0 : return WERR_INVALID_FUNCTION;
10793 : }
10794 :
10795 : /****************************************************************
10796 : _spoolss_XcvData
10797 : ****************************************************************/
10798 :
10799 0 : WERROR _spoolss_XcvData(struct pipes_struct *p,
10800 : struct spoolss_XcvData *r)
10801 : {
10802 0 : struct dcesrv_call_state *dce_call = p->dce_call;
10803 0 : struct auth_session_info *session_info =
10804 0 : dcesrv_call_session_info(dce_call);
10805 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10806 0 : DATA_BLOB out_data = data_blob_null;
10807 0 : WERROR werror;
10808 :
10809 0 : if (!Printer) {
10810 0 : DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10811 : OUR_HANDLE(r->in.handle)));
10812 0 : return WERR_INVALID_HANDLE;
10813 : }
10814 :
10815 : /* Has to be a handle to the TCP/IP port monitor */
10816 :
10817 0 : if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10818 0 : DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10819 0 : return WERR_INVALID_HANDLE;
10820 : }
10821 :
10822 : /* requires administrative access to the server */
10823 :
10824 0 : if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10825 0 : DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10826 0 : return WERR_ACCESS_DENIED;
10827 : }
10828 :
10829 : /* Allocate the outgoing buffer */
10830 :
10831 0 : if (r->in.out_data_size) {
10832 0 : out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10833 0 : if (out_data.data == NULL) {
10834 0 : return WERR_NOT_ENOUGH_MEMORY;
10835 : }
10836 : }
10837 :
10838 0 : switch ( Printer->printer_type ) {
10839 0 : case SPLHND_PORTMON_TCP:
10840 0 : werror = process_xcvtcp_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 : case SPLHND_PORTMON_LOCAL:
10847 0 : werror = process_xcvlocal_command(p->mem_ctx,
10848 : session_info->security_token,
10849 : r->in.function_name,
10850 : &r->in.in_data, &out_data,
10851 : r->out.needed);
10852 0 : break;
10853 0 : default:
10854 0 : werror = WERR_INVALID_PRINT_MONITOR;
10855 : }
10856 :
10857 0 : if (!W_ERROR_IS_OK(werror)) {
10858 0 : return werror;
10859 : }
10860 :
10861 0 : *r->out.status_code = 0;
10862 :
10863 0 : if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10864 0 : memcpy(r->out.out_data, out_data.data,
10865 0 : MIN(r->in.out_data_size, out_data.length));
10866 : }
10867 :
10868 0 : return WERR_OK;
10869 : }
10870 :
10871 : /****************************************************************
10872 : _spoolss_AddPrintProcessor
10873 : ****************************************************************/
10874 :
10875 4 : WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10876 : struct spoolss_AddPrintProcessor *r)
10877 : {
10878 : /* for now, just indicate success and ignore the add. We'll
10879 : automatically set the winprint processor for printer
10880 : entries later. Used to debug the LexMark Optra S 1855 PCL
10881 : driver --jerry */
10882 :
10883 4 : return WERR_OK;
10884 : }
10885 :
10886 : /****************************************************************
10887 : _spoolss_AddPort
10888 : ****************************************************************/
10889 :
10890 4 : WERROR _spoolss_AddPort(struct pipes_struct *p,
10891 : struct spoolss_AddPort *r)
10892 : {
10893 : /* do what w2k3 does */
10894 :
10895 4 : return WERR_NOT_SUPPORTED;
10896 : }
10897 :
10898 : /****************************************************************
10899 : _spoolss_GetPrinterDriver
10900 : ****************************************************************/
10901 :
10902 0 : WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10903 : struct spoolss_GetPrinterDriver *r)
10904 : {
10905 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10906 0 : return WERR_NOT_SUPPORTED;
10907 : }
10908 :
10909 : /****************************************************************
10910 : _spoolss_ReadPrinter
10911 : ****************************************************************/
10912 :
10913 0 : WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10914 : struct spoolss_ReadPrinter *r)
10915 : {
10916 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10917 0 : return WERR_NOT_SUPPORTED;
10918 : }
10919 :
10920 : /****************************************************************
10921 : _spoolss_WaitForPrinterChange
10922 : ****************************************************************/
10923 :
10924 0 : WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10925 : struct spoolss_WaitForPrinterChange *r)
10926 : {
10927 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10928 0 : return WERR_NOT_SUPPORTED;
10929 : }
10930 :
10931 : /****************************************************************
10932 : _spoolss_ConfigurePort
10933 : ****************************************************************/
10934 :
10935 0 : WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10936 : struct spoolss_ConfigurePort *r)
10937 : {
10938 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10939 0 : return WERR_NOT_SUPPORTED;
10940 : }
10941 :
10942 : /****************************************************************
10943 : _spoolss_DeletePort
10944 : ****************************************************************/
10945 :
10946 0 : WERROR _spoolss_DeletePort(struct pipes_struct *p,
10947 : struct spoolss_DeletePort *r)
10948 : {
10949 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10950 0 : return WERR_NOT_SUPPORTED;
10951 : }
10952 :
10953 : /****************************************************************
10954 : _spoolss_CreatePrinterIC
10955 : ****************************************************************/
10956 :
10957 0 : WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10958 : struct spoolss_CreatePrinterIC *r)
10959 : {
10960 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10961 0 : return WERR_NOT_SUPPORTED;
10962 : }
10963 :
10964 : /****************************************************************
10965 : _spoolss_PlayGDIScriptOnPrinterIC
10966 : ****************************************************************/
10967 :
10968 0 : WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10969 : struct spoolss_PlayGDIScriptOnPrinterIC *r)
10970 : {
10971 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10972 0 : return WERR_NOT_SUPPORTED;
10973 : }
10974 :
10975 : /****************************************************************
10976 : _spoolss_DeletePrinterIC
10977 : ****************************************************************/
10978 :
10979 0 : WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10980 : struct spoolss_DeletePrinterIC *r)
10981 : {
10982 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10983 0 : return WERR_NOT_SUPPORTED;
10984 : }
10985 :
10986 : /****************************************************************
10987 : _spoolss_AddPrinterConnection
10988 : ****************************************************************/
10989 :
10990 0 : WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10991 : struct spoolss_AddPrinterConnection *r)
10992 : {
10993 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10994 0 : return WERR_NOT_SUPPORTED;
10995 : }
10996 :
10997 : /****************************************************************
10998 : _spoolss_DeletePrinterConnection
10999 : ****************************************************************/
11000 :
11001 0 : WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
11002 : struct spoolss_DeletePrinterConnection *r)
11003 : {
11004 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11005 0 : return WERR_NOT_SUPPORTED;
11006 : }
11007 :
11008 : /****************************************************************
11009 : _spoolss_PrinterMessageBox
11010 : ****************************************************************/
11011 :
11012 0 : WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
11013 : struct spoolss_PrinterMessageBox *r)
11014 : {
11015 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11016 0 : return WERR_NOT_SUPPORTED;
11017 : }
11018 :
11019 : /****************************************************************
11020 : _spoolss_AddMonitor
11021 : ****************************************************************/
11022 :
11023 0 : WERROR _spoolss_AddMonitor(struct pipes_struct *p,
11024 : struct spoolss_AddMonitor *r)
11025 : {
11026 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11027 0 : return WERR_NOT_SUPPORTED;
11028 : }
11029 :
11030 : /****************************************************************
11031 : _spoolss_DeleteMonitor
11032 : ****************************************************************/
11033 :
11034 0 : WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
11035 : struct spoolss_DeleteMonitor *r)
11036 : {
11037 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11038 0 : return WERR_NOT_SUPPORTED;
11039 : }
11040 :
11041 : /****************************************************************
11042 : _spoolss_DeletePrintProcessor
11043 : ****************************************************************/
11044 :
11045 0 : WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
11046 : struct spoolss_DeletePrintProcessor *r)
11047 : {
11048 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11049 0 : return WERR_NOT_SUPPORTED;
11050 : }
11051 :
11052 : /****************************************************************
11053 : _spoolss_AddPrintProvidor
11054 : ****************************************************************/
11055 :
11056 0 : WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
11057 : struct spoolss_AddPrintProvidor *r)
11058 : {
11059 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11060 0 : return WERR_NOT_SUPPORTED;
11061 : }
11062 :
11063 : /****************************************************************
11064 : _spoolss_DeletePrintProvidor
11065 : ****************************************************************/
11066 :
11067 0 : WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
11068 : struct spoolss_DeletePrintProvidor *r)
11069 : {
11070 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11071 0 : return WERR_NOT_SUPPORTED;
11072 : }
11073 :
11074 : /****************************************************************
11075 : _spoolss_FindFirstPrinterChangeNotification
11076 : ****************************************************************/
11077 :
11078 0 : WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
11079 : struct spoolss_FindFirstPrinterChangeNotification *r)
11080 : {
11081 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11082 0 : return WERR_NOT_SUPPORTED;
11083 : }
11084 :
11085 : /****************************************************************
11086 : _spoolss_FindNextPrinterChangeNotification
11087 : ****************************************************************/
11088 :
11089 0 : WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
11090 : struct spoolss_FindNextPrinterChangeNotification *r)
11091 : {
11092 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11093 0 : return WERR_NOT_SUPPORTED;
11094 : }
11095 :
11096 : /****************************************************************
11097 : _spoolss_RouterFindFirstPrinterChangeNotificationOld
11098 : ****************************************************************/
11099 :
11100 0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
11101 : struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
11102 : {
11103 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11104 0 : return WERR_NOT_SUPPORTED;
11105 : }
11106 :
11107 : /****************************************************************
11108 : _spoolss_ReplyOpenPrinter
11109 : ****************************************************************/
11110 :
11111 0 : WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
11112 : struct spoolss_ReplyOpenPrinter *r)
11113 : {
11114 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11115 0 : return WERR_NOT_SUPPORTED;
11116 : }
11117 :
11118 : /****************************************************************
11119 : _spoolss_RouterReplyPrinter
11120 : ****************************************************************/
11121 :
11122 0 : WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
11123 : struct spoolss_RouterReplyPrinter *r)
11124 : {
11125 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11126 0 : return WERR_NOT_SUPPORTED;
11127 : }
11128 :
11129 : /****************************************************************
11130 : _spoolss_ReplyClosePrinter
11131 : ****************************************************************/
11132 :
11133 0 : WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
11134 : struct spoolss_ReplyClosePrinter *r)
11135 : {
11136 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11137 0 : return WERR_NOT_SUPPORTED;
11138 : }
11139 :
11140 : /****************************************************************
11141 : _spoolss_AddPortEx
11142 : ****************************************************************/
11143 :
11144 0 : WERROR _spoolss_AddPortEx(struct pipes_struct *p,
11145 : struct spoolss_AddPortEx *r)
11146 : {
11147 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11148 0 : return WERR_NOT_SUPPORTED;
11149 : }
11150 :
11151 : /****************************************************************
11152 : _spoolss_RouterFindFirstPrinterChangeNotification
11153 : ****************************************************************/
11154 :
11155 0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
11156 : struct spoolss_RouterFindFirstPrinterChangeNotification *r)
11157 : {
11158 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11159 0 : return WERR_NOT_SUPPORTED;
11160 : }
11161 :
11162 : /****************************************************************
11163 : _spoolss_SpoolerInit
11164 : ****************************************************************/
11165 :
11166 0 : WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
11167 : struct spoolss_SpoolerInit *r)
11168 : {
11169 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11170 0 : return WERR_NOT_SUPPORTED;
11171 : }
11172 :
11173 : /****************************************************************
11174 : _spoolss_ResetPrinterEx
11175 : ****************************************************************/
11176 :
11177 0 : WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
11178 : struct spoolss_ResetPrinterEx *r)
11179 : {
11180 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11181 0 : return WERR_NOT_SUPPORTED;
11182 : }
11183 :
11184 : /****************************************************************
11185 : _spoolss_RouterReplyPrinterEx
11186 : ****************************************************************/
11187 :
11188 0 : WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
11189 : struct spoolss_RouterReplyPrinterEx *r)
11190 : {
11191 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11192 0 : return WERR_NOT_SUPPORTED;
11193 : }
11194 :
11195 : /****************************************************************
11196 : _spoolss_44
11197 : ****************************************************************/
11198 :
11199 0 : WERROR _spoolss_44(struct pipes_struct *p,
11200 : struct spoolss_44 *r)
11201 : {
11202 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11203 0 : return WERR_NOT_SUPPORTED;
11204 : }
11205 :
11206 : /****************************************************************
11207 : _spoolss_SetPort
11208 : ****************************************************************/
11209 :
11210 0 : WERROR _spoolss_SetPort(struct pipes_struct *p,
11211 : struct spoolss_SetPort *r)
11212 : {
11213 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11214 0 : return WERR_NOT_SUPPORTED;
11215 : }
11216 :
11217 : /****************************************************************
11218 : _spoolss_4a
11219 : ****************************************************************/
11220 :
11221 0 : WERROR _spoolss_4a(struct pipes_struct *p,
11222 : struct spoolss_4a *r)
11223 : {
11224 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11225 0 : return WERR_NOT_SUPPORTED;
11226 : }
11227 :
11228 : /****************************************************************
11229 : _spoolss_4b
11230 : ****************************************************************/
11231 :
11232 0 : WERROR _spoolss_4b(struct pipes_struct *p,
11233 : struct spoolss_4b *r)
11234 : {
11235 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11236 0 : return WERR_NOT_SUPPORTED;
11237 : }
11238 :
11239 : /****************************************************************
11240 : _spoolss_4c
11241 : ****************************************************************/
11242 :
11243 0 : WERROR _spoolss_4c(struct pipes_struct *p,
11244 : struct spoolss_4c *r)
11245 : {
11246 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11247 0 : return WERR_NOT_SUPPORTED;
11248 : }
11249 :
11250 : /****************************************************************
11251 : _spoolss_53
11252 : ****************************************************************/
11253 :
11254 0 : WERROR _spoolss_53(struct pipes_struct *p,
11255 : struct spoolss_53 *r)
11256 : {
11257 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11258 0 : return WERR_NOT_SUPPORTED;
11259 : }
11260 :
11261 : /****************************************************************
11262 : _spoolss_AddPerMachineConnection
11263 : ****************************************************************/
11264 :
11265 4 : WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11266 : struct spoolss_AddPerMachineConnection *r)
11267 : {
11268 4 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11269 4 : return WERR_NOT_SUPPORTED;
11270 : }
11271 :
11272 : /****************************************************************
11273 : _spoolss_DeletePerMachineConnection
11274 : ****************************************************************/
11275 :
11276 0 : WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11277 : struct spoolss_DeletePerMachineConnection *r)
11278 : {
11279 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11280 0 : return WERR_NOT_SUPPORTED;
11281 : }
11282 :
11283 : /****************************************************************
11284 : _spoolss_EnumPerMachineConnections
11285 : ****************************************************************/
11286 :
11287 0 : WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11288 : struct spoolss_EnumPerMachineConnections *r)
11289 : {
11290 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11291 0 : return WERR_NOT_SUPPORTED;
11292 : }
11293 :
11294 : /****************************************************************
11295 : _spoolss_5a
11296 : ****************************************************************/
11297 :
11298 0 : WERROR _spoolss_5a(struct pipes_struct *p,
11299 : struct spoolss_5a *r)
11300 : {
11301 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11302 0 : return WERR_NOT_SUPPORTED;
11303 : }
11304 :
11305 : /****************************************************************
11306 : _spoolss_5b
11307 : ****************************************************************/
11308 :
11309 0 : WERROR _spoolss_5b(struct pipes_struct *p,
11310 : struct spoolss_5b *r)
11311 : {
11312 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11313 0 : return WERR_NOT_SUPPORTED;
11314 : }
11315 :
11316 : /****************************************************************
11317 : _spoolss_5c
11318 : ****************************************************************/
11319 :
11320 0 : WERROR _spoolss_5c(struct pipes_struct *p,
11321 : struct spoolss_5c *r)
11322 : {
11323 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11324 0 : return WERR_NOT_SUPPORTED;
11325 : }
11326 :
11327 : /****************************************************************
11328 : _spoolss_5d
11329 : ****************************************************************/
11330 :
11331 0 : WERROR _spoolss_5d(struct pipes_struct *p,
11332 : struct spoolss_5d *r)
11333 : {
11334 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11335 0 : return WERR_NOT_SUPPORTED;
11336 : }
11337 :
11338 : /****************************************************************
11339 : _spoolss_5e
11340 : ****************************************************************/
11341 :
11342 0 : WERROR _spoolss_5e(struct pipes_struct *p,
11343 : struct spoolss_5e *r)
11344 : {
11345 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11346 0 : return WERR_NOT_SUPPORTED;
11347 : }
11348 :
11349 : /****************************************************************
11350 : _spoolss_5f
11351 : ****************************************************************/
11352 :
11353 0 : WERROR _spoolss_5f(struct pipes_struct *p,
11354 : struct spoolss_5f *r)
11355 : {
11356 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11357 0 : return WERR_NOT_SUPPORTED;
11358 : }
11359 :
11360 : /****************************************************************
11361 : _spoolss_60
11362 : ****************************************************************/
11363 :
11364 0 : WERROR _spoolss_60(struct pipes_struct *p,
11365 : struct spoolss_60 *r)
11366 : {
11367 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11368 0 : return WERR_NOT_SUPPORTED;
11369 : }
11370 :
11371 : /****************************************************************
11372 : _spoolss_SendRecvBidiData
11373 : ****************************************************************/
11374 :
11375 0 : WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11376 : struct spoolss_SendRecvBidiData *r)
11377 : {
11378 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11379 0 : return WERR_NOT_SUPPORTED;
11380 : }
11381 :
11382 : /****************************************************************
11383 : _spoolss_62
11384 : ****************************************************************/
11385 :
11386 0 : WERROR _spoolss_62(struct pipes_struct *p,
11387 : struct spoolss_62 *r)
11388 : {
11389 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11390 0 : return WERR_NOT_SUPPORTED;
11391 : }
11392 :
11393 : /****************************************************************
11394 : _spoolss_63
11395 : ****************************************************************/
11396 :
11397 0 : WERROR _spoolss_63(struct pipes_struct *p,
11398 : struct spoolss_63 *r)
11399 : {
11400 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11401 0 : return WERR_NOT_SUPPORTED;
11402 : }
11403 :
11404 : /****************************************************************
11405 : _spoolss_64
11406 : ****************************************************************/
11407 :
11408 0 : WERROR _spoolss_64(struct pipes_struct *p,
11409 : struct spoolss_64 *r)
11410 : {
11411 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11412 0 : return WERR_NOT_SUPPORTED;
11413 : }
11414 :
11415 : /****************************************************************
11416 : _spoolss_65
11417 : ****************************************************************/
11418 :
11419 0 : WERROR _spoolss_65(struct pipes_struct *p,
11420 : struct spoolss_65 *r)
11421 : {
11422 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11423 0 : return WERR_NOT_SUPPORTED;
11424 : }
11425 :
11426 : /****************************************************************
11427 : _spoolss_GetCorePrinterDrivers
11428 : ****************************************************************/
11429 :
11430 8 : HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11431 : struct spoolss_GetCorePrinterDrivers *r)
11432 : {
11433 8 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11434 8 : return HRES_ERROR_NOT_SUPPORTED;
11435 : }
11436 :
11437 : /****************************************************************
11438 : _spoolss_67
11439 : ****************************************************************/
11440 :
11441 0 : WERROR _spoolss_67(struct pipes_struct *p,
11442 : struct spoolss_67 *r)
11443 : {
11444 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11445 0 : return WERR_NOT_SUPPORTED;
11446 : }
11447 :
11448 : /****************************************************************
11449 : _spoolss_GetPrinterDriverPackagePath
11450 : ****************************************************************/
11451 :
11452 4 : HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11453 : struct spoolss_GetPrinterDriverPackagePath *r)
11454 : {
11455 4 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11456 4 : return HRES_ERROR_NOT_SUPPORTED;
11457 : }
11458 :
11459 : /****************************************************************
11460 : _spoolss_69
11461 : ****************************************************************/
11462 :
11463 0 : WERROR _spoolss_69(struct pipes_struct *p,
11464 : struct spoolss_69 *r)
11465 : {
11466 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11467 0 : return WERR_NOT_SUPPORTED;
11468 : }
11469 :
11470 : /****************************************************************
11471 : _spoolss_6a
11472 : ****************************************************************/
11473 :
11474 0 : WERROR _spoolss_6a(struct pipes_struct *p,
11475 : struct spoolss_6a *r)
11476 : {
11477 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11478 0 : return WERR_NOT_SUPPORTED;
11479 : }
11480 :
11481 : /****************************************************************
11482 : _spoolss_6b
11483 : ****************************************************************/
11484 :
11485 0 : WERROR _spoolss_6b(struct pipes_struct *p,
11486 : struct spoolss_6b *r)
11487 : {
11488 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11489 0 : return WERR_NOT_SUPPORTED;
11490 : }
11491 :
11492 : /****************************************************************
11493 : _spoolss_6c
11494 : ****************************************************************/
11495 :
11496 0 : WERROR _spoolss_6c(struct pipes_struct *p,
11497 : struct spoolss_6c *r)
11498 : {
11499 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11500 0 : return WERR_NOT_SUPPORTED;
11501 : }
11502 :
11503 : /****************************************************************
11504 : _spoolss_6d
11505 : ****************************************************************/
11506 :
11507 0 : WERROR _spoolss_6d(struct pipes_struct *p,
11508 : struct spoolss_6d *r)
11509 : {
11510 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11511 0 : return WERR_NOT_SUPPORTED;
11512 : }
11513 :
11514 : /****************************************************************
11515 : _spoolss_GetJobNamedPropertyValue
11516 : ****************************************************************/
11517 :
11518 0 : WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11519 : struct spoolss_GetJobNamedPropertyValue *r)
11520 : {
11521 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11522 0 : return WERR_NOT_SUPPORTED;
11523 : }
11524 :
11525 : /****************************************************************
11526 : _spoolss_SetJobNamedProperty
11527 : ****************************************************************/
11528 :
11529 0 : WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11530 : struct spoolss_SetJobNamedProperty *r)
11531 : {
11532 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11533 0 : return WERR_NOT_SUPPORTED;
11534 : }
11535 :
11536 : /****************************************************************
11537 : _spoolss_DeleteJobNamedProperty
11538 : ****************************************************************/
11539 :
11540 0 : WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11541 : struct spoolss_DeleteJobNamedProperty *r)
11542 : {
11543 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11544 0 : return WERR_NOT_SUPPORTED;
11545 : }
11546 :
11547 : /****************************************************************
11548 : _spoolss_EnumJobNamedProperties
11549 : ****************************************************************/
11550 :
11551 0 : WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11552 : struct spoolss_EnumJobNamedProperties *r)
11553 : {
11554 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11555 0 : return WERR_NOT_SUPPORTED;
11556 : }
11557 :
11558 : /****************************************************************
11559 : _spoolss_72
11560 : ****************************************************************/
11561 :
11562 0 : WERROR _spoolss_72(struct pipes_struct *p,
11563 : struct spoolss_72 *r)
11564 : {
11565 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11566 0 : return WERR_NOT_SUPPORTED;
11567 : }
11568 :
11569 : /****************************************************************
11570 : _spoolss_73
11571 : ****************************************************************/
11572 :
11573 0 : WERROR _spoolss_73(struct pipes_struct *p,
11574 : struct spoolss_73 *r)
11575 : {
11576 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11577 0 : return WERR_NOT_SUPPORTED;
11578 : }
11579 :
11580 : /****************************************************************
11581 : _spoolss_RpcLogJobInfoForBranchOffice
11582 : ****************************************************************/
11583 :
11584 8 : WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11585 : struct spoolss_LogJobInfoForBranchOffice *r)
11586 : {
11587 8 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11588 8 : return WERR_NOT_SUPPORTED;
11589 : }
11590 :
11591 : static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx,
11592 : const struct dcesrv_endpoint_server *ep_server);
11593 :
11594 : static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
11595 : const struct dcesrv_endpoint_server *ep_server);
11596 :
11597 : #define DCESRV_INTERFACE_SPOOLSS_INIT_SERVER \
11598 : spoolss_init_server
11599 :
11600 : #define DCESRV_INTERFACE_SPOOLSS_SHUTDOWN_SERVER \
11601 : spoolss_shutdown_server
11602 :
11603 28 : static NTSTATUS spoolss_init_server(struct dcesrv_context *dce_ctx,
11604 : const struct dcesrv_endpoint_server *ep_server)
11605 : {
11606 28 : struct messaging_context *msg_ctx = global_messaging_context();
11607 0 : bool ok;
11608 :
11609 : /*
11610 : * Migrate the printers first.
11611 : */
11612 28 : ok = nt_printing_tdb_migrate(msg_ctx);
11613 28 : if (!ok) {
11614 0 : return NT_STATUS_UNSUCCESSFUL;
11615 : }
11616 :
11617 28 : return spoolss__op_init_server(dce_ctx, ep_server);
11618 : }
11619 :
11620 28 : static NTSTATUS spoolss_shutdown_server(struct dcesrv_context *dce_ctx,
11621 : const struct dcesrv_endpoint_server *ep_server)
11622 : {
11623 28 : srv_spoolss_cleanup();
11624 :
11625 28 : return spoolss__op_shutdown_server(dce_ctx, ep_server);
11626 : }
11627 :
11628 : /* include the generated boilerplate */
11629 : #include "librpc/gen_ndr/ndr_spoolss_scompat.c"
|