Parameterize in local.h the MAX_RPC_DATA_SIZE, and ensure
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobd24a44bc403b5a71bda4ad90d0a3d4837e3a4380
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.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
28 #include "includes.h"
30 extern userdom_struct current_user_info;
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 struct table_node {
43 const char *long_archi;
44 const char *short_archi;
45 int version;
48 static Printer_entry *printers_list;
50 typedef struct _counter_printer_0 {
51 struct _counter_printer_0 *next;
52 struct _counter_printer_0 *prev;
54 int snum;
55 uint32 counter;
56 } counter_printer_0;
58 static counter_printer_0 *counter_list;
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
64 /* in printing/nt_printing.c */
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
68 /* API table for Xcv Monitor functions */
70 struct xcv_api_table {
71 const char *name;
72 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
75 /********************************************************************
76 * Canonicalize servername.
77 ********************************************************************/
79 static const char *canon_servername(const char *servername)
81 const char *pservername = servername;
82 while (*pservername == '\\') {
83 pservername++;
85 return pservername;
88 /* translate between internal status numbers and NT status numbers */
89 static int nt_printj_status(int v)
91 switch (v) {
92 case LPQ_QUEUED:
93 return 0;
94 case LPQ_PAUSED:
95 return JOB_STATUS_PAUSED;
96 case LPQ_SPOOLING:
97 return JOB_STATUS_SPOOLING;
98 case LPQ_PRINTING:
99 return JOB_STATUS_PRINTING;
100 case LPQ_ERROR:
101 return JOB_STATUS_ERROR;
102 case LPQ_DELETING:
103 return JOB_STATUS_DELETING;
104 case LPQ_OFFLINE:
105 return JOB_STATUS_OFFLINE;
106 case LPQ_PAPEROUT:
107 return JOB_STATUS_PAPEROUT;
108 case LPQ_PRINTED:
109 return JOB_STATUS_PRINTED;
110 case LPQ_DELETED:
111 return JOB_STATUS_DELETED;
112 case LPQ_BLOCKED:
113 return JOB_STATUS_BLOCKED;
114 case LPQ_USER_INTERVENTION:
115 return JOB_STATUS_USER_INTERVENTION;
117 return 0;
120 static int nt_printq_status(int v)
122 switch (v) {
123 case LPQ_PAUSED:
124 return PRINTER_STATUS_PAUSED;
125 case LPQ_QUEUED:
126 case LPQ_SPOOLING:
127 case LPQ_PRINTING:
128 return 0;
130 return 0;
133 /****************************************************************************
134 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
135 ****************************************************************************/
137 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
139 if (*pp == NULL)
140 return;
142 SAFE_FREE((*pp)->ctr.type);
143 SAFE_FREE(*pp);
146 /***************************************************************************
147 Disconnect from the client
148 ****************************************************************************/
150 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
152 WERROR result;
155 * Tell the specific printing tdb we no longer want messages for this printer
156 * by deregistering our PID.
159 if (!print_notify_deregister_pid(snum))
160 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
162 /* weird if the test succeds !!! */
163 if (smb_connections==0) {
164 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
165 return;
168 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe,
169 talloc_tos(),
170 handle);
172 if (!W_ERROR_IS_OK(result))
173 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
174 dos_errstr(result)));
176 /* if it's the last connection, deconnect the IPC$ share */
177 if (smb_connections==1) {
179 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
180 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
182 messaging_deregister(smbd_messaging_context(),
183 MSG_PRINTER_NOTIFY2, NULL);
185 /* Tell the connections db we're no longer interested in
186 * printer notify messages. */
188 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
191 smb_connections--;
194 /****************************************************************************
195 Functions to free a printer entry datastruct.
196 ****************************************************************************/
198 static void free_printer_entry(void *ptr)
200 Printer_entry *Printer = (Printer_entry *)ptr;
202 if (Printer->notify.client_connected==True) {
203 int snum = -1;
205 if ( Printer->printer_type == SPLHND_SERVER) {
206 snum = -1;
207 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
208 } else if (Printer->printer_type == SPLHND_PRINTER) {
209 snum = print_queue_snum(Printer->sharename);
210 if (snum != -1)
211 srv_spoolss_replycloseprinter(snum,
212 &Printer->notify.client_hnd);
216 Printer->notify.flags=0;
217 Printer->notify.options=0;
218 Printer->notify.localmachine[0]='\0';
219 Printer->notify.printerlocal=0;
220 free_spool_notify_option(&Printer->notify.option);
221 Printer->notify.option=NULL;
222 Printer->notify.client_connected=False;
224 free_nt_devicemode( &Printer->nt_devmode );
225 free_a_printer( &Printer->printer_info, 2 );
227 talloc_destroy( Printer->ctx );
229 /* Remove from the internal list. */
230 DLIST_REMOVE(printers_list, Printer);
232 SAFE_FREE(Printer);
235 /****************************************************************************
236 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
237 ****************************************************************************/
239 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
241 SPOOL_NOTIFY_OPTION *new_sp = NULL;
243 if (!sp)
244 return NULL;
246 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
247 if (!new_sp)
248 return NULL;
250 *new_sp = *sp;
252 if (sp->ctr.count) {
253 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
255 if (!new_sp->ctr.type) {
256 SAFE_FREE(new_sp);
257 return NULL;
261 return new_sp;
264 /****************************************************************************
265 find printer index by handle
266 ****************************************************************************/
268 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
270 Printer_entry *find_printer = NULL;
272 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
273 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
274 return NULL;
277 return find_printer;
280 /****************************************************************************
281 Close printer index by handle.
282 ****************************************************************************/
284 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
286 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
288 if (!Printer) {
289 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
290 return False;
293 close_policy_hnd(p, hnd);
295 return True;
298 /****************************************************************************
299 Delete a printer given a handle.
300 ****************************************************************************/
302 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
304 char *cmd = lp_deleteprinter_cmd();
305 char *command = NULL;
306 int ret;
307 SE_PRIV se_printop = SE_PRINT_OPERATOR;
308 bool is_print_op = False;
310 /* can't fail if we don't try */
312 if ( !*cmd )
313 return WERR_OK;
315 command = talloc_asprintf(ctx,
316 "%s \"%s\"",
317 cmd, sharename);
318 if (!command) {
319 return WERR_NOMEM;
321 if ( token )
322 is_print_op = user_has_privileges( token, &se_printop );
324 DEBUG(10,("Running [%s]\n", command));
326 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
328 if ( is_print_op )
329 become_root();
331 if ( (ret = smbrun(command, NULL)) == 0 ) {
332 /* Tell everyone we updated smb.conf. */
333 message_send_all(smbd_messaging_context(),
334 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
337 if ( is_print_op )
338 unbecome_root();
340 /********** END SePrintOperatorPrivlege BLOCK **********/
342 DEBUGADD(10,("returned [%d]\n", ret));
344 TALLOC_FREE(command);
346 if (ret != 0)
347 return WERR_BADFID; /* What to return here? */
349 /* go ahead and re-read the services immediately */
350 reload_services( False );
352 if ( lp_servicenumber( sharename ) < 0 )
353 return WERR_ACCESS_DENIED;
355 return WERR_OK;
358 /****************************************************************************
359 Delete a printer given a handle.
360 ****************************************************************************/
362 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
364 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
366 if (!Printer) {
367 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
368 return WERR_BADFID;
372 * It turns out that Windows allows delete printer on a handle
373 * opened by an admin user, then used on a pipe handle created
374 * by an anonymous user..... but they're working on security.... riiight !
375 * JRA.
378 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
379 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
380 return WERR_ACCESS_DENIED;
383 /* this does not need a become root since the access check has been
384 done on the handle already */
386 if (del_a_printer( Printer->sharename ) != 0) {
387 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
388 return WERR_BADFID;
391 return delete_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, Printer->sharename );
394 /****************************************************************************
395 Return the snum of a printer corresponding to an handle.
396 ****************************************************************************/
398 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
399 struct share_params **params)
401 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
403 if (!Printer) {
404 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
405 return False;
408 switch (Printer->printer_type) {
409 case SPLHND_PRINTER:
410 DEBUG(4,("short name:%s\n", Printer->sharename));
411 *number = print_queue_snum(Printer->sharename);
412 return (*number != -1);
413 case SPLHND_SERVER:
414 return False;
415 default:
416 return False;
420 /****************************************************************************
421 Set printer handle type.
422 Check if it's \\server or \\server\printer
423 ****************************************************************************/
425 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
427 DEBUG(3,("Setting printer type=%s\n", handlename));
429 if ( strlen(handlename) < 3 ) {
430 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
431 return False;
434 /* it's a print server */
435 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
436 DEBUGADD(4,("Printer is a print server\n"));
437 Printer->printer_type = SPLHND_SERVER;
439 /* it's a printer (set_printer_hnd_name() will handle port monitors */
440 else {
441 DEBUGADD(4,("Printer is a printer\n"));
442 Printer->printer_type = SPLHND_PRINTER;
445 return True;
448 /****************************************************************************
449 Set printer handle name.. Accept names like \\server, \\server\printer,
450 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
451 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
452 XcvDataPort() interface.
453 ****************************************************************************/
455 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
457 int snum;
458 int n_services=lp_numservices();
459 char *aprinter, *printername;
460 const char *servername;
461 fstring sname;
462 bool found=False;
463 NT_PRINTER_INFO_LEVEL *printer = NULL;
464 WERROR result;
466 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
468 aprinter = handlename;
469 if ( *handlename == '\\' ) {
470 servername = canon_servername(handlename);
471 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
472 *aprinter = '\0';
473 aprinter++;
475 } else {
476 servername = "";
479 /* save the servername to fill in replies on this handle */
481 if ( !is_myname_or_ipaddr( servername ) )
482 return False;
484 fstrcpy( Printer->servername, servername );
486 if ( Printer->printer_type == SPLHND_SERVER )
487 return True;
489 if ( Printer->printer_type != SPLHND_PRINTER )
490 return False;
492 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
494 /* check for the Port Monitor Interface */
496 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
497 Printer->printer_type = SPLHND_PORTMON_TCP;
498 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
499 found = True;
501 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
502 Printer->printer_type = SPLHND_PORTMON_LOCAL;
503 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
504 found = True;
507 /* Search all sharenames first as this is easier than pulling
508 the printer_info_2 off of disk. Don't use find_service() since
509 that calls out to map_username() */
511 /* do another loop to look for printernames */
513 for (snum=0; !found && snum<n_services; snum++) {
515 /* no point going on if this is not a printer */
517 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
518 continue;
520 fstrcpy(sname, lp_servicename(snum));
521 if ( strequal( aprinter, sname ) ) {
522 found = True;
523 break;
526 /* no point looking up the printer object if
527 we aren't allowing printername != sharename */
529 if ( lp_force_printername(snum) )
530 continue;
532 fstrcpy(sname, lp_servicename(snum));
534 printer = NULL;
536 /* This call doesn't fill in the location or comment from
537 * a CUPS server for efficiency with large numbers of printers.
538 * JRA.
541 result = get_a_printer_search( NULL, &printer, 2, sname );
542 if ( !W_ERROR_IS_OK(result) ) {
543 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
544 sname, dos_errstr(result)));
545 continue;
548 /* printername is always returned as \\server\printername */
549 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
550 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
551 printer->info_2->printername));
552 free_a_printer( &printer, 2);
553 continue;
556 printername++;
558 if ( strequal(printername, aprinter) ) {
559 free_a_printer( &printer, 2);
560 found = True;
561 break;
564 DEBUGADD(10, ("printername: %s\n", printername));
566 free_a_printer( &printer, 2);
569 free_a_printer( &printer, 2);
571 if ( !found ) {
572 DEBUGADD(4,("Printer not found\n"));
573 return False;
576 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
578 fstrcpy(Printer->sharename, sname);
580 return True;
583 /****************************************************************************
584 Find first available printer slot. creates a printer handle for you.
585 ****************************************************************************/
587 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
589 Printer_entry *new_printer;
591 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
593 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
594 return False;
596 ZERO_STRUCTP(new_printer);
598 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
599 SAFE_FREE(new_printer);
600 return False;
603 /* Add to the internal list. */
604 DLIST_ADD(printers_list, new_printer);
606 new_printer->notify.option=NULL;
608 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
609 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
610 close_printer_handle(p, hnd);
611 return False;
614 if (!set_printer_hnd_printertype(new_printer, name)) {
615 close_printer_handle(p, hnd);
616 return False;
619 if (!set_printer_hnd_name(new_printer, name)) {
620 close_printer_handle(p, hnd);
621 return False;
624 new_printer->access_granted = access_granted;
626 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
628 return True;
631 /***************************************************************************
632 check to see if the client motify handle is monitoring the notification
633 given by (notify_type, notify_field).
634 **************************************************************************/
636 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
637 uint16 notify_field)
639 return True;
642 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
643 uint16 notify_field)
645 SPOOL_NOTIFY_OPTION *option = p->notify.option;
646 uint32 i, j;
649 * Flags should always be zero when the change notify
650 * is registered by the client's spooler. A user Win32 app
651 * might use the flags though instead of the NOTIFY_OPTION_INFO
652 * --jerry
655 if (!option) {
656 return False;
659 if (p->notify.flags)
660 return is_monitoring_event_flags(
661 p->notify.flags, notify_type, notify_field);
663 for (i = 0; i < option->count; i++) {
665 /* Check match for notify_type */
667 if (option->ctr.type[i].type != notify_type)
668 continue;
670 /* Check match for field */
672 for (j = 0; j < option->ctr.type[i].count; j++) {
673 if (option->ctr.type[i].fields[j] == notify_field) {
674 return True;
679 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
680 p->servername, p->sharename, notify_type, notify_field));
682 return False;
685 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
687 static void notify_one_value(struct spoolss_notify_msg *msg,
688 SPOOL_NOTIFY_INFO_DATA *data,
689 TALLOC_CTX *mem_ctx)
691 data->notify_data.value[0] = msg->notify.value[0];
692 data->notify_data.value[1] = 0;
695 static void notify_string(struct spoolss_notify_msg *msg,
696 SPOOL_NOTIFY_INFO_DATA *data,
697 TALLOC_CTX *mem_ctx)
699 UNISTR2 unistr;
701 /* The length of the message includes the trailing \0 */
703 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
705 data->notify_data.data.length = msg->len * 2;
706 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
708 if (!data->notify_data.data.string) {
709 data->notify_data.data.length = 0;
710 return;
713 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
716 static void notify_system_time(struct spoolss_notify_msg *msg,
717 SPOOL_NOTIFY_INFO_DATA *data,
718 TALLOC_CTX *mem_ctx)
720 SYSTEMTIME systime;
721 prs_struct ps;
723 if (msg->len != sizeof(time_t)) {
724 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
725 msg->len));
726 return;
729 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
730 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
731 return;
734 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
735 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
736 prs_mem_free(&ps);
737 return;
740 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
741 prs_mem_free(&ps);
742 return;
745 data->notify_data.data.length = prs_offset(&ps);
746 if (prs_offset(&ps)) {
747 data->notify_data.data.string = (uint16 *)
748 TALLOC(mem_ctx, prs_offset(&ps));
749 if (!data->notify_data.data.string) {
750 prs_mem_free(&ps);
751 return;
753 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
754 } else {
755 data->notify_data.data.string = NULL;
758 prs_mem_free(&ps);
761 struct notify2_message_table {
762 const char *name;
763 void (*fn)(struct spoolss_notify_msg *msg,
764 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
767 static struct notify2_message_table printer_notify_table[] = {
768 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
769 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
770 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
771 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
772 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
773 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
774 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
775 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
776 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
777 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
778 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
779 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
780 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
781 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
782 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
783 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
784 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
785 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
786 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
789 static struct notify2_message_table job_notify_table[] = {
790 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
791 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
792 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
793 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
794 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
795 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
796 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
797 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
798 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
799 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
800 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
801 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
802 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
803 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
804 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
805 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
806 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
807 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
808 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
809 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
810 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
811 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
812 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
813 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
817 /***********************************************************************
818 Allocate talloc context for container object
819 **********************************************************************/
821 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
823 if ( !ctr )
824 return;
826 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
828 return;
831 /***********************************************************************
832 release all allocated memory and zero out structure
833 **********************************************************************/
835 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
837 if ( !ctr )
838 return;
840 if ( ctr->ctx )
841 talloc_destroy(ctr->ctx);
843 ZERO_STRUCTP(ctr);
845 return;
848 /***********************************************************************
849 **********************************************************************/
851 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
853 if ( !ctr )
854 return NULL;
856 return ctr->ctx;
859 /***********************************************************************
860 **********************************************************************/
862 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
864 if ( !ctr || !ctr->msg_groups )
865 return NULL;
867 if ( idx >= ctr->num_groups )
868 return NULL;
870 return &ctr->msg_groups[idx];
874 /***********************************************************************
875 How many groups of change messages do we have ?
876 **********************************************************************/
878 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
880 if ( !ctr )
881 return 0;
883 return ctr->num_groups;
886 /***********************************************************************
887 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
888 **********************************************************************/
890 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
892 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
893 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
894 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
895 int i, new_slot;
897 if ( !ctr || !msg )
898 return 0;
900 /* loop over all groups looking for a matching printer name */
902 for ( i=0; i<ctr->num_groups; i++ ) {
903 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
904 break;
907 /* add a new group? */
909 if ( i == ctr->num_groups ) {
910 ctr->num_groups++;
912 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
913 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
914 return 0;
916 ctr->msg_groups = groups;
918 /* clear the new entry and set the printer name */
920 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
921 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
924 /* add the change messages; 'i' is the correct index now regardless */
926 msg_grp = &ctr->msg_groups[i];
928 msg_grp->num_msgs++;
930 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
931 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
932 return 0;
934 msg_grp->msgs = msg_list;
936 new_slot = msg_grp->num_msgs-1;
937 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
939 /* need to allocate own copy of data */
941 if ( msg->len != 0 )
942 msg_grp->msgs[new_slot].notify.data = (char *)
943 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
945 return ctr->num_groups;
948 /***********************************************************************
949 Send a change notication message on all handles which have a call
950 back registered
951 **********************************************************************/
953 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
955 Printer_entry *p;
956 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
957 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
958 SPOOLSS_NOTIFY_MSG *messages;
959 int sending_msg_count;
961 if ( !msg_group ) {
962 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
963 return;
966 messages = msg_group->msgs;
968 if ( !messages ) {
969 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
970 return;
973 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
975 /* loop over all printers */
977 for (p = printers_list; p; p = p->next) {
978 SPOOL_NOTIFY_INFO_DATA *data;
979 uint32 data_len = 0;
980 uint32 id;
981 int i;
983 /* Is there notification on this handle? */
985 if ( !p->notify.client_connected )
986 continue;
988 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
990 /* For this printer? Print servers always receive
991 notifications. */
993 if ( ( p->printer_type == SPLHND_PRINTER ) &&
994 ( !strequal(msg_group->printername, p->sharename) ) )
995 continue;
997 DEBUG(10,("Our printer\n"));
999 /* allocate the max entries possible */
1001 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
1002 if (!data) {
1003 return;
1006 ZERO_STRUCTP(data);
1008 /* build the array of change notifications */
1010 sending_msg_count = 0;
1012 for ( i=0; i<msg_group->num_msgs; i++ ) {
1013 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1015 /* Are we monitoring this event? */
1017 if (!is_monitoring_event(p, msg->type, msg->field))
1018 continue;
1020 sending_msg_count++;
1023 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1024 msg->type, msg->field, p->sharename));
1027 * if the is a printer notification handle and not a job notification
1028 * type, then set the id to 0. Other wise just use what was specified
1029 * in the message.
1031 * When registering change notification on a print server handle
1032 * we always need to send back the id (snum) matching the printer
1033 * for which the change took place. For change notify registered
1034 * on a printer handle, this does not matter and the id should be 0.
1036 * --jerry
1039 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1040 id = 0;
1041 else
1042 id = msg->id;
1045 /* Convert unix jobid to smb jobid */
1047 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1048 id = sysjob_to_jobid(msg->id);
1050 if (id == -1) {
1051 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1052 goto done;
1056 construct_info_data( &data[data_len], msg->type, msg->field, id );
1058 switch(msg->type) {
1059 case PRINTER_NOTIFY_TYPE:
1060 if ( printer_notify_table[msg->field].fn )
1061 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1062 break;
1064 case JOB_NOTIFY_TYPE:
1065 if ( job_notify_table[msg->field].fn )
1066 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1067 break;
1069 default:
1070 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1071 goto done;
1074 data_len++;
1077 if ( sending_msg_count ) {
1078 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1079 data_len, data, p->notify.change, 0 );
1083 done:
1084 DEBUG(8,("send_notify2_changes: Exit...\n"));
1085 return;
1088 /***********************************************************************
1089 **********************************************************************/
1091 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1094 uint32 tv_sec, tv_usec;
1095 size_t offset = 0;
1097 /* Unpack message */
1099 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1100 msg->printer);
1102 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1103 &tv_sec, &tv_usec,
1104 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1106 if (msg->len == 0)
1107 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1108 &msg->notify.value[0], &msg->notify.value[1]);
1109 else
1110 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1111 &msg->len, &msg->notify.data);
1113 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1114 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1116 tv->tv_sec = tv_sec;
1117 tv->tv_usec = tv_usec;
1119 if (msg->len == 0)
1120 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1121 msg->notify.value[1]));
1122 else
1123 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1125 return True;
1128 /********************************************************************
1129 Receive a notify2 message list
1130 ********************************************************************/
1132 static void receive_notify2_message_list(struct messaging_context *msg,
1133 void *private_data,
1134 uint32_t msg_type,
1135 struct server_id server_id,
1136 DATA_BLOB *data)
1138 size_t msg_count, i;
1139 char *buf = (char *)data->data;
1140 char *msg_ptr;
1141 size_t msg_len;
1142 SPOOLSS_NOTIFY_MSG notify;
1143 SPOOLSS_NOTIFY_MSG_CTR messages;
1144 int num_groups;
1146 if (data->length < 4) {
1147 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1148 return;
1151 msg_count = IVAL(buf, 0);
1152 msg_ptr = buf + 4;
1154 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1156 if (msg_count == 0) {
1157 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1158 return;
1161 /* initialize the container */
1163 ZERO_STRUCT( messages );
1164 notify_msg_ctr_init( &messages );
1167 * build message groups for each printer identified
1168 * in a change_notify msg. Remember that a PCN message
1169 * includes the handle returned for the srv_spoolss_replyopenprinter()
1170 * call. Therefore messages are grouped according to printer handle.
1173 for ( i=0; i<msg_count; i++ ) {
1174 struct timeval msg_tv;
1176 if (msg_ptr + 4 - buf > data->length) {
1177 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1178 return;
1181 msg_len = IVAL(msg_ptr,0);
1182 msg_ptr += 4;
1184 if (msg_ptr + msg_len - buf > data->length) {
1185 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1186 return;
1189 /* unpack messages */
1191 ZERO_STRUCT( notify );
1192 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1193 msg_ptr += msg_len;
1195 /* add to correct list in container */
1197 notify_msg_ctr_addmsg( &messages, &notify );
1199 /* free memory that might have been allocated by notify2_unpack_msg() */
1201 if ( notify.len != 0 )
1202 SAFE_FREE( notify.notify.data );
1205 /* process each group of messages */
1207 num_groups = notify_msg_ctr_numgroups( &messages );
1208 for ( i=0; i<num_groups; i++ )
1209 send_notify2_changes( &messages, i );
1212 /* cleanup */
1214 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1216 notify_msg_ctr_destroy( &messages );
1218 return;
1221 /********************************************************************
1222 Send a message to ourself about new driver being installed
1223 so we can upgrade the information for each printer bound to this
1224 driver
1225 ********************************************************************/
1227 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1229 int len = strlen(drivername);
1231 if (!len)
1232 return False;
1234 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1235 drivername));
1237 messaging_send_buf(smbd_messaging_context(), procid_self(),
1238 MSG_PRINTER_DRVUPGRADE,
1239 (uint8 *)drivername, len+1);
1241 return True;
1244 /**********************************************************************
1245 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1246 over all printers, upgrading ones as necessary
1247 **********************************************************************/
1249 void do_drv_upgrade_printer(struct messaging_context *msg,
1250 void *private_data,
1251 uint32_t msg_type,
1252 struct server_id server_id,
1253 DATA_BLOB *data)
1255 fstring drivername;
1256 int snum;
1257 int n_services = lp_numservices();
1258 size_t len;
1260 len = MIN(data->length,sizeof(drivername)-1);
1261 strncpy(drivername, (const char *)data->data, len);
1263 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1265 /* Iterate the printer list */
1267 for (snum=0; snum<n_services; snum++)
1269 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1271 WERROR result;
1272 NT_PRINTER_INFO_LEVEL *printer = NULL;
1274 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1275 if (!W_ERROR_IS_OK(result))
1276 continue;
1278 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1280 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1282 /* all we care about currently is the change_id */
1284 result = mod_a_printer(printer, 2);
1285 if (!W_ERROR_IS_OK(result)) {
1286 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1287 dos_errstr(result)));
1291 free_a_printer(&printer, 2);
1295 /* all done */
1298 /********************************************************************
1299 Update the cache for all printq's with a registered client
1300 connection
1301 ********************************************************************/
1303 void update_monitored_printq_cache( void )
1305 Printer_entry *printer = printers_list;
1306 int snum;
1308 /* loop through all printers and update the cache where
1309 client_connected == True */
1310 while ( printer )
1312 if ( (printer->printer_type == SPLHND_PRINTER)
1313 && printer->notify.client_connected )
1315 snum = print_queue_snum(printer->sharename);
1316 print_queue_status( snum, NULL, NULL );
1319 printer = printer->next;
1322 return;
1324 /********************************************************************
1325 Send a message to ourself about new driver being installed
1326 so we can upgrade the information for each printer bound to this
1327 driver
1328 ********************************************************************/
1330 static bool srv_spoolss_reset_printerdata(char* drivername)
1332 int len = strlen(drivername);
1334 if (!len)
1335 return False;
1337 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1338 drivername));
1340 messaging_send_buf(smbd_messaging_context(), procid_self(),
1341 MSG_PRINTERDATA_INIT_RESET,
1342 (uint8 *)drivername, len+1);
1344 return True;
1347 /**********************************************************************
1348 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1349 over all printers, resetting printer data as neessary
1350 **********************************************************************/
1352 void reset_all_printerdata(struct messaging_context *msg,
1353 void *private_data,
1354 uint32_t msg_type,
1355 struct server_id server_id,
1356 DATA_BLOB *data)
1358 fstring drivername;
1359 int snum;
1360 int n_services = lp_numservices();
1361 size_t len;
1363 len = MIN( data->length, sizeof(drivername)-1 );
1364 strncpy( drivername, (const char *)data->data, len );
1366 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1368 /* Iterate the printer list */
1370 for ( snum=0; snum<n_services; snum++ )
1372 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1374 WERROR result;
1375 NT_PRINTER_INFO_LEVEL *printer = NULL;
1377 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1378 if ( !W_ERROR_IS_OK(result) )
1379 continue;
1382 * if the printer is bound to the driver,
1383 * then reset to the new driver initdata
1386 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1388 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1390 if ( !set_driver_init(printer, 2) ) {
1391 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1392 printer->info_2->printername, printer->info_2->drivername));
1395 result = mod_a_printer( printer, 2 );
1396 if ( !W_ERROR_IS_OK(result) ) {
1397 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1398 get_dos_error_msg(result)));
1402 free_a_printer( &printer, 2 );
1406 /* all done */
1408 return;
1411 /********************************************************************
1412 Copy routines used by convert_to_openprinterex()
1413 *******************************************************************/
1415 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1417 DEVICEMODE *d;
1418 int len;
1420 if (!devmode)
1421 return NULL;
1423 DEBUG (8,("dup_devmode\n"));
1425 /* bulk copy first */
1427 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1428 if (!d)
1429 return NULL;
1431 /* dup the pointer members separately */
1433 len = unistrlen(devmode->devicename.buffer);
1434 if (len != -1) {
1435 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1436 if (!d->devicename.buffer) {
1437 return NULL;
1439 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1440 return NULL;
1444 len = unistrlen(devmode->formname.buffer);
1445 if (len != -1) {
1446 d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
1447 if (!d->formname.buffer) {
1448 return NULL;
1450 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1451 return NULL;
1454 if (devmode->driverextra) {
1455 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1456 devmode->driverextra);
1457 if (!d->dev_private) {
1458 return NULL;
1460 } else {
1461 d->dev_private = NULL;
1463 return d;
1466 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1468 if (!new_ctr || !ctr)
1469 return;
1471 DEBUG(8,("copy_devmode_ctr\n"));
1473 new_ctr->size = ctr->size;
1474 new_ctr->devmode_ptr = ctr->devmode_ptr;
1476 if(ctr->devmode_ptr)
1477 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1480 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1482 if (!new_def || !def)
1483 return;
1485 DEBUG(8,("copy_printer_defaults\n"));
1487 new_def->datatype_ptr = def->datatype_ptr;
1489 if (def->datatype_ptr)
1490 copy_unistr2(&new_def->datatype, &def->datatype);
1492 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1494 new_def->access_required = def->access_required;
1497 /********************************************************************
1498 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1499 * SPOOL_Q_OPEN_PRINTER_EX structure
1500 ********************************************************************/
1502 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1504 if (!q_u_ex || !q_u)
1505 return WERR_OK;
1507 DEBUG(8,("convert_to_openprinterex\n"));
1509 if ( q_u->printername ) {
1510 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1511 if (q_u_ex->printername == NULL)
1512 return WERR_NOMEM;
1513 copy_unistr2(q_u_ex->printername, q_u->printername);
1516 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1518 return WERR_OK;
1521 /********************************************************************
1522 * spoolss_open_printer
1524 * called from the spoolss dispatcher
1525 ********************************************************************/
1527 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1529 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1530 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1532 if (!q_u || !r_u)
1533 return WERR_NOMEM;
1535 ZERO_STRUCT(q_u_ex);
1536 ZERO_STRUCT(r_u_ex);
1538 /* convert the OpenPrinter() call to OpenPrinterEx() */
1540 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1541 if (!W_ERROR_IS_OK(r_u_ex.status))
1542 return r_u_ex.status;
1544 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1546 /* convert back to OpenPrinter() */
1548 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1550 if (W_ERROR_EQUAL(r_u->status, WERR_INVALID_PARAM)) {
1551 /* OpenPrinterEx returns this for a bad
1552 * printer name. We must return WERR_INVALID_PRINTER_NAME
1553 * instead.
1555 r_u->status = WERR_INVALID_PRINTER_NAME;
1557 return r_u->status;
1560 /********************************************************************
1561 ********************************************************************/
1563 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1565 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1566 POLICY_HND *handle = &r_u->handle;
1568 fstring name;
1569 int snum;
1570 Printer_entry *Printer=NULL;
1572 if (!q_u->printername) {
1573 return WERR_INVALID_PARAM;
1576 /* some sanity check because you can open a printer or a print server */
1577 /* aka: \\server\printer or \\server */
1579 unistr2_to_ascii(name, q_u->printername, sizeof(name));
1581 DEBUGADD(3,("checking name: %s\n",name));
1583 if (!open_printer_hnd(p, handle, name, 0)) {
1584 return WERR_INVALID_PARAM;
1587 Printer=find_printer_index_by_hnd(p, handle);
1588 if ( !Printer ) {
1589 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1590 "handle we created for printer %s\n", name ));
1591 close_printer_handle(p,handle);
1592 return WERR_INVALID_PARAM;
1596 * First case: the user is opening the print server:
1598 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1599 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1601 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1602 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1603 * or if the user is listed in the smb.conf printer admin parameter.
1605 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1606 * client view printer folder, but does not show the MSAPW.
1608 * Note: this test needs code to check access rights here too. Jeremy
1609 * could you look at this?
1611 * Second case: the user is opening a printer:
1612 * NT doesn't let us connect to a printer if the connecting user
1613 * doesn't have print permission.
1615 * Third case: user is opening a Port Monitor
1616 * access checks same as opening a handle to the print server.
1619 switch (Printer->printer_type )
1621 case SPLHND_SERVER:
1622 case SPLHND_PORTMON_TCP:
1623 case SPLHND_PORTMON_LOCAL:
1624 /* Printserver handles use global struct... */
1626 snum = -1;
1628 /* Map standard access rights to object specific access rights */
1630 se_map_standard(&printer_default->access_required,
1631 &printserver_std_mapping);
1633 /* Deny any object specific bits that don't apply to print
1634 servers (i.e printer and job specific bits) */
1636 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1638 if (printer_default->access_required &
1639 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1640 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1641 close_printer_handle(p, handle);
1642 return WERR_ACCESS_DENIED;
1645 /* Allow admin access */
1647 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1649 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1651 if (!lp_ms_add_printer_wizard()) {
1652 close_printer_handle(p, handle);
1653 return WERR_ACCESS_DENIED;
1656 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1657 and not a printer admin, then fail */
1659 if ((p->pipe_user.ut.uid != 0) &&
1660 !user_has_privileges(p->pipe_user.nt_user_token,
1661 &se_printop ) &&
1662 !token_contains_name_in_list(
1663 uidtoname(p->pipe_user.ut.uid),
1664 NULL, NULL,
1665 p->pipe_user.nt_user_token,
1666 lp_printer_admin(snum))) {
1667 close_printer_handle(p, handle);
1668 return WERR_ACCESS_DENIED;
1671 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1673 else
1675 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1678 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1679 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1681 /* We fall through to return WERR_OK */
1682 break;
1684 case SPLHND_PRINTER:
1685 /* NT doesn't let us connect to a printer if the connecting user
1686 doesn't have print permission. */
1688 if (!get_printer_snum(p, handle, &snum, NULL)) {
1689 close_printer_handle(p, handle);
1690 return WERR_BADFID;
1693 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1695 /* map an empty access mask to the minimum access mask */
1696 if (printer_default->access_required == 0x0)
1697 printer_default->access_required = PRINTER_ACCESS_USE;
1700 * If we are not serving the printer driver for this printer,
1701 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1702 * will keep NT clients happy --jerry
1705 if (lp_use_client_driver(snum)
1706 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1708 printer_default->access_required = PRINTER_ACCESS_USE;
1711 /* check smb.conf parameters and the the sec_desc */
1713 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1714 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1715 return WERR_ACCESS_DENIED;
1718 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid), NULL,
1719 p->pipe_user.nt_user_token, snum) ||
1720 !print_access_check(p->server_info, snum,
1721 printer_default->access_required)) {
1722 DEBUG(3, ("access DENIED for printer open\n"));
1723 close_printer_handle(p, handle);
1724 return WERR_ACCESS_DENIED;
1727 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1728 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1729 close_printer_handle(p, handle);
1730 return WERR_ACCESS_DENIED;
1733 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1734 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1735 else
1736 printer_default->access_required = PRINTER_ACCESS_USE;
1738 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1739 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1741 break;
1743 default:
1744 /* sanity check to prevent programmer error */
1745 return WERR_BADFID;
1748 Printer->access_granted = printer_default->access_required;
1751 * If the client sent a devmode in the OpenPrinter() call, then
1752 * save it here in case we get a job submission on this handle
1755 if ( (Printer->printer_type != SPLHND_SERVER)
1756 && q_u->printer_default.devmode_cont.devmode_ptr )
1758 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1759 &Printer->nt_devmode );
1762 #if 0 /* JERRY -- I'm doubtful this is really effective */
1763 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1764 optimization in Windows 2000 clients --jerry */
1766 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1767 && (RA_WIN2K == get_remote_arch()) )
1769 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1770 sys_usleep( 500000 );
1772 #endif
1774 return WERR_OK;
1777 /****************************************************************************
1778 ****************************************************************************/
1780 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1781 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1783 bool ret;
1785 switch (level) {
1786 case 2:
1787 /* allocate memory if needed. Messy because
1788 convert_printer_info is used to update an existing
1789 printer or build a new one */
1791 if ( !printer->info_2 ) {
1792 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1793 if ( !printer->info_2 ) {
1794 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1795 return False;
1799 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1800 printer->info_2->setuptime = time(NULL);
1802 return ret;
1805 return False;
1808 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1809 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1811 bool result = True;
1813 switch (level) {
1814 case 3:
1815 printer->info_3=NULL;
1816 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1817 result = False;
1818 break;
1819 case 6:
1820 printer->info_6=NULL;
1821 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1822 result = False;
1823 break;
1824 default:
1825 break;
1828 return result;
1831 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1832 NT_DEVICEMODE **pp_nt_devmode)
1834 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1837 * Ensure nt_devmode is a valid pointer
1838 * as we will be overwriting it.
1841 if (nt_devmode == NULL) {
1842 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1843 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1844 return False;
1847 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1848 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1850 nt_devmode->specversion=devmode->specversion;
1851 nt_devmode->driverversion=devmode->driverversion;
1852 nt_devmode->size=devmode->size;
1853 nt_devmode->fields=devmode->fields;
1854 nt_devmode->orientation=devmode->orientation;
1855 nt_devmode->papersize=devmode->papersize;
1856 nt_devmode->paperlength=devmode->paperlength;
1857 nt_devmode->paperwidth=devmode->paperwidth;
1858 nt_devmode->scale=devmode->scale;
1859 nt_devmode->copies=devmode->copies;
1860 nt_devmode->defaultsource=devmode->defaultsource;
1861 nt_devmode->printquality=devmode->printquality;
1862 nt_devmode->color=devmode->color;
1863 nt_devmode->duplex=devmode->duplex;
1864 nt_devmode->yresolution=devmode->yresolution;
1865 nt_devmode->ttoption=devmode->ttoption;
1866 nt_devmode->collate=devmode->collate;
1868 nt_devmode->logpixels=devmode->logpixels;
1869 nt_devmode->bitsperpel=devmode->bitsperpel;
1870 nt_devmode->pelswidth=devmode->pelswidth;
1871 nt_devmode->pelsheight=devmode->pelsheight;
1872 nt_devmode->displayflags=devmode->displayflags;
1873 nt_devmode->displayfrequency=devmode->displayfrequency;
1874 nt_devmode->icmmethod=devmode->icmmethod;
1875 nt_devmode->icmintent=devmode->icmintent;
1876 nt_devmode->mediatype=devmode->mediatype;
1877 nt_devmode->dithertype=devmode->dithertype;
1878 nt_devmode->reserved1=devmode->reserved1;
1879 nt_devmode->reserved2=devmode->reserved2;
1880 nt_devmode->panningwidth=devmode->panningwidth;
1881 nt_devmode->panningheight=devmode->panningheight;
1884 * Only change private and driverextra if the incoming devmode
1885 * has a new one. JRA.
1888 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1889 SAFE_FREE(nt_devmode->nt_dev_private);
1890 nt_devmode->driverextra=devmode->driverextra;
1891 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1892 return False;
1893 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1896 *pp_nt_devmode = nt_devmode;
1898 return True;
1901 /********************************************************************
1902 * _spoolss_enddocprinter_internal.
1903 ********************************************************************/
1905 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1907 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1908 int snum;
1910 if (!Printer) {
1911 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1912 return WERR_BADFID;
1915 if (!get_printer_snum(p, handle, &snum, NULL))
1916 return WERR_BADFID;
1918 Printer->document_started=False;
1919 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1920 /* error codes unhandled so far ... */
1922 return WERR_OK;
1925 /********************************************************************
1926 * api_spoolss_closeprinter
1927 ********************************************************************/
1929 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1931 POLICY_HND *handle = &q_u->handle;
1933 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1935 if (Printer && Printer->document_started)
1936 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1938 if (!close_printer_handle(p, handle))
1939 return WERR_BADFID;
1941 /* clear the returned printer handle. Observed behavior
1942 from Win2k server. Don't think this really matters.
1943 Previous code just copied the value of the closed
1944 handle. --jerry */
1946 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1948 return WERR_OK;
1951 /********************************************************************
1952 * api_spoolss_deleteprinter
1954 ********************************************************************/
1956 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1958 POLICY_HND *handle = &q_u->handle;
1959 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1960 WERROR result;
1962 if (Printer && Printer->document_started)
1963 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1965 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1967 result = delete_printer_handle(p, handle);
1969 update_c_setprinter(False);
1971 return result;
1974 /*******************************************************************
1975 * static function to lookup the version id corresponding to an
1976 * long architecture string
1977 ******************************************************************/
1979 static int get_version_id (char * arch)
1981 int i;
1982 struct table_node archi_table[]= {
1984 {"Windows 4.0", "WIN40", 0 },
1985 {"Windows NT x86", "W32X86", 2 },
1986 {"Windows NT R4000", "W32MIPS", 2 },
1987 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1988 {"Windows NT PowerPC", "W32PPC", 2 },
1989 {"Windows IA64", "IA64", 3 },
1990 {"Windows x64", "x64", 3 },
1991 {NULL, "", -1 }
1994 for (i=0; archi_table[i].long_archi != NULL; i++)
1996 if (strcmp(arch, archi_table[i].long_archi) == 0)
1997 return (archi_table[i].version);
2000 return -1;
2003 /********************************************************************
2004 * _spoolss_deleteprinterdriver
2005 ********************************************************************/
2007 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2009 fstring driver;
2010 fstring arch;
2011 NT_PRINTER_DRIVER_INFO_LEVEL info;
2012 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2013 int version;
2014 WERROR status;
2015 WERROR status_win2k = WERR_ACCESS_DENIED;
2016 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2018 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2019 and not a printer admin, then fail */
2021 if ( (p->pipe_user.ut.uid != 0)
2022 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2023 && !token_contains_name_in_list(
2024 uidtoname(p->pipe_user.ut.uid), NULL,
2025 NULL, p->pipe_user.nt_user_token,
2026 lp_printer_admin(-1)) )
2028 return WERR_ACCESS_DENIED;
2031 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2032 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2034 /* check that we have a valid driver name first */
2036 if ((version=get_version_id(arch)) == -1)
2037 return WERR_INVALID_ENVIRONMENT;
2039 ZERO_STRUCT(info);
2040 ZERO_STRUCT(info_win2k);
2042 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2044 /* try for Win2k driver if "Windows NT x86" */
2046 if ( version == 2 ) {
2047 version = 3;
2048 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2049 status = WERR_UNKNOWN_PRINTER_DRIVER;
2050 goto done;
2053 /* otherwise it was a failure */
2054 else {
2055 status = WERR_UNKNOWN_PRINTER_DRIVER;
2056 goto done;
2061 if (printer_driver_in_use(info.info_3)) {
2062 status = WERR_PRINTER_DRIVER_IN_USE;
2063 goto done;
2066 if ( version == 2 )
2068 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2070 /* if we get to here, we now have 2 driver info structures to remove */
2071 /* remove the Win2k driver first*/
2073 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2074 free_a_printer_driver( info_win2k, 3 );
2076 /* this should not have failed---if it did, report to client */
2077 if ( !W_ERROR_IS_OK(status_win2k) )
2079 status = status_win2k;
2080 goto done;
2085 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2087 /* if at least one of the deletes succeeded return OK */
2089 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2090 status = WERR_OK;
2092 done:
2093 free_a_printer_driver( info, 3 );
2095 return status;
2098 /********************************************************************
2099 * spoolss_deleteprinterdriverex
2100 ********************************************************************/
2102 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2104 fstring driver;
2105 fstring arch;
2106 NT_PRINTER_DRIVER_INFO_LEVEL info;
2107 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2108 int version;
2109 uint32 flags = q_u->delete_flags;
2110 bool delete_files;
2111 WERROR status;
2112 WERROR status_win2k = WERR_ACCESS_DENIED;
2113 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2115 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2116 and not a printer admin, then fail */
2118 if ( (p->pipe_user.ut.uid != 0)
2119 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2120 && !token_contains_name_in_list(
2121 uidtoname(p->pipe_user.ut.uid), NULL, NULL,
2122 p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2124 return WERR_ACCESS_DENIED;
2127 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2128 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2130 /* check that we have a valid driver name first */
2131 if ((version=get_version_id(arch)) == -1) {
2132 /* this is what NT returns */
2133 return WERR_INVALID_ENVIRONMENT;
2136 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2137 version = q_u->version;
2139 ZERO_STRUCT(info);
2140 ZERO_STRUCT(info_win2k);
2142 status = get_a_printer_driver(&info, 3, driver, arch, version);
2144 if ( !W_ERROR_IS_OK(status) )
2147 * if the client asked for a specific version,
2148 * or this is something other than Windows NT x86,
2149 * then we've failed
2152 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2153 goto done;
2155 /* try for Win2k driver if "Windows NT x86" */
2157 version = 3;
2158 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2159 status = WERR_UNKNOWN_PRINTER_DRIVER;
2160 goto done;
2164 if ( printer_driver_in_use(info.info_3) ) {
2165 status = WERR_PRINTER_DRIVER_IN_USE;
2166 goto done;
2170 * we have a couple of cases to consider.
2171 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2172 * then the delete should fail if **any** files overlap with
2173 * other drivers
2174 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2175 * non-overlapping files
2176 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2177 * is set, the do not delete any files
2178 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2181 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2183 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2185 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2186 /* no idea of the correct error here */
2187 status = WERR_ACCESS_DENIED;
2188 goto done;
2192 /* also check for W32X86/3 if necessary; maybe we already have? */
2194 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2195 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2198 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2199 /* no idea of the correct error here */
2200 free_a_printer_driver( info_win2k, 3 );
2201 status = WERR_ACCESS_DENIED;
2202 goto done;
2205 /* if we get to here, we now have 2 driver info structures to remove */
2206 /* remove the Win2k driver first*/
2208 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2209 free_a_printer_driver( info_win2k, 3 );
2211 /* this should not have failed---if it did, report to client */
2213 if ( !W_ERROR_IS_OK(status_win2k) )
2214 goto done;
2218 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2220 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2221 status = WERR_OK;
2222 done:
2223 free_a_printer_driver( info, 3 );
2225 return status;
2229 /****************************************************************************
2230 Internal routine for retreiving printerdata
2231 ***************************************************************************/
2233 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2234 const char *key, const char *value, uint32 *type, uint8 **data,
2235 uint32 *needed, uint32 in_size )
2237 REGISTRY_VALUE *val;
2238 uint32 size;
2239 int data_len;
2241 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2242 return WERR_BADFILE;
2244 *type = regval_type( val );
2246 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2248 size = regval_size( val );
2250 /* copy the min(in_size, len) */
2252 if ( in_size ) {
2253 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2255 /* special case for 0 length values */
2256 if ( data_len ) {
2257 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2258 return WERR_NOMEM;
2260 else {
2261 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2262 return WERR_NOMEM;
2265 else
2266 *data = NULL;
2268 *needed = size;
2270 DEBUG(5,("get_printer_dataex: copy done\n"));
2272 return WERR_OK;
2275 /****************************************************************************
2276 Internal routine for removing printerdata
2277 ***************************************************************************/
2279 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2281 return delete_printer_data( printer->info_2, key, value );
2284 /****************************************************************************
2285 Internal routine for storing printerdata
2286 ***************************************************************************/
2288 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2289 uint32 type, uint8 *data, int real_len )
2291 /* the registry objects enforce uniqueness based on value name */
2293 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2296 /********************************************************************
2297 GetPrinterData on a printer server Handle.
2298 ********************************************************************/
2300 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2302 int i;
2304 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2306 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2307 *type = REG_DWORD;
2308 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2309 return WERR_NOMEM;
2310 SIVAL(*data, 0, 0x00);
2311 *needed = 0x4;
2312 return WERR_OK;
2315 if (!StrCaseCmp(value, "BeepEnabled")) {
2316 *type = REG_DWORD;
2317 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2318 return WERR_NOMEM;
2319 SIVAL(*data, 0, 0x00);
2320 *needed = 0x4;
2321 return WERR_OK;
2324 if (!StrCaseCmp(value, "EventLog")) {
2325 *type = REG_DWORD;
2326 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2327 return WERR_NOMEM;
2328 /* formally was 0x1b */
2329 SIVAL(*data, 0, 0x0);
2330 *needed = 0x4;
2331 return WERR_OK;
2334 if (!StrCaseCmp(value, "NetPopup")) {
2335 *type = REG_DWORD;
2336 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2337 return WERR_NOMEM;
2338 SIVAL(*data, 0, 0x00);
2339 *needed = 0x4;
2340 return WERR_OK;
2343 if (!StrCaseCmp(value, "MajorVersion")) {
2344 *type = REG_DWORD;
2345 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2346 return WERR_NOMEM;
2348 /* Windows NT 4.0 seems to not allow uploading of drivers
2349 to a server that reports 0x3 as the MajorVersion.
2350 need to investigate more how Win2k gets around this .
2351 -- jerry */
2353 if ( RA_WINNT == get_remote_arch() )
2354 SIVAL(*data, 0, 2);
2355 else
2356 SIVAL(*data, 0, 3);
2358 *needed = 0x4;
2359 return WERR_OK;
2362 if (!StrCaseCmp(value, "MinorVersion")) {
2363 *type = REG_DWORD;
2364 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2365 return WERR_NOMEM;
2366 SIVAL(*data, 0, 0);
2367 *needed = 0x4;
2368 return WERR_OK;
2371 /* REG_BINARY
2372 * uint32 size = 0x114
2373 * uint32 major = 5
2374 * uint32 minor = [0|1]
2375 * uint32 build = [2195|2600]
2376 * extra unicode string = e.g. "Service Pack 3"
2378 if (!StrCaseCmp(value, "OSVersion")) {
2379 *type = REG_BINARY;
2380 *needed = 0x114;
2382 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2383 return WERR_NOMEM;
2385 SIVAL(*data, 0, *needed); /* size */
2386 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2387 SIVAL(*data, 8, 0);
2388 SIVAL(*data, 12, 2195); /* build */
2390 /* leave extra string empty */
2392 return WERR_OK;
2396 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2397 const char *string="C:\\PRINTERS";
2398 *type = REG_SZ;
2399 *needed = 2*(strlen(string)+1);
2400 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2401 return WERR_NOMEM;
2402 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2404 /* it's done by hand ready to go on the wire */
2405 for (i=0; i<strlen(string); i++) {
2406 (*data)[2*i]=string[i];
2407 (*data)[2*i+1]='\0';
2409 return WERR_OK;
2412 if (!StrCaseCmp(value, "Architecture")) {
2413 const char *string="Windows NT x86";
2414 *type = REG_SZ;
2415 *needed = 2*(strlen(string)+1);
2416 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2417 return WERR_NOMEM;
2418 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2419 for (i=0; i<strlen(string); i++) {
2420 (*data)[2*i]=string[i];
2421 (*data)[2*i+1]='\0';
2423 return WERR_OK;
2426 if (!StrCaseCmp(value, "DsPresent")) {
2427 *type = REG_DWORD;
2428 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2429 return WERR_NOMEM;
2431 /* only show the publish check box if we are a
2432 memeber of a AD domain */
2434 if ( lp_security() == SEC_ADS )
2435 SIVAL(*data, 0, 0x01);
2436 else
2437 SIVAL(*data, 0, 0x00);
2439 *needed = 0x4;
2440 return WERR_OK;
2443 if (!StrCaseCmp(value, "DNSMachineName")) {
2444 const char *hostname = get_mydnsfullname();
2446 if (!hostname)
2447 return WERR_BADFILE;
2448 *type = REG_SZ;
2449 *needed = 2*(strlen(hostname)+1);
2450 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2451 return WERR_NOMEM;
2452 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2453 for (i=0; i<strlen(hostname); i++) {
2454 (*data)[2*i]=hostname[i];
2455 (*data)[2*i+1]='\0';
2457 return WERR_OK;
2461 return WERR_BADFILE;
2464 /********************************************************************
2465 * spoolss_getprinterdata
2466 ********************************************************************/
2468 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2470 POLICY_HND *handle = &q_u->handle;
2471 UNISTR2 *valuename = &q_u->valuename;
2472 uint32 in_size = q_u->size;
2473 uint32 *type = &r_u->type;
2474 uint32 *out_size = &r_u->size;
2475 uint8 **data = &r_u->data;
2476 uint32 *needed = &r_u->needed;
2477 WERROR status;
2478 fstring value;
2479 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2480 NT_PRINTER_INFO_LEVEL *printer = NULL;
2481 int snum = 0;
2484 * Reminder: when it's a string, the length is in BYTES
2485 * even if UNICODE is negociated.
2487 * JFM, 4/19/1999
2490 *out_size = in_size;
2492 /* in case of problem, return some default values */
2494 *needed = 0;
2495 *type = 0;
2497 DEBUG(4,("_spoolss_getprinterdata\n"));
2499 if ( !Printer ) {
2500 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2501 status = WERR_BADFID;
2502 goto done;
2505 unistr2_to_ascii(value, valuename, sizeof(value));
2507 if ( Printer->printer_type == SPLHND_SERVER )
2508 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2509 else
2511 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2512 status = WERR_BADFID;
2513 goto done;
2516 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2517 if ( !W_ERROR_IS_OK(status) )
2518 goto done;
2520 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2522 if ( strequal(value, "ChangeId") ) {
2523 *type = REG_DWORD;
2524 *needed = sizeof(uint32);
2525 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2526 status = WERR_NOMEM;
2527 goto done;
2529 SIVAL( *data, 0, printer->info_2->changeid );
2530 status = WERR_OK;
2532 else
2533 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2536 if (*needed > *out_size)
2537 status = WERR_MORE_DATA;
2539 done:
2540 if ( !W_ERROR_IS_OK(status) )
2542 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2544 /* reply this param doesn't exist */
2546 if ( *out_size ) {
2547 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2548 if ( printer )
2549 free_a_printer( &printer, 2 );
2550 return WERR_NOMEM;
2552 } else {
2553 *data = NULL;
2557 /* cleanup & exit */
2559 if ( printer )
2560 free_a_printer( &printer, 2 );
2562 return status;
2565 /*********************************************************
2566 Connect to the client machine.
2567 **********************************************************/
2569 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2570 struct sockaddr_storage *client_ss, const char *remote_machine)
2572 NTSTATUS ret;
2573 struct cli_state *the_cli;
2574 struct sockaddr_storage rm_addr;
2576 if ( is_zero_addr(client_ss) ) {
2577 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2578 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2579 return False;
2582 if (ismyaddr(&rm_addr)) {
2583 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2584 return False;
2586 } else {
2587 char addr[INET6_ADDRSTRLEN];
2588 rm_addr = *client_ss;
2589 print_sockaddr(addr, sizeof(addr), &rm_addr);
2590 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2591 addr));
2594 /* setup the connection */
2596 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2597 &rm_addr, 0, "IPC$", "IPC",
2598 "", /* username */
2599 "", /* domain */
2600 "", /* password */
2601 0, lp_client_signing(), NULL );
2603 if ( !NT_STATUS_IS_OK( ret ) ) {
2604 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2605 remote_machine ));
2606 return False;
2609 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2610 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2611 cli_shutdown(the_cli);
2612 return False;
2616 * Ok - we have an anonymous connection to the IPC$ share.
2617 * Now start the NT Domain stuff :-).
2620 ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2621 if (!NT_STATUS_IS_OK(ret)) {
2622 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2623 remote_machine, nt_errstr(ret)));
2624 cli_shutdown(the_cli);
2625 return False;
2628 return True;
2631 /***************************************************************************
2632 Connect to the client.
2633 ****************************************************************************/
2635 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2636 uint32 localprinter, uint32 type,
2637 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2639 WERROR result;
2642 * If it's the first connection, contact the client
2643 * and connect to the IPC$ share anonymously
2645 if (smb_connections==0) {
2646 fstring unix_printer;
2648 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2650 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2651 return False;
2653 messaging_register(smbd_messaging_context(), NULL,
2654 MSG_PRINTER_NOTIFY2,
2655 receive_notify2_message_list);
2656 /* Tell the connections db we're now interested in printer
2657 * notify messages. */
2658 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2662 * Tell the specific printing tdb we want messages for this printer
2663 * by registering our PID.
2666 if (!print_notify_register_pid(snum))
2667 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2669 smb_connections++;
2671 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe,
2672 talloc_tos(),
2673 printer,
2674 localprinter,
2675 type,
2676 handle);
2678 if (!W_ERROR_IS_OK(result))
2679 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2680 dos_errstr(result)));
2682 return (W_ERROR_IS_OK(result));
2685 /********************************************************************
2686 * _spoolss_rffpcnex
2687 * ReplyFindFirstPrinterChangeNotifyEx
2689 * before replying OK: status=0 a rpc call is made to the workstation
2690 * asking ReplyOpenPrinter
2692 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2693 * called from api_spoolss_rffpcnex
2694 ********************************************************************/
2696 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2698 POLICY_HND *handle = &q_u->handle;
2699 uint32 flags = q_u->flags;
2700 uint32 options = q_u->options;
2701 UNISTR2 *localmachine = &q_u->localmachine;
2702 uint32 printerlocal = q_u->printerlocal;
2703 int snum = -1;
2704 SPOOL_NOTIFY_OPTION *option = q_u->option;
2705 struct sockaddr_storage client_ss;
2707 /* store the notify value in the printer struct */
2709 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2711 if (!Printer) {
2712 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2713 return WERR_BADFID;
2716 Printer->notify.flags=flags;
2717 Printer->notify.options=options;
2718 Printer->notify.printerlocal=printerlocal;
2720 if (Printer->notify.option)
2721 free_spool_notify_option(&Printer->notify.option);
2723 Printer->notify.option=dup_spool_notify_option(option);
2725 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2726 sizeof(Printer->notify.localmachine));
2728 /* Connect to the client machine and send a ReplyOpenPrinter */
2730 if ( Printer->printer_type == SPLHND_SERVER)
2731 snum = -1;
2732 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2733 !get_printer_snum(p, handle, &snum, NULL) )
2734 return WERR_BADFID;
2736 if (!interpret_string_addr(&client_ss, p->client_address,
2737 AI_NUMERICHOST)) {
2738 return WERR_SERVER_UNAVAILABLE;
2741 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2742 Printer->notify.printerlocal, 1,
2743 &Printer->notify.client_hnd, &client_ss))
2744 return WERR_SERVER_UNAVAILABLE;
2746 Printer->notify.client_connected=True;
2748 return WERR_OK;
2751 /*******************************************************************
2752 * fill a notify_info_data with the servername
2753 ********************************************************************/
2755 void spoolss_notify_server_name(int snum,
2756 SPOOL_NOTIFY_INFO_DATA *data,
2757 print_queue_struct *queue,
2758 NT_PRINTER_INFO_LEVEL *printer,
2759 TALLOC_CTX *mem_ctx)
2761 smb_ucs2_t *temp = NULL;
2762 uint32 len;
2764 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2765 if (len == (uint32)-1) {
2766 len = 0;
2769 data->notify_data.data.length = len;
2770 if (len) {
2771 data->notify_data.data.string = (uint16 *)temp;
2772 } else {
2773 data->notify_data.data.string = NULL;
2777 /*******************************************************************
2778 * fill a notify_info_data with the printername (not including the servername).
2779 ********************************************************************/
2781 void spoolss_notify_printer_name(int snum,
2782 SPOOL_NOTIFY_INFO_DATA *data,
2783 print_queue_struct *queue,
2784 NT_PRINTER_INFO_LEVEL *printer,
2785 TALLOC_CTX *mem_ctx)
2787 smb_ucs2_t *temp = NULL;
2788 uint32 len;
2790 /* the notify name should not contain the \\server\ part */
2791 char *p = strrchr(printer->info_2->printername, '\\');
2793 if (!p) {
2794 p = printer->info_2->printername;
2795 } else {
2796 p++;
2799 len = rpcstr_push_talloc(mem_ctx, &temp, p);
2800 if (len == (uint32)-1) {
2801 len = 0;
2804 data->notify_data.data.length = len;
2805 if (len) {
2806 data->notify_data.data.string = (uint16 *)temp;
2807 } else {
2808 data->notify_data.data.string = NULL;
2812 /*******************************************************************
2813 * fill a notify_info_data with the servicename
2814 ********************************************************************/
2816 void spoolss_notify_share_name(int snum,
2817 SPOOL_NOTIFY_INFO_DATA *data,
2818 print_queue_struct *queue,
2819 NT_PRINTER_INFO_LEVEL *printer,
2820 TALLOC_CTX *mem_ctx)
2822 smb_ucs2_t *temp = NULL;
2823 uint32 len;
2825 len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2826 if (len == (uint32)-1) {
2827 len = 0;
2830 data->notify_data.data.length = len;
2831 if (len) {
2832 data->notify_data.data.string = (uint16 *)temp;
2833 } else {
2834 data->notify_data.data.string = NULL;
2839 /*******************************************************************
2840 * fill a notify_info_data with the port name
2841 ********************************************************************/
2843 void spoolss_notify_port_name(int snum,
2844 SPOOL_NOTIFY_INFO_DATA *data,
2845 print_queue_struct *queue,
2846 NT_PRINTER_INFO_LEVEL *printer,
2847 TALLOC_CTX *mem_ctx)
2849 smb_ucs2_t *temp = NULL;
2850 uint32 len;
2852 /* even if it's strange, that's consistant in all the code */
2854 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2855 if (len == (uint32)-1) {
2856 len = 0;
2859 data->notify_data.data.length = len;
2860 if (len) {
2861 data->notify_data.data.string = (uint16 *)temp;
2862 } else {
2863 data->notify_data.data.string = NULL;
2867 /*******************************************************************
2868 * fill a notify_info_data with the printername
2869 * but it doesn't exist, have to see what to do
2870 ********************************************************************/
2872 void spoolss_notify_driver_name(int snum,
2873 SPOOL_NOTIFY_INFO_DATA *data,
2874 print_queue_struct *queue,
2875 NT_PRINTER_INFO_LEVEL *printer,
2876 TALLOC_CTX *mem_ctx)
2878 smb_ucs2_t *temp = NULL;
2879 uint32 len;
2881 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2882 if (len == (uint32)-1) {
2883 len = 0;
2886 data->notify_data.data.length = len;
2887 if (len) {
2888 data->notify_data.data.string = (uint16 *)temp;
2889 } else {
2890 data->notify_data.data.string = NULL;
2894 /*******************************************************************
2895 * fill a notify_info_data with the comment
2896 ********************************************************************/
2898 void spoolss_notify_comment(int snum,
2899 SPOOL_NOTIFY_INFO_DATA *data,
2900 print_queue_struct *queue,
2901 NT_PRINTER_INFO_LEVEL *printer,
2902 TALLOC_CTX *mem_ctx)
2904 smb_ucs2_t *temp = NULL;
2905 uint32 len;
2907 if (*printer->info_2->comment == '\0')
2908 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2909 else
2910 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2912 if (len == (uint32)-1) {
2913 len = 0;
2915 data->notify_data.data.length = len;
2916 if (len) {
2917 data->notify_data.data.string = (uint16 *)temp;
2918 } else {
2919 data->notify_data.data.string = NULL;
2923 /*******************************************************************
2924 * fill a notify_info_data with the comment
2925 * location = "Room 1, floor 2, building 3"
2926 ********************************************************************/
2928 void spoolss_notify_location(int snum,
2929 SPOOL_NOTIFY_INFO_DATA *data,
2930 print_queue_struct *queue,
2931 NT_PRINTER_INFO_LEVEL *printer,
2932 TALLOC_CTX *mem_ctx)
2934 smb_ucs2_t *temp = NULL;
2935 uint32 len;
2937 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2938 if (len == (uint32)-1) {
2939 len = 0;
2942 data->notify_data.data.length = len;
2943 if (len) {
2944 data->notify_data.data.string = (uint16 *)temp;
2945 } else {
2946 data->notify_data.data.string = NULL;
2950 /*******************************************************************
2951 * fill a notify_info_data with the device mode
2952 * jfm:xxxx don't to it for know but that's a real problem !!!
2953 ********************************************************************/
2955 static void spoolss_notify_devmode(int snum,
2956 SPOOL_NOTIFY_INFO_DATA *data,
2957 print_queue_struct *queue,
2958 NT_PRINTER_INFO_LEVEL *printer,
2959 TALLOC_CTX *mem_ctx)
2961 /* for a dummy implementation we have to zero the fields */
2962 data->notify_data.data.length = 0;
2963 data->notify_data.data.string = NULL;
2966 /*******************************************************************
2967 * fill a notify_info_data with the separator file name
2968 ********************************************************************/
2970 void spoolss_notify_sepfile(int snum,
2971 SPOOL_NOTIFY_INFO_DATA *data,
2972 print_queue_struct *queue,
2973 NT_PRINTER_INFO_LEVEL *printer,
2974 TALLOC_CTX *mem_ctx)
2976 smb_ucs2_t *temp = NULL;
2977 uint32 len;
2979 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2980 if (len == (uint32)-1) {
2981 len = 0;
2984 data->notify_data.data.length = len;
2985 if (len) {
2986 data->notify_data.data.string = (uint16 *)temp;
2987 } else {
2988 data->notify_data.data.string = NULL;
2992 /*******************************************************************
2993 * fill a notify_info_data with the print processor
2994 * jfm:xxxx return always winprint to indicate we don't do anything to it
2995 ********************************************************************/
2997 void spoolss_notify_print_processor(int snum,
2998 SPOOL_NOTIFY_INFO_DATA *data,
2999 print_queue_struct *queue,
3000 NT_PRINTER_INFO_LEVEL *printer,
3001 TALLOC_CTX *mem_ctx)
3003 smb_ucs2_t *temp = NULL;
3004 uint32 len;
3006 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
3007 if (len == (uint32)-1) {
3008 len = 0;
3011 data->notify_data.data.length = len;
3012 if (len) {
3013 data->notify_data.data.string = (uint16 *)temp;
3014 } else {
3015 data->notify_data.data.string = NULL;
3019 /*******************************************************************
3020 * fill a notify_info_data with the print processor options
3021 * jfm:xxxx send an empty string
3022 ********************************************************************/
3024 void spoolss_notify_parameters(int snum,
3025 SPOOL_NOTIFY_INFO_DATA *data,
3026 print_queue_struct *queue,
3027 NT_PRINTER_INFO_LEVEL *printer,
3028 TALLOC_CTX *mem_ctx)
3030 smb_ucs2_t *temp = NULL;
3031 uint32 len;
3033 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3034 if (len == (uint32)-1) {
3035 len = 0;
3038 data->notify_data.data.length = len;
3039 if (len) {
3040 data->notify_data.data.string = (uint16 *)temp;
3041 } else {
3042 data->notify_data.data.string = NULL;
3046 /*******************************************************************
3047 * fill a notify_info_data with the data type
3048 * jfm:xxxx always send RAW as data type
3049 ********************************************************************/
3051 void spoolss_notify_datatype(int snum,
3052 SPOOL_NOTIFY_INFO_DATA *data,
3053 print_queue_struct *queue,
3054 NT_PRINTER_INFO_LEVEL *printer,
3055 TALLOC_CTX *mem_ctx)
3057 smb_ucs2_t *temp = NULL;
3058 uint32 len;
3060 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3061 if (len == (uint32)-1) {
3062 len = 0;
3065 data->notify_data.data.length = len;
3066 if (len) {
3067 data->notify_data.data.string = (uint16 *)temp;
3068 } else {
3069 data->notify_data.data.string = NULL;
3073 /*******************************************************************
3074 * fill a notify_info_data with the security descriptor
3075 * jfm:xxxx send an null pointer to say no security desc
3076 * have to implement security before !
3077 ********************************************************************/
3079 static void spoolss_notify_security_desc(int snum,
3080 SPOOL_NOTIFY_INFO_DATA *data,
3081 print_queue_struct *queue,
3082 NT_PRINTER_INFO_LEVEL *printer,
3083 TALLOC_CTX *mem_ctx)
3085 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3086 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3089 /*******************************************************************
3090 * fill a notify_info_data with the attributes
3091 * jfm:xxxx a samba printer is always shared
3092 ********************************************************************/
3094 void spoolss_notify_attributes(int snum,
3095 SPOOL_NOTIFY_INFO_DATA *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 data->notify_data.value[0] = printer->info_2->attributes;
3101 data->notify_data.value[1] = 0;
3104 /*******************************************************************
3105 * fill a notify_info_data with the priority
3106 ********************************************************************/
3108 static void spoolss_notify_priority(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 data->notify_data.value[0] = printer->info_2->priority;
3115 data->notify_data.value[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the default priority
3120 ********************************************************************/
3122 static void spoolss_notify_default_priority(int snum,
3123 SPOOL_NOTIFY_INFO_DATA *data,
3124 print_queue_struct *queue,
3125 NT_PRINTER_INFO_LEVEL *printer,
3126 TALLOC_CTX *mem_ctx)
3128 data->notify_data.value[0] = printer->info_2->default_priority;
3129 data->notify_data.value[1] = 0;
3132 /*******************************************************************
3133 * fill a notify_info_data with the start time
3134 ********************************************************************/
3136 static void spoolss_notify_start_time(int snum,
3137 SPOOL_NOTIFY_INFO_DATA *data,
3138 print_queue_struct *queue,
3139 NT_PRINTER_INFO_LEVEL *printer,
3140 TALLOC_CTX *mem_ctx)
3142 data->notify_data.value[0] = printer->info_2->starttime;
3143 data->notify_data.value[1] = 0;
3146 /*******************************************************************
3147 * fill a notify_info_data with the until time
3148 ********************************************************************/
3150 static void spoolss_notify_until_time(int snum,
3151 SPOOL_NOTIFY_INFO_DATA *data,
3152 print_queue_struct *queue,
3153 NT_PRINTER_INFO_LEVEL *printer,
3154 TALLOC_CTX *mem_ctx)
3156 data->notify_data.value[0] = printer->info_2->untiltime;
3157 data->notify_data.value[1] = 0;
3160 /*******************************************************************
3161 * fill a notify_info_data with the status
3162 ********************************************************************/
3164 static void spoolss_notify_status(int snum,
3165 SPOOL_NOTIFY_INFO_DATA *data,
3166 print_queue_struct *queue,
3167 NT_PRINTER_INFO_LEVEL *printer,
3168 TALLOC_CTX *mem_ctx)
3170 print_status_struct status;
3172 print_queue_length(snum, &status);
3173 data->notify_data.value[0]=(uint32) status.status;
3174 data->notify_data.value[1] = 0;
3177 /*******************************************************************
3178 * fill a notify_info_data with the number of jobs queued
3179 ********************************************************************/
3181 void spoolss_notify_cjobs(int snum,
3182 SPOOL_NOTIFY_INFO_DATA *data,
3183 print_queue_struct *queue,
3184 NT_PRINTER_INFO_LEVEL *printer,
3185 TALLOC_CTX *mem_ctx)
3187 data->notify_data.value[0] = print_queue_length(snum, NULL);
3188 data->notify_data.value[1] = 0;
3191 /*******************************************************************
3192 * fill a notify_info_data with the average ppm
3193 ********************************************************************/
3195 static void spoolss_notify_average_ppm(int snum,
3196 SPOOL_NOTIFY_INFO_DATA *data,
3197 print_queue_struct *queue,
3198 NT_PRINTER_INFO_LEVEL *printer,
3199 TALLOC_CTX *mem_ctx)
3201 /* always respond 8 pages per minutes */
3202 /* a little hard ! */
3203 data->notify_data.value[0] = printer->info_2->averageppm;
3204 data->notify_data.value[1] = 0;
3207 /*******************************************************************
3208 * fill a notify_info_data with username
3209 ********************************************************************/
3211 static void spoolss_notify_username(int snum,
3212 SPOOL_NOTIFY_INFO_DATA *data,
3213 print_queue_struct *queue,
3214 NT_PRINTER_INFO_LEVEL *printer,
3215 TALLOC_CTX *mem_ctx)
3217 smb_ucs2_t *temp = NULL;
3218 uint32 len;
3220 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3221 if (len == (uint32)-1) {
3222 len = 0;
3225 data->notify_data.data.length = len;
3226 if (len) {
3227 data->notify_data.data.string = (uint16 *)temp;
3228 } else {
3229 data->notify_data.data.string = NULL;
3233 /*******************************************************************
3234 * fill a notify_info_data with job status
3235 ********************************************************************/
3237 static void spoolss_notify_job_status(int snum,
3238 SPOOL_NOTIFY_INFO_DATA *data,
3239 print_queue_struct *queue,
3240 NT_PRINTER_INFO_LEVEL *printer,
3241 TALLOC_CTX *mem_ctx)
3243 data->notify_data.value[0]=nt_printj_status(queue->status);
3244 data->notify_data.value[1] = 0;
3247 /*******************************************************************
3248 * fill a notify_info_data with job name
3249 ********************************************************************/
3251 static void spoolss_notify_job_name(int snum,
3252 SPOOL_NOTIFY_INFO_DATA *data,
3253 print_queue_struct *queue,
3254 NT_PRINTER_INFO_LEVEL *printer,
3255 TALLOC_CTX *mem_ctx)
3257 smb_ucs2_t *temp = NULL;
3258 uint32 len;
3260 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3261 if (len == (uint32)-1) {
3262 len = 0;
3265 data->notify_data.data.length = len;
3266 if (len) {
3267 data->notify_data.data.string = (uint16 *)temp;
3268 } else {
3269 data->notify_data.data.string = NULL;
3273 /*******************************************************************
3274 * fill a notify_info_data with job status
3275 ********************************************************************/
3277 static void spoolss_notify_job_status_string(int snum,
3278 SPOOL_NOTIFY_INFO_DATA *data,
3279 print_queue_struct *queue,
3280 NT_PRINTER_INFO_LEVEL *printer,
3281 TALLOC_CTX *mem_ctx)
3284 * Now we're returning job status codes we just return a "" here. JRA.
3287 const char *p = "";
3288 smb_ucs2_t *temp = NULL;
3289 uint32 len;
3291 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3292 p = "unknown";
3294 switch (queue->status) {
3295 case LPQ_QUEUED:
3296 p = "Queued";
3297 break;
3298 case LPQ_PAUSED:
3299 p = ""; /* NT provides the paused string */
3300 break;
3301 case LPQ_SPOOLING:
3302 p = "Spooling";
3303 break;
3304 case LPQ_PRINTING:
3305 p = "Printing";
3306 break;
3308 #endif /* NO LONGER NEEDED. */
3310 len = rpcstr_push_talloc(mem_ctx, &temp, p);
3311 if (len == (uint32)-1) {
3312 len = 0;
3315 data->notify_data.data.length = len;
3316 if (len) {
3317 data->notify_data.data.string = (uint16 *)temp;
3318 } else {
3319 data->notify_data.data.string = NULL;
3323 /*******************************************************************
3324 * fill a notify_info_data with job time
3325 ********************************************************************/
3327 static void spoolss_notify_job_time(int snum,
3328 SPOOL_NOTIFY_INFO_DATA *data,
3329 print_queue_struct *queue,
3330 NT_PRINTER_INFO_LEVEL *printer,
3331 TALLOC_CTX *mem_ctx)
3333 data->notify_data.value[0]=0x0;
3334 data->notify_data.value[1]=0;
3337 /*******************************************************************
3338 * fill a notify_info_data with job size
3339 ********************************************************************/
3341 static void spoolss_notify_job_size(int snum,
3342 SPOOL_NOTIFY_INFO_DATA *data,
3343 print_queue_struct *queue,
3344 NT_PRINTER_INFO_LEVEL *printer,
3345 TALLOC_CTX *mem_ctx)
3347 data->notify_data.value[0]=queue->size;
3348 data->notify_data.value[1]=0;
3351 /*******************************************************************
3352 * fill a notify_info_data with page info
3353 ********************************************************************/
3354 static void spoolss_notify_total_pages(int snum,
3355 SPOOL_NOTIFY_INFO_DATA *data,
3356 print_queue_struct *queue,
3357 NT_PRINTER_INFO_LEVEL *printer,
3358 TALLOC_CTX *mem_ctx)
3360 data->notify_data.value[0]=queue->page_count;
3361 data->notify_data.value[1]=0;
3364 /*******************************************************************
3365 * fill a notify_info_data with pages printed info.
3366 ********************************************************************/
3367 static void spoolss_notify_pages_printed(int snum,
3368 SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer,
3371 TALLOC_CTX *mem_ctx)
3373 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3374 data->notify_data.value[1]=0;
3377 /*******************************************************************
3378 Fill a notify_info_data with job position.
3379 ********************************************************************/
3381 static void spoolss_notify_job_position(int snum,
3382 SPOOL_NOTIFY_INFO_DATA *data,
3383 print_queue_struct *queue,
3384 NT_PRINTER_INFO_LEVEL *printer,
3385 TALLOC_CTX *mem_ctx)
3387 data->notify_data.value[0]=queue->job;
3388 data->notify_data.value[1]=0;
3391 /*******************************************************************
3392 Fill a notify_info_data with submitted time.
3393 ********************************************************************/
3395 static void spoolss_notify_submitted_time(int snum,
3396 SPOOL_NOTIFY_INFO_DATA *data,
3397 print_queue_struct *queue,
3398 NT_PRINTER_INFO_LEVEL *printer,
3399 TALLOC_CTX *mem_ctx)
3401 struct tm *t;
3402 uint32 len;
3403 SYSTEMTIME st;
3404 char *p;
3406 t=gmtime(&queue->time);
3408 len = sizeof(SYSTEMTIME);
3410 data->notify_data.data.length = len;
3411 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3413 if (!data->notify_data.data.string) {
3414 data->notify_data.data.length = 0;
3415 return;
3418 make_systemtime(&st, t);
3421 * Systemtime must be linearized as a set of UINT16's.
3422 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3425 p = (char *)data->notify_data.data.string;
3426 SSVAL(p, 0, st.year);
3427 SSVAL(p, 2, st.month);
3428 SSVAL(p, 4, st.dayofweek);
3429 SSVAL(p, 6, st.day);
3430 SSVAL(p, 8, st.hour);
3431 SSVAL(p, 10, st.minute);
3432 SSVAL(p, 12, st.second);
3433 SSVAL(p, 14, st.milliseconds);
3436 struct s_notify_info_data_table
3438 uint16 type;
3439 uint16 field;
3440 const char *name;
3441 uint32 size;
3442 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3443 print_queue_struct *queue,
3444 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3447 /* A table describing the various print notification constants and
3448 whether the notification data is a pointer to a variable sized
3449 buffer, a one value uint32 or a two value uint32. */
3451 static const struct s_notify_info_data_table notify_info_data_table[] =
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3502 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3505 /*******************************************************************
3506 Return the size of info_data structure.
3507 ********************************************************************/
3509 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3511 int i=0;
3513 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3514 if ( (notify_info_data_table[i].type == type)
3515 && (notify_info_data_table[i].field == field) ) {
3516 switch(notify_info_data_table[i].size) {
3517 case NOTIFY_ONE_VALUE:
3518 case NOTIFY_TWO_VALUE:
3519 return 1;
3520 case NOTIFY_STRING:
3521 return 2;
3523 /* The only pointer notify data I have seen on
3524 the wire is the submitted time and this has
3525 the notify size set to 4. -tpot */
3527 case NOTIFY_POINTER:
3528 return 4;
3530 case NOTIFY_SECDESC:
3531 return 5;
3536 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3538 return 0;
3541 /*******************************************************************
3542 Return the type of notify_info_data.
3543 ********************************************************************/
3545 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3547 uint32 i=0;
3549 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3550 if (notify_info_data_table[i].type == type &&
3551 notify_info_data_table[i].field == field)
3552 return notify_info_data_table[i].size;
3555 return 0;
3558 /****************************************************************************
3559 ****************************************************************************/
3561 static bool search_notify(uint16 type, uint16 field, int *value)
3563 int i;
3565 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3566 if (notify_info_data_table[i].type == type &&
3567 notify_info_data_table[i].field == field &&
3568 notify_info_data_table[i].fn != NULL) {
3569 *value = i;
3570 return True;
3574 return False;
3577 /****************************************************************************
3578 ****************************************************************************/
3580 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3582 info_data->type = type;
3583 info_data->field = field;
3584 info_data->reserved = 0;
3586 info_data->size = size_of_notify_info_data(type, field);
3587 info_data->enc_type = type_of_notify_info_data(type, field);
3589 info_data->id = id;
3592 /*******************************************************************
3594 * fill a notify_info struct with info asked
3596 ********************************************************************/
3598 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3599 snum, SPOOL_NOTIFY_OPTION_TYPE
3600 *option_type, uint32 id,
3601 TALLOC_CTX *mem_ctx)
3603 int field_num,j;
3604 uint16 type;
3605 uint16 field;
3607 SPOOL_NOTIFY_INFO_DATA *current_data;
3608 NT_PRINTER_INFO_LEVEL *printer = NULL;
3609 print_queue_struct *queue=NULL;
3611 type=option_type->type;
3613 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3614 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3615 option_type->count, lp_servicename(snum)));
3617 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3618 return False;
3620 for(field_num=0; field_num<option_type->count; field_num++) {
3621 field = option_type->fields[field_num];
3623 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3625 if (!search_notify(type, field, &j) )
3626 continue;
3628 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3629 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3630 free_a_printer(&printer, 2);
3631 return False;
3634 current_data = &info->data[info->count];
3636 construct_info_data(current_data, type, field, id);
3638 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3639 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3641 notify_info_data_table[j].fn(snum, current_data, queue,
3642 printer, mem_ctx);
3644 info->count++;
3647 free_a_printer(&printer, 2);
3648 return True;
3651 /*******************************************************************
3653 * fill a notify_info struct with info asked
3655 ********************************************************************/
3657 static bool construct_notify_jobs_info(print_queue_struct *queue,
3658 SPOOL_NOTIFY_INFO *info,
3659 NT_PRINTER_INFO_LEVEL *printer,
3660 int snum, SPOOL_NOTIFY_OPTION_TYPE
3661 *option_type, uint32 id,
3662 TALLOC_CTX *mem_ctx)
3664 int field_num,j;
3665 uint16 type;
3666 uint16 field;
3668 SPOOL_NOTIFY_INFO_DATA *current_data;
3670 DEBUG(4,("construct_notify_jobs_info\n"));
3672 type = option_type->type;
3674 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3675 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3676 option_type->count));
3678 for(field_num=0; field_num<option_type->count; field_num++) {
3679 field = option_type->fields[field_num];
3681 if (!search_notify(type, field, &j) )
3682 continue;
3684 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3685 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3686 return False;
3689 current_data=&(info->data[info->count]);
3691 construct_info_data(current_data, type, field, id);
3692 notify_info_data_table[j].fn(snum, current_data, queue,
3693 printer, mem_ctx);
3694 info->count++;
3697 return True;
3701 * JFM: The enumeration is not that simple, it's even non obvious.
3703 * let's take an example: I want to monitor the PRINTER SERVER for
3704 * the printer's name and the number of jobs currently queued.
3705 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3706 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3708 * I have 3 printers on the back of my server.
3710 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3711 * structures.
3712 * Number Data Id
3713 * 1 printer 1 name 1
3714 * 2 printer 1 cjob 1
3715 * 3 printer 2 name 2
3716 * 4 printer 2 cjob 2
3717 * 5 printer 3 name 3
3718 * 6 printer 3 name 3
3720 * that's the print server case, the printer case is even worse.
3723 /*******************************************************************
3725 * enumerate all printers on the printserver
3726 * fill a notify_info struct with info asked
3728 ********************************************************************/
3730 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3731 SPOOL_NOTIFY_INFO *info,
3732 TALLOC_CTX *mem_ctx)
3734 int snum;
3735 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3736 int n_services=lp_numservices();
3737 int i;
3738 SPOOL_NOTIFY_OPTION *option;
3739 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3741 DEBUG(4,("printserver_notify_info\n"));
3743 if (!Printer)
3744 return WERR_BADFID;
3746 option=Printer->notify.option;
3747 info->version=2;
3748 info->data=NULL;
3749 info->count=0;
3751 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3752 sending a ffpcn() request first */
3754 if ( !option )
3755 return WERR_BADFID;
3757 for (i=0; i<option->count; i++) {
3758 option_type=&(option->ctr.type[i]);
3760 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3761 continue;
3763 for (snum=0; snum<n_services; snum++)
3765 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3766 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3770 #if 0
3772 * Debugging information, don't delete.
3775 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3776 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3777 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3779 for (i=0; i<info->count; i++) {
3780 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3781 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3782 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3784 #endif
3786 return WERR_OK;
3789 /*******************************************************************
3791 * fill a notify_info struct with info asked
3793 ********************************************************************/
3795 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3796 TALLOC_CTX *mem_ctx)
3798 int snum;
3799 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3800 int i;
3801 uint32 id;
3802 SPOOL_NOTIFY_OPTION *option;
3803 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3804 int count,j;
3805 print_queue_struct *queue=NULL;
3806 print_status_struct status;
3808 DEBUG(4,("printer_notify_info\n"));
3810 if (!Printer)
3811 return WERR_BADFID;
3813 option=Printer->notify.option;
3814 id = 0x0;
3815 info->version=2;
3816 info->data=NULL;
3817 info->count=0;
3819 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3820 sending a ffpcn() request first */
3822 if ( !option )
3823 return WERR_BADFID;
3825 get_printer_snum(p, hnd, &snum, NULL);
3827 for (i=0; i<option->count; i++) {
3828 option_type=&option->ctr.type[i];
3830 switch ( option_type->type ) {
3831 case PRINTER_NOTIFY_TYPE:
3832 if(construct_notify_printer_info(Printer, info, snum,
3833 option_type, id,
3834 mem_ctx))
3835 id--;
3836 break;
3838 case JOB_NOTIFY_TYPE: {
3839 NT_PRINTER_INFO_LEVEL *printer = NULL;
3841 count = print_queue_status(snum, &queue, &status);
3843 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3844 goto done;
3846 for (j=0; j<count; j++) {
3847 construct_notify_jobs_info(&queue[j], info,
3848 printer, snum,
3849 option_type,
3850 queue[j].job,
3851 mem_ctx);
3854 free_a_printer(&printer, 2);
3856 done:
3857 SAFE_FREE(queue);
3858 break;
3864 * Debugging information, don't delete.
3867 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3868 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3869 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3871 for (i=0; i<info->count; i++) {
3872 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3873 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3874 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3877 return WERR_OK;
3880 /********************************************************************
3881 * spoolss_rfnpcnex
3882 ********************************************************************/
3884 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3886 POLICY_HND *handle = &q_u->handle;
3887 SPOOL_NOTIFY_INFO *info = &r_u->info;
3889 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3890 WERROR result = WERR_BADFID;
3892 /* we always have a NOTIFY_INFO struct */
3893 r_u->info_ptr=0x1;
3895 if (!Printer) {
3896 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3897 OUR_HANDLE(handle)));
3898 goto done;
3901 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3904 * We are now using the change value, and
3905 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3906 * I don't have a global notification system, I'm sending back all the
3907 * informations even when _NOTHING_ has changed.
3910 /* We need to keep track of the change value to send back in
3911 RRPCN replies otherwise our updates are ignored. */
3913 Printer->notify.fnpcn = True;
3915 if (Printer->notify.client_connected) {
3916 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3917 Printer->notify.change = q_u->change;
3920 /* just ignore the SPOOL_NOTIFY_OPTION */
3922 switch (Printer->printer_type) {
3923 case SPLHND_SERVER:
3924 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3925 break;
3927 case SPLHND_PRINTER:
3928 result = printer_notify_info(p, handle, info, p->mem_ctx);
3929 break;
3932 Printer->notify.fnpcn = False;
3934 done:
3935 return result;
3938 /********************************************************************
3939 * construct_printer_info_0
3940 * fill a printer_info_0 struct
3941 ********************************************************************/
3943 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3945 char *chaine = NULL;
3946 int count;
3947 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3948 counter_printer_0 *session_counter;
3949 uint32 global_counter;
3950 struct tm *t;
3951 time_t setuptime;
3952 print_status_struct status;
3953 TALLOC_CTX *ctx = talloc_tos();
3955 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3956 return False;
3958 init_unistr(&printer->printername, ntprinter->info_2->printername);
3960 chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3961 if (!chaine) {
3962 free_a_printer(&ntprinter,2);
3963 return false;
3966 count = print_queue_length(snum, &status);
3968 /* check if we already have a counter for this printer */
3969 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3970 if (session_counter->snum == snum)
3971 break;
3974 init_unistr(&printer->servername, chaine);
3976 /* it's the first time, add it to the list */
3977 if (session_counter==NULL) {
3978 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3979 free_a_printer(&ntprinter, 2);
3980 return False;
3982 ZERO_STRUCTP(session_counter);
3983 session_counter->snum=snum;
3984 session_counter->counter=0;
3985 DLIST_ADD(counter_list, session_counter);
3988 /* increment it */
3989 session_counter->counter++;
3991 /* JFM:
3992 * the global_counter should be stored in a TDB as it's common to all the clients
3993 * and should be zeroed on samba startup
3995 global_counter=session_counter->counter;
3996 printer->cjobs = count;
3997 printer->total_jobs = 0;
3998 printer->total_bytes = 0;
4000 setuptime = (time_t)ntprinter->info_2->setuptime;
4001 t=gmtime(&setuptime);
4003 printer->year = t->tm_year+1900;
4004 printer->month = t->tm_mon+1;
4005 printer->dayofweek = t->tm_wday;
4006 printer->day = t->tm_mday;
4007 printer->hour = t->tm_hour;
4008 printer->minute = t->tm_min;
4009 printer->second = t->tm_sec;
4010 printer->milliseconds = 0;
4012 printer->global_counter = global_counter;
4013 printer->total_pages = 0;
4015 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4016 printer->major_version = 0x0005; /* NT 5 */
4017 printer->build_version = 0x0893; /* build 2195 */
4019 printer->unknown7 = 0x1;
4020 printer->unknown8 = 0x0;
4021 printer->unknown9 = 0x0;
4022 printer->session_counter = session_counter->counter;
4023 printer->unknown11 = 0x0;
4024 printer->printer_errors = 0x0; /* number of print failure */
4025 printer->unknown13 = 0x0;
4026 printer->unknown14 = 0x1;
4027 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4028 printer->unknown16 = 0x0;
4029 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4030 printer->unknown18 = 0x0;
4031 printer->status = nt_printq_status(status.status);
4032 printer->unknown20 = 0x0;
4033 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4034 printer->unknown22 = 0x0;
4035 printer->unknown23 = 0x6; /* 6 ???*/
4036 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4037 printer->unknown25 = 0;
4038 printer->unknown26 = 0;
4039 printer->unknown27 = 0;
4040 printer->unknown28 = 0;
4041 printer->unknown29 = 0;
4043 free_a_printer(&ntprinter,2);
4044 return (True);
4047 /********************************************************************
4048 * construct_printer_info_1
4049 * fill a printer_info_1 struct
4050 ********************************************************************/
4051 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4053 char *chaine = NULL;
4054 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4055 TALLOC_CTX *ctx = talloc_tos();
4057 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4058 return false;
4060 printer->flags=flags;
4062 if (*ntprinter->info_2->comment == '\0') {
4063 init_unistr(&printer->comment, lp_comment(snum));
4064 chaine = talloc_asprintf(ctx,
4065 "%s,%s,%s", ntprinter->info_2->printername,
4066 ntprinter->info_2->drivername, lp_comment(snum));
4068 else {
4069 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4070 chaine = talloc_asprintf(ctx,
4071 "%s,%s,%s", ntprinter->info_2->printername,
4072 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4075 if (!chaine) {
4076 free_a_printer(&ntprinter,2);
4077 return false;
4080 init_unistr(&printer->description, chaine);
4081 init_unistr(&printer->name, ntprinter->info_2->printername);
4083 free_a_printer(&ntprinter,2);
4085 return True;
4088 /****************************************************************************
4089 Free a DEVMODE struct.
4090 ****************************************************************************/
4092 static void free_dev_mode(DEVICEMODE *dev)
4094 if (dev == NULL)
4095 return;
4097 SAFE_FREE(dev->dev_private);
4098 SAFE_FREE(dev);
4102 /****************************************************************************
4103 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4104 should be valid upon entry
4105 ****************************************************************************/
4107 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4109 if ( !devmode || !ntdevmode )
4110 return False;
4112 init_unistr(&devmode->devicename, ntdevmode->devicename);
4114 init_unistr(&devmode->formname, ntdevmode->formname);
4116 devmode->specversion = ntdevmode->specversion;
4117 devmode->driverversion = ntdevmode->driverversion;
4118 devmode->size = ntdevmode->size;
4119 devmode->driverextra = ntdevmode->driverextra;
4120 devmode->fields = ntdevmode->fields;
4122 devmode->orientation = ntdevmode->orientation;
4123 devmode->papersize = ntdevmode->papersize;
4124 devmode->paperlength = ntdevmode->paperlength;
4125 devmode->paperwidth = ntdevmode->paperwidth;
4126 devmode->scale = ntdevmode->scale;
4127 devmode->copies = ntdevmode->copies;
4128 devmode->defaultsource = ntdevmode->defaultsource;
4129 devmode->printquality = ntdevmode->printquality;
4130 devmode->color = ntdevmode->color;
4131 devmode->duplex = ntdevmode->duplex;
4132 devmode->yresolution = ntdevmode->yresolution;
4133 devmode->ttoption = ntdevmode->ttoption;
4134 devmode->collate = ntdevmode->collate;
4135 devmode->icmmethod = ntdevmode->icmmethod;
4136 devmode->icmintent = ntdevmode->icmintent;
4137 devmode->mediatype = ntdevmode->mediatype;
4138 devmode->dithertype = ntdevmode->dithertype;
4140 if (ntdevmode->nt_dev_private != NULL) {
4141 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4142 return False;
4145 return True;
4148 /****************************************************************************
4149 Create a DEVMODE struct. Returns malloced memory.
4150 ****************************************************************************/
4152 DEVICEMODE *construct_dev_mode(const char *servicename)
4154 NT_PRINTER_INFO_LEVEL *printer = NULL;
4155 DEVICEMODE *devmode = NULL;
4157 DEBUG(7,("construct_dev_mode\n"));
4159 DEBUGADD(8,("getting printer characteristics\n"));
4161 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4162 return NULL;
4164 if ( !printer->info_2->devmode ) {
4165 DEBUG(5, ("BONG! There was no device mode!\n"));
4166 goto done;
4169 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4170 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4171 goto done;
4174 ZERO_STRUCTP(devmode);
4176 DEBUGADD(8,("loading DEVICEMODE\n"));
4178 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4179 free_dev_mode( devmode );
4180 devmode = NULL;
4183 done:
4184 free_a_printer(&printer,2);
4186 return devmode;
4189 /********************************************************************
4190 * construct_printer_info_2
4191 * fill a printer_info_2 struct
4192 ********************************************************************/
4194 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4196 int count;
4197 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4199 print_status_struct status;
4201 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4202 return False;
4204 count = print_queue_length(snum, &status);
4206 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4207 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4208 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4209 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4210 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4212 if (*ntprinter->info_2->comment == '\0')
4213 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4214 else
4215 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4217 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4218 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4219 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4220 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4221 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4223 printer->attributes = ntprinter->info_2->attributes;
4225 printer->priority = ntprinter->info_2->priority; /* priority */
4226 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4227 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4228 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4229 printer->status = nt_printq_status(status.status); /* status */
4230 printer->cjobs = count; /* jobs */
4231 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4233 if ( !(printer->devmode = construct_dev_mode(
4234 lp_const_servicename(snum))) )
4235 DEBUG(8, ("Returning NULL Devicemode!\n"));
4237 printer->secdesc = NULL;
4239 if ( ntprinter->info_2->secdesc_buf
4240 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4242 /* don't use talloc_steal() here unless you do a deep steal of all
4243 the SEC_DESC members */
4245 printer->secdesc = dup_sec_desc( talloc_tos(),
4246 ntprinter->info_2->secdesc_buf->sd );
4249 free_a_printer(&ntprinter, 2);
4251 return True;
4254 /********************************************************************
4255 * construct_printer_info_3
4256 * fill a printer_info_3 struct
4257 ********************************************************************/
4259 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4261 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4262 PRINTER_INFO_3 *printer = NULL;
4264 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4265 return False;
4267 *pp_printer = NULL;
4268 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4269 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4270 free_a_printer(&ntprinter, 2);
4271 return False;
4274 ZERO_STRUCTP(printer);
4276 /* These are the components of the SD we are returning. */
4278 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4279 /* don't use talloc_steal() here unless you do a deep steal of all
4280 the SEC_DESC members */
4282 printer->secdesc = dup_sec_desc( talloc_tos(),
4283 ntprinter->info_2->secdesc_buf->sd );
4286 free_a_printer(&ntprinter, 2);
4288 *pp_printer = printer;
4289 return True;
4292 /********************************************************************
4293 * construct_printer_info_4
4294 * fill a printer_info_4 struct
4295 ********************************************************************/
4297 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4299 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4301 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4302 return False;
4304 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4305 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4306 printer->attributes = ntprinter->info_2->attributes;
4308 free_a_printer(&ntprinter, 2);
4309 return True;
4312 /********************************************************************
4313 * construct_printer_info_5
4314 * fill a printer_info_5 struct
4315 ********************************************************************/
4317 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4319 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4321 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4322 return False;
4324 init_unistr(&printer->printername, ntprinter->info_2->printername);
4325 init_unistr(&printer->portname, ntprinter->info_2->portname);
4326 printer->attributes = ntprinter->info_2->attributes;
4328 /* these two are not used by NT+ according to MSDN */
4330 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4331 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4333 free_a_printer(&ntprinter, 2);
4335 return True;
4338 /********************************************************************
4339 * construct_printer_info_6
4340 * fill a printer_info_6 struct
4341 ********************************************************************/
4343 static bool construct_printer_info_6(Printer_entry *print_hnd,
4344 PRINTER_INFO_6 *printer,
4345 int snum)
4347 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4348 int count;
4349 print_status_struct status;
4351 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4352 lp_const_servicename(snum))))
4353 return False;
4355 count = print_queue_length(snum, &status);
4357 printer->status = nt_printq_status(status.status);
4359 free_a_printer(&ntprinter, 2);
4361 return True;
4364 /********************************************************************
4365 * construct_printer_info_7
4366 * fill a printer_info_7 struct
4367 ********************************************************************/
4369 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4371 char *guid_str = NULL;
4372 struct GUID guid;
4374 if (is_printer_published(print_hnd, snum, &guid)) {
4375 if (asprintf(&guid_str, "{%s}",
4376 smb_uuid_string(talloc_tos(), guid)) == -1) {
4377 return false;
4379 strupper_m(guid_str);
4380 init_unistr(&printer->guid, guid_str);
4381 SAFE_FREE(guid_str);
4382 printer->action = SPOOL_DS_PUBLISH;
4383 } else {
4384 init_unistr(&printer->guid, "");
4385 printer->action = SPOOL_DS_UNPUBLISH;
4388 return True;
4391 /********************************************************************
4392 Spoolss_enumprinters.
4393 ********************************************************************/
4395 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4397 int snum;
4398 int i;
4399 int n_services=lp_numservices();
4400 PRINTER_INFO_1 *printers=NULL;
4401 PRINTER_INFO_1 current_prt;
4402 WERROR result = WERR_OK;
4404 DEBUG(4,("enum_all_printers_info_1\n"));
4406 for (snum=0; snum<n_services; snum++) {
4407 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4408 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4410 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4411 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4412 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4413 *returned=0;
4414 return WERR_NOMEM;
4416 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4418 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4419 (*returned)++;
4424 /* check the required size. */
4425 for (i=0; i<*returned; i++)
4426 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4428 if (*needed > offered) {
4429 result = WERR_INSUFFICIENT_BUFFER;
4430 goto out;
4433 if (!rpcbuf_alloc_size(buffer, *needed)) {
4434 result = WERR_NOMEM;
4435 goto out;
4438 /* fill the buffer with the structures */
4439 for (i=0; i<*returned; i++)
4440 smb_io_printer_info_1("", buffer, &printers[i], 0);
4442 out:
4443 /* clear memory */
4445 SAFE_FREE(printers);
4447 if ( !W_ERROR_IS_OK(result) )
4448 *returned = 0;
4450 return result;
4453 /********************************************************************
4454 enum_all_printers_info_1_local.
4455 *********************************************************************/
4457 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4459 DEBUG(4,("enum_all_printers_info_1_local\n"));
4461 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4464 /********************************************************************
4465 enum_all_printers_info_1_name.
4466 *********************************************************************/
4468 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4470 char *s = name;
4472 DEBUG(4,("enum_all_printers_info_1_name\n"));
4474 if ((name[0] == '\\') && (name[1] == '\\'))
4475 s = name + 2;
4477 if (is_myname_or_ipaddr(s)) {
4478 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4480 else
4481 return WERR_INVALID_NAME;
4484 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4485 /********************************************************************
4486 enum_all_printers_info_1_remote.
4487 *********************************************************************/
4489 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4491 PRINTER_INFO_1 *printer;
4492 fstring printername;
4493 fstring desc;
4494 fstring comment;
4495 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4496 WERROR result = WERR_OK;
4498 /* JFM: currently it's more a place holder than anything else.
4499 * In the spooler world there is a notion of server registration.
4500 * the print servers are registered on the PDC (in the same domain)
4502 * We should have a TDB here. The registration is done thru an
4503 * undocumented RPC call.
4506 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4507 return WERR_NOMEM;
4509 *returned=1;
4511 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4512 slprintf(desc, sizeof(desc)-1,"%s", name);
4513 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4515 init_unistr(&printer->description, desc);
4516 init_unistr(&printer->name, printername);
4517 init_unistr(&printer->comment, comment);
4518 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4520 /* check the required size. */
4521 *needed += spoolss_size_printer_info_1(printer);
4523 if (*needed > offered) {
4524 result = WERR_INSUFFICIENT_BUFFER;
4525 goto out;
4528 if (!rpcbuf_alloc_size(buffer, *needed)) {
4529 result = WERR_NOMEM;
4530 goto out;
4533 /* fill the buffer with the structures */
4534 smb_io_printer_info_1("", buffer, printer, 0);
4536 out:
4537 /* clear memory */
4538 SAFE_FREE(printer);
4540 if ( !W_ERROR_IS_OK(result) )
4541 *returned = 0;
4543 return result;
4546 #endif
4548 /********************************************************************
4549 enum_all_printers_info_1_network.
4550 *********************************************************************/
4552 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4554 char *s = name;
4556 DEBUG(4,("enum_all_printers_info_1_network\n"));
4558 /* If we respond to a enum_printers level 1 on our name with flags
4559 set to PRINTER_ENUM_REMOTE with a list of printers then these
4560 printers incorrectly appear in the APW browse list.
4561 Specifically the printers for the server appear at the workgroup
4562 level where all the other servers in the domain are
4563 listed. Windows responds to this call with a
4564 WERR_CAN_NOT_COMPLETE so we should do the same. */
4566 if (name[0] == '\\' && name[1] == '\\')
4567 s = name + 2;
4569 if (is_myname_or_ipaddr(s))
4570 return WERR_CAN_NOT_COMPLETE;
4572 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4575 /********************************************************************
4576 * api_spoolss_enumprinters
4578 * called from api_spoolss_enumprinters (see this to understand)
4579 ********************************************************************/
4581 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4583 int snum;
4584 int i;
4585 int n_services=lp_numservices();
4586 PRINTER_INFO_2 *printers=NULL;
4587 PRINTER_INFO_2 current_prt;
4588 WERROR result = WERR_OK;
4590 *returned = 0;
4592 for (snum=0; snum<n_services; snum++) {
4593 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4594 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4596 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4597 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4598 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4599 *returned = 0;
4600 return WERR_NOMEM;
4603 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4605 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4607 (*returned)++;
4612 /* check the required size. */
4613 for (i=0; i<*returned; i++)
4614 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4616 if (*needed > offered) {
4617 result = WERR_INSUFFICIENT_BUFFER;
4618 goto out;
4621 if (!rpcbuf_alloc_size(buffer, *needed)) {
4622 result = WERR_NOMEM;
4623 goto out;
4626 /* fill the buffer with the structures */
4627 for (i=0; i<*returned; i++)
4628 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4630 out:
4631 /* clear memory */
4633 for (i=0; i<*returned; i++)
4634 free_devmode(printers[i].devmode);
4636 SAFE_FREE(printers);
4638 if ( !W_ERROR_IS_OK(result) )
4639 *returned = 0;
4641 return result;
4644 /********************************************************************
4645 * handle enumeration of printers at level 1
4646 ********************************************************************/
4648 static WERROR enumprinters_level1( uint32 flags, fstring name,
4649 RPC_BUFFER *buffer, uint32 offered,
4650 uint32 *needed, uint32 *returned)
4652 /* Not all the flags are equals */
4654 if (flags & PRINTER_ENUM_LOCAL)
4655 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4657 if (flags & PRINTER_ENUM_NAME)
4658 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4660 #if 0 /* JERRY - disabled for now */
4661 if (flags & PRINTER_ENUM_REMOTE)
4662 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4663 #endif
4665 if (flags & PRINTER_ENUM_NETWORK)
4666 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4668 return WERR_OK; /* NT4sp5 does that */
4671 /********************************************************************
4672 * handle enumeration of printers at level 2
4673 ********************************************************************/
4675 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4676 RPC_BUFFER *buffer, uint32 offered,
4677 uint32 *needed, uint32 *returned)
4679 if (flags & PRINTER_ENUM_LOCAL) {
4680 return enum_all_printers_info_2(buffer, offered, needed, returned);
4683 if (flags & PRINTER_ENUM_NAME) {
4684 if (is_myname_or_ipaddr(canon_servername(servername)))
4685 return enum_all_printers_info_2(buffer, offered, needed, returned);
4686 else
4687 return WERR_INVALID_NAME;
4690 if (flags & PRINTER_ENUM_REMOTE)
4691 return WERR_UNKNOWN_LEVEL;
4693 return WERR_OK;
4696 /********************************************************************
4697 * handle enumeration of printers at level 5
4698 ********************************************************************/
4700 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4701 RPC_BUFFER *buffer, uint32 offered,
4702 uint32 *needed, uint32 *returned)
4704 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4705 return WERR_OK;
4708 /********************************************************************
4709 * api_spoolss_enumprinters
4711 * called from api_spoolss_enumprinters (see this to understand)
4712 ********************************************************************/
4714 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4716 uint32 flags = q_u->flags;
4717 UNISTR2 *servername = &q_u->servername;
4718 uint32 level = q_u->level;
4719 RPC_BUFFER *buffer = NULL;
4720 uint32 offered = q_u->offered;
4721 uint32 *needed = &r_u->needed;
4722 uint32 *returned = &r_u->returned;
4724 fstring name;
4726 /* that's an [in out] buffer */
4728 if (!q_u->buffer && (offered!=0)) {
4729 return WERR_INVALID_PARAM;
4732 if (offered > MAX_RPC_DATA_SIZE) {
4733 return WERR_INVALID_PARAM;
4736 rpcbuf_move(q_u->buffer, &r_u->buffer);
4737 buffer = r_u->buffer;
4739 DEBUG(4,("_spoolss_enumprinters\n"));
4741 *needed=0;
4742 *returned=0;
4745 * Level 1:
4746 * flags==PRINTER_ENUM_NAME
4747 * if name=="" then enumerates all printers
4748 * if name!="" then enumerate the printer
4749 * flags==PRINTER_ENUM_REMOTE
4750 * name is NULL, enumerate printers
4751 * Level 2: name!="" enumerates printers, name can't be NULL
4752 * Level 3: doesn't exist
4753 * Level 4: does a local registry lookup
4754 * Level 5: same as Level 2
4757 unistr2_to_ascii(name, servername, sizeof(name));
4758 strupper_m(name);
4760 switch (level) {
4761 case 1:
4762 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4763 case 2:
4764 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4765 case 5:
4766 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4767 case 3:
4768 case 4:
4769 break;
4771 return WERR_UNKNOWN_LEVEL;
4774 /****************************************************************************
4775 ****************************************************************************/
4777 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4779 PRINTER_INFO_0 *printer=NULL;
4780 WERROR result = WERR_OK;
4782 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4783 return WERR_NOMEM;
4785 construct_printer_info_0(print_hnd, printer, snum);
4787 /* check the required size. */
4788 *needed += spoolss_size_printer_info_0(printer);
4790 if (*needed > offered) {
4791 result = WERR_INSUFFICIENT_BUFFER;
4792 goto out;
4795 if (!rpcbuf_alloc_size(buffer, *needed)) {
4796 result = WERR_NOMEM;
4797 goto out;
4800 /* fill the buffer with the structures */
4801 smb_io_printer_info_0("", buffer, printer, 0);
4803 out:
4804 /* clear memory */
4806 SAFE_FREE(printer);
4808 return result;
4811 /****************************************************************************
4812 ****************************************************************************/
4814 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4816 PRINTER_INFO_1 *printer=NULL;
4817 WERROR result = WERR_OK;
4819 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4820 return WERR_NOMEM;
4822 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4824 /* check the required size. */
4825 *needed += spoolss_size_printer_info_1(printer);
4827 if (*needed > offered) {
4828 result = WERR_INSUFFICIENT_BUFFER;
4829 goto out;
4832 if (!rpcbuf_alloc_size(buffer, *needed)) {
4833 result = WERR_NOMEM;
4834 goto out;
4837 /* fill the buffer with the structures */
4838 smb_io_printer_info_1("", buffer, printer, 0);
4840 out:
4841 /* clear memory */
4842 SAFE_FREE(printer);
4844 return result;
4847 /****************************************************************************
4848 ****************************************************************************/
4850 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4852 PRINTER_INFO_2 *printer=NULL;
4853 WERROR result = WERR_OK;
4855 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4856 return WERR_NOMEM;
4858 construct_printer_info_2(print_hnd, printer, snum);
4860 /* check the required size. */
4861 *needed += spoolss_size_printer_info_2(printer);
4863 if (*needed > offered) {
4864 result = WERR_INSUFFICIENT_BUFFER;
4865 goto out;
4868 if (!rpcbuf_alloc_size(buffer, *needed)) {
4869 result = WERR_NOMEM;
4870 goto out;
4873 /* fill the buffer with the structures */
4874 if (!smb_io_printer_info_2("", buffer, printer, 0))
4875 result = WERR_NOMEM;
4877 out:
4878 /* clear memory */
4879 free_printer_info_2(printer);
4881 return result;
4884 /****************************************************************************
4885 ****************************************************************************/
4887 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4889 PRINTER_INFO_3 *printer=NULL;
4890 WERROR result = WERR_OK;
4892 if (!construct_printer_info_3(print_hnd, &printer, snum))
4893 return WERR_NOMEM;
4895 /* check the required size. */
4896 *needed += spoolss_size_printer_info_3(printer);
4898 if (*needed > offered) {
4899 result = WERR_INSUFFICIENT_BUFFER;
4900 goto out;
4903 if (!rpcbuf_alloc_size(buffer, *needed)) {
4904 result = WERR_NOMEM;
4905 goto out;
4908 /* fill the buffer with the structures */
4909 smb_io_printer_info_3("", buffer, printer, 0);
4911 out:
4912 /* clear memory */
4913 free_printer_info_3(printer);
4915 return result;
4918 /****************************************************************************
4919 ****************************************************************************/
4921 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4923 PRINTER_INFO_4 *printer=NULL;
4924 WERROR result = WERR_OK;
4926 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4927 return WERR_NOMEM;
4929 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4930 SAFE_FREE(printer);
4931 return WERR_NOMEM;
4934 /* check the required size. */
4935 *needed += spoolss_size_printer_info_4(printer);
4937 if (*needed > offered) {
4938 result = WERR_INSUFFICIENT_BUFFER;
4939 goto out;
4942 if (!rpcbuf_alloc_size(buffer, *needed)) {
4943 result = WERR_NOMEM;
4944 goto out;
4947 /* fill the buffer with the structures */
4948 smb_io_printer_info_4("", buffer, printer, 0);
4950 out:
4951 /* clear memory */
4952 free_printer_info_4(printer);
4954 return result;
4957 /****************************************************************************
4958 ****************************************************************************/
4960 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4962 PRINTER_INFO_5 *printer=NULL;
4963 WERROR result = WERR_OK;
4965 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4966 return WERR_NOMEM;
4968 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4969 free_printer_info_5(printer);
4970 return WERR_NOMEM;
4973 /* check the required size. */
4974 *needed += spoolss_size_printer_info_5(printer);
4976 if (*needed > offered) {
4977 result = WERR_INSUFFICIENT_BUFFER;
4978 goto out;
4981 if (!rpcbuf_alloc_size(buffer, *needed)) {
4982 result = WERR_NOMEM;
4983 goto out;
4986 /* fill the buffer with the structures */
4987 smb_io_printer_info_5("", buffer, printer, 0);
4989 out:
4990 /* clear memory */
4991 free_printer_info_5(printer);
4993 return result;
4996 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4997 int snum,
4998 RPC_BUFFER *buffer, uint32 offered,
4999 uint32 *needed)
5001 PRINTER_INFO_6 *printer;
5002 WERROR result = WERR_OK;
5004 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5005 return WERR_NOMEM;
5008 if (!construct_printer_info_6(print_hnd, printer, snum)) {
5009 free_printer_info_6(printer);
5010 return WERR_NOMEM;
5013 /* check the required size. */
5014 *needed += spoolss_size_printer_info_6(printer);
5016 if (*needed > offered) {
5017 result = WERR_INSUFFICIENT_BUFFER;
5018 goto out;
5021 if (!rpcbuf_alloc_size(buffer, *needed)) {
5022 result = WERR_NOMEM;
5023 goto out;
5026 /* fill the buffer with the structures */
5027 smb_io_printer_info_6("", buffer, printer, 0);
5029 out:
5030 /* clear memory */
5031 free_printer_info_6(printer);
5033 return result;
5036 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5038 PRINTER_INFO_7 *printer=NULL;
5039 WERROR result = WERR_OK;
5041 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5042 return WERR_NOMEM;
5044 if (!construct_printer_info_7(print_hnd, printer, snum)) {
5045 result = WERR_NOMEM;
5046 goto out;
5049 /* check the required size. */
5050 *needed += spoolss_size_printer_info_7(printer);
5052 if (*needed > offered) {
5053 result = WERR_INSUFFICIENT_BUFFER;
5054 goto out;
5057 if (!rpcbuf_alloc_size(buffer, *needed)) {
5058 result = WERR_NOMEM;
5059 goto out;
5063 /* fill the buffer with the structures */
5064 smb_io_printer_info_7("", buffer, printer, 0);
5066 out:
5067 /* clear memory */
5068 free_printer_info_7(printer);
5070 return result;
5073 /****************************************************************************
5074 ****************************************************************************/
5076 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5078 POLICY_HND *handle = &q_u->handle;
5079 uint32 level = q_u->level;
5080 RPC_BUFFER *buffer = NULL;
5081 uint32 offered = q_u->offered;
5082 uint32 *needed = &r_u->needed;
5083 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5085 int snum;
5087 /* that's an [in out] buffer */
5089 if (!q_u->buffer && (offered!=0)) {
5090 return WERR_INVALID_PARAM;
5093 if (offered > MAX_RPC_DATA_SIZE) {
5094 return WERR_INVALID_PARAM;
5097 rpcbuf_move(q_u->buffer, &r_u->buffer);
5098 buffer = r_u->buffer;
5100 *needed=0;
5102 if (!get_printer_snum(p, handle, &snum, NULL))
5103 return WERR_BADFID;
5105 switch (level) {
5106 case 0:
5107 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5108 case 1:
5109 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5110 case 2:
5111 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5112 case 3:
5113 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5114 case 4:
5115 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5116 case 5:
5117 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5118 case 6:
5119 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5120 case 7:
5121 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5123 return WERR_UNKNOWN_LEVEL;
5126 /********************************************************************
5127 * fill a DRIVER_INFO_1 struct
5128 ********************************************************************/
5130 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5132 init_unistr( &info->name, driver.info_3->name);
5135 /********************************************************************
5136 * construct_printer_driver_info_1
5137 ********************************************************************/
5139 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5141 NT_PRINTER_INFO_LEVEL *printer = NULL;
5142 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5144 ZERO_STRUCT(driver);
5146 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5147 return WERR_INVALID_PRINTER_NAME;
5149 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5150 free_a_printer(&printer, 2);
5151 return WERR_UNKNOWN_PRINTER_DRIVER;
5154 fill_printer_driver_info_1(info, driver, servername, architecture);
5156 free_a_printer(&printer,2);
5158 return WERR_OK;
5161 /********************************************************************
5162 * construct_printer_driver_info_2
5163 * fill a printer_info_2 struct
5164 ********************************************************************/
5166 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5168 TALLOC_CTX *ctx = talloc_tos();
5169 char *temp = NULL;
5170 const char *cservername = canon_servername(servername);
5172 info->version=driver.info_3->cversion;
5174 init_unistr( &info->name, driver.info_3->name );
5175 init_unistr( &info->architecture, driver.info_3->environment );
5177 if (strlen(driver.info_3->driverpath)) {
5178 temp = talloc_asprintf(ctx,
5179 "\\\\%s%s",
5180 cservername,
5181 driver.info_3->driverpath);
5182 init_unistr( &info->driverpath, temp );
5183 } else {
5184 init_unistr( &info->driverpath, "" );
5187 TALLOC_FREE(temp);
5188 if (strlen(driver.info_3->datafile)) {
5189 temp = talloc_asprintf(ctx,
5190 "\\\\%s%s",
5191 cservername,
5192 driver.info_3->datafile);
5193 init_unistr( &info->datafile, temp );
5194 } else
5195 init_unistr( &info->datafile, "" );
5197 TALLOC_FREE(temp);
5198 if (strlen(driver.info_3->configfile)) {
5199 temp = talloc_asprintf(ctx,
5200 "\\\\%s%s",
5201 cservername,
5202 driver.info_3->configfile);
5203 init_unistr( &info->configfile, temp );
5204 } else
5205 init_unistr( &info->configfile, "" );
5208 /********************************************************************
5209 * construct_printer_driver_info_2
5210 * fill a printer_info_2 struct
5211 ********************************************************************/
5213 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5215 NT_PRINTER_INFO_LEVEL *printer = NULL;
5216 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5218 ZERO_STRUCT(printer);
5219 ZERO_STRUCT(driver);
5221 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5222 return WERR_INVALID_PRINTER_NAME;
5224 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5225 free_a_printer(&printer, 2);
5226 return WERR_UNKNOWN_PRINTER_DRIVER;
5229 fill_printer_driver_info_2(info, driver, servername);
5231 free_a_printer(&printer,2);
5233 return WERR_OK;
5236 /********************************************************************
5237 * copy a strings array and convert to UNICODE
5239 * convert an array of ascii string to a UNICODE string
5240 ********************************************************************/
5242 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5244 int i=0;
5245 int j=0;
5246 const char *v;
5247 char *line = NULL;
5248 TALLOC_CTX *ctx = talloc_tos();
5250 DEBUG(6,("init_unistr_array\n"));
5251 *uni_array=NULL;
5253 while (true) {
5254 if ( !char_array ) {
5255 v = "";
5256 } else {
5257 v = char_array[i];
5258 if (!v)
5259 v = ""; /* hack to handle null lists */
5262 /* hack to allow this to be used in places other than when generating
5263 the list of dependent files */
5265 TALLOC_FREE(line);
5266 if ( servername ) {
5267 line = talloc_asprintf(ctx,
5268 "\\\\%s%s",
5269 canon_servername(servername),
5271 } else {
5272 line = talloc_strdup(ctx, v);
5275 if (!line) {
5276 SAFE_FREE(*uni_array);
5277 return 0;
5279 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5281 /* add one extra unit16 for the second terminating NULL */
5283 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5284 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5285 return 0;
5288 if ( !strlen(v) )
5289 break;
5291 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5292 i++;
5295 if (*uni_array) {
5296 /* special case for ""; we need to add both NULL's here */
5297 if (!j)
5298 (*uni_array)[j++]=0x0000;
5299 (*uni_array)[j]=0x0000;
5302 DEBUGADD(6,("last one:done\n"));
5304 /* return size of array in uint16's */
5306 return j+1;
5309 /********************************************************************
5310 * construct_printer_info_3
5311 * fill a printer_info_3 struct
5312 ********************************************************************/
5314 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5316 char *temp = NULL;
5317 TALLOC_CTX *ctx = talloc_tos();
5318 const char *cservername = canon_servername(servername);
5320 ZERO_STRUCTP(info);
5322 info->version=driver.info_3->cversion;
5324 init_unistr( &info->name, driver.info_3->name );
5325 init_unistr( &info->architecture, driver.info_3->environment );
5327 if (strlen(driver.info_3->driverpath)) {
5328 temp = talloc_asprintf(ctx,
5329 "\\\\%s%s",
5330 cservername,
5331 driver.info_3->driverpath);
5332 init_unistr( &info->driverpath, temp );
5333 } else
5334 init_unistr( &info->driverpath, "" );
5336 TALLOC_FREE(temp);
5337 if (strlen(driver.info_3->datafile)) {
5338 temp = talloc_asprintf(ctx,
5339 "\\\\%s%s",
5340 cservername,
5341 driver.info_3->datafile);
5342 init_unistr( &info->datafile, temp );
5343 } else
5344 init_unistr( &info->datafile, "" );
5346 TALLOC_FREE(temp);
5347 if (strlen(driver.info_3->configfile)) {
5348 temp = talloc_asprintf(ctx,
5349 "\\\\%s%s",
5350 cservername,
5351 driver.info_3->configfile);
5352 init_unistr( &info->configfile, temp );
5353 } else
5354 init_unistr( &info->configfile, "" );
5356 TALLOC_FREE(temp);
5357 if (strlen(driver.info_3->helpfile)) {
5358 temp = talloc_asprintf(ctx,
5359 "\\\\%s%s",
5360 cservername,
5361 driver.info_3->helpfile);
5362 init_unistr( &info->helpfile, temp );
5363 } else
5364 init_unistr( &info->helpfile, "" );
5366 TALLOC_FREE(temp);
5367 init_unistr( &info->monitorname, driver.info_3->monitorname );
5368 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5370 info->dependentfiles=NULL;
5371 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5374 /********************************************************************
5375 * construct_printer_info_3
5376 * fill a printer_info_3 struct
5377 ********************************************************************/
5379 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5381 NT_PRINTER_INFO_LEVEL *printer = NULL;
5382 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5383 WERROR status;
5384 ZERO_STRUCT(driver);
5386 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5387 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5388 if (!W_ERROR_IS_OK(status))
5389 return WERR_INVALID_PRINTER_NAME;
5391 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5392 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5394 #if 0 /* JERRY */
5397 * I put this code in during testing. Helpful when commenting out the
5398 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5399 * as win2k always queries the driver using an infor level of 6.
5400 * I've left it in (but ifdef'd out) because I'll probably
5401 * use it in experimentation again in the future. --jerry 22/01/2002
5404 if (!W_ERROR_IS_OK(status)) {
5406 * Is this a W2k client ?
5408 if (version == 3) {
5409 /* Yes - try again with a WinNT driver. */
5410 version = 2;
5411 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5412 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5414 #endif
5416 if (!W_ERROR_IS_OK(status)) {
5417 free_a_printer(&printer,2);
5418 return WERR_UNKNOWN_PRINTER_DRIVER;
5421 #if 0 /* JERRY */
5423 #endif
5426 fill_printer_driver_info_3(info, driver, servername);
5428 free_a_printer(&printer,2);
5430 return WERR_OK;
5433 /********************************************************************
5434 * construct_printer_info_6
5435 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5436 ********************************************************************/
5438 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5440 char *temp = NULL;
5441 fstring nullstr;
5442 TALLOC_CTX *ctx = talloc_tos();
5443 const char *cservername = canon_servername(servername);
5445 ZERO_STRUCTP(info);
5446 memset(&nullstr, '\0', sizeof(fstring));
5448 info->version=driver.info_3->cversion;
5450 init_unistr( &info->name, driver.info_3->name );
5451 init_unistr( &info->architecture, driver.info_3->environment );
5453 if (strlen(driver.info_3->driverpath)) {
5454 temp = talloc_asprintf(ctx,
5455 "\\\\%s%s",
5456 cservername,
5457 driver.info_3->driverpath);
5458 init_unistr( &info->driverpath, temp );
5459 } else
5460 init_unistr( &info->driverpath, "" );
5462 TALLOC_FREE(temp);
5463 if (strlen(driver.info_3->datafile)) {
5464 temp = talloc_asprintf(ctx,
5465 "\\\\%s%s",
5466 cservername,
5467 driver.info_3->datafile);
5468 init_unistr( &info->datafile, temp );
5469 } else
5470 init_unistr( &info->datafile, "" );
5472 TALLOC_FREE(temp);
5473 if (strlen(driver.info_3->configfile)) {
5474 temp = talloc_asprintf(ctx,
5475 "\\\\%s%s",
5476 cservername,
5477 driver.info_3->configfile);
5478 init_unistr( &info->configfile, temp );
5479 } else
5480 init_unistr( &info->configfile, "" );
5482 TALLOC_FREE(temp);
5483 if (strlen(driver.info_3->helpfile)) {
5484 temp = talloc_asprintf(ctx,
5485 "\\\\%s%s",
5486 cservername,
5487 driver.info_3->helpfile);
5488 init_unistr( &info->helpfile, temp );
5489 } else
5490 init_unistr( &info->helpfile, "" );
5492 TALLOC_FREE(temp);
5493 init_unistr( &info->monitorname, driver.info_3->monitorname );
5494 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5496 info->dependentfiles = NULL;
5497 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5499 info->previousdrivernames=NULL;
5500 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5502 info->driver_date=0;
5504 info->padding=0;
5505 info->driver_version_low=0;
5506 info->driver_version_high=0;
5508 init_unistr( &info->mfgname, "");
5509 init_unistr( &info->oem_url, "");
5510 init_unistr( &info->hardware_id, "");
5511 init_unistr( &info->provider, "");
5514 /********************************************************************
5515 * construct_printer_info_6
5516 * fill a printer_info_6 struct
5517 ********************************************************************/
5519 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5520 const char *servername, fstring architecture, uint32 version)
5522 NT_PRINTER_INFO_LEVEL *printer = NULL;
5523 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5524 WERROR status;
5526 ZERO_STRUCT(driver);
5528 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5530 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5532 if (!W_ERROR_IS_OK(status))
5533 return WERR_INVALID_PRINTER_NAME;
5535 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5537 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5539 if (!W_ERROR_IS_OK(status))
5542 * Is this a W2k client ?
5545 if (version < 3) {
5546 free_a_printer(&printer,2);
5547 return WERR_UNKNOWN_PRINTER_DRIVER;
5550 /* Yes - try again with a WinNT driver. */
5551 version = 2;
5552 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5553 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5554 if (!W_ERROR_IS_OK(status)) {
5555 free_a_printer(&printer,2);
5556 return WERR_UNKNOWN_PRINTER_DRIVER;
5560 fill_printer_driver_info_6(info, driver, servername);
5562 free_a_printer(&printer,2);
5563 free_a_printer_driver(driver, 3);
5565 return WERR_OK;
5568 /****************************************************************************
5569 ****************************************************************************/
5571 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5573 SAFE_FREE(info->dependentfiles);
5576 /****************************************************************************
5577 ****************************************************************************/
5579 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5581 SAFE_FREE(info->dependentfiles);
5584 /****************************************************************************
5585 ****************************************************************************/
5587 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5589 DRIVER_INFO_1 *info=NULL;
5590 WERROR result;
5592 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5593 return WERR_NOMEM;
5595 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5596 if (!W_ERROR_IS_OK(result))
5597 goto out;
5599 /* check the required size. */
5600 *needed += spoolss_size_printer_driver_info_1(info);
5602 if (*needed > offered) {
5603 result = WERR_INSUFFICIENT_BUFFER;
5604 goto out;
5607 if (!rpcbuf_alloc_size(buffer, *needed)) {
5608 result = WERR_NOMEM;
5609 goto out;
5612 /* fill the buffer with the structures */
5613 smb_io_printer_driver_info_1("", buffer, info, 0);
5615 out:
5616 /* clear memory */
5617 SAFE_FREE(info);
5619 return result;
5622 /****************************************************************************
5623 ****************************************************************************/
5625 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5627 DRIVER_INFO_2 *info=NULL;
5628 WERROR result;
5630 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5631 return WERR_NOMEM;
5633 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5634 if (!W_ERROR_IS_OK(result))
5635 goto out;
5637 /* check the required size. */
5638 *needed += spoolss_size_printer_driver_info_2(info);
5640 if (*needed > offered) {
5641 result = WERR_INSUFFICIENT_BUFFER;
5642 goto out;
5645 if (!rpcbuf_alloc_size(buffer, *needed)) {
5646 result = WERR_NOMEM;
5647 goto out;
5650 /* fill the buffer with the structures */
5651 smb_io_printer_driver_info_2("", buffer, info, 0);
5653 out:
5654 /* clear memory */
5655 SAFE_FREE(info);
5657 return result;
5660 /****************************************************************************
5661 ****************************************************************************/
5663 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5665 DRIVER_INFO_3 info;
5666 WERROR result;
5668 ZERO_STRUCT(info);
5670 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5671 if (!W_ERROR_IS_OK(result))
5672 goto out;
5674 /* check the required size. */
5675 *needed += spoolss_size_printer_driver_info_3(&info);
5677 if (*needed > offered) {
5678 result = WERR_INSUFFICIENT_BUFFER;
5679 goto out;
5682 if (!rpcbuf_alloc_size(buffer, *needed)) {
5683 result = WERR_NOMEM;
5684 goto out;
5687 /* fill the buffer with the structures */
5688 smb_io_printer_driver_info_3("", buffer, &info, 0);
5690 out:
5691 free_printer_driver_info_3(&info);
5693 return result;
5696 /****************************************************************************
5697 ****************************************************************************/
5699 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5701 DRIVER_INFO_6 info;
5702 WERROR result;
5704 ZERO_STRUCT(info);
5706 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5707 if (!W_ERROR_IS_OK(result))
5708 goto out;
5710 /* check the required size. */
5711 *needed += spoolss_size_printer_driver_info_6(&info);
5713 if (*needed > offered) {
5714 result = WERR_INSUFFICIENT_BUFFER;
5715 goto out;
5718 if (!rpcbuf_alloc_size(buffer, *needed)) {
5719 result = WERR_NOMEM;
5720 goto out;
5723 /* fill the buffer with the structures */
5724 smb_io_printer_driver_info_6("", buffer, &info, 0);
5726 out:
5727 free_printer_driver_info_6(&info);
5729 return result;
5732 /****************************************************************************
5733 ****************************************************************************/
5735 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5737 POLICY_HND *handle = &q_u->handle;
5738 UNISTR2 *uni_arch = &q_u->architecture;
5739 uint32 level = q_u->level;
5740 uint32 clientmajorversion = q_u->clientmajorversion;
5741 RPC_BUFFER *buffer = NULL;
5742 uint32 offered = q_u->offered;
5743 uint32 *needed = &r_u->needed;
5744 uint32 *servermajorversion = &r_u->servermajorversion;
5745 uint32 *serverminorversion = &r_u->serverminorversion;
5746 Printer_entry *printer;
5748 fstring servername;
5749 fstring architecture;
5750 int snum;
5752 /* that's an [in out] buffer */
5754 if (!q_u->buffer && (offered!=0)) {
5755 return WERR_INVALID_PARAM;
5758 if (offered > MAX_RPC_DATA_SIZE) {
5759 return WERR_INVALID_PARAM;
5762 rpcbuf_move(q_u->buffer, &r_u->buffer);
5763 buffer = r_u->buffer;
5765 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5767 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5768 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5769 return WERR_INVALID_PRINTER_NAME;
5772 *needed = 0;
5773 *servermajorversion = 0;
5774 *serverminorversion = 0;
5776 fstrcpy(servername, get_server_name( printer ));
5777 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5779 if (!get_printer_snum(p, handle, &snum, NULL))
5780 return WERR_BADFID;
5782 switch (level) {
5783 case 1:
5784 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5785 case 2:
5786 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5787 case 3:
5788 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5789 case 6:
5790 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5791 #if 0 /* JERRY */
5792 case 101:
5793 /* apparently this call is the equivalent of
5794 EnumPrinterDataEx() for the DsDriver key */
5795 break;
5796 #endif
5799 return WERR_UNKNOWN_LEVEL;
5802 /****************************************************************************
5803 ****************************************************************************/
5805 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5807 POLICY_HND *handle = &q_u->handle;
5809 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5811 if (!Printer) {
5812 DEBUG(3,("Error in startpageprinter printer handle\n"));
5813 return WERR_BADFID;
5816 Printer->page_started=True;
5817 return WERR_OK;
5820 /****************************************************************************
5821 ****************************************************************************/
5823 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5825 POLICY_HND *handle = &q_u->handle;
5826 int snum;
5828 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5830 if (!Printer) {
5831 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5832 return WERR_BADFID;
5835 if (!get_printer_snum(p, handle, &snum, NULL))
5836 return WERR_BADFID;
5838 Printer->page_started=False;
5839 print_job_endpage(snum, Printer->jobid);
5841 return WERR_OK;
5844 /********************************************************************
5845 * api_spoolss_getprinter
5846 * called from the spoolss dispatcher
5848 ********************************************************************/
5850 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5852 POLICY_HND *handle = &q_u->handle;
5853 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5854 uint32 *jobid = &r_u->jobid;
5855 TALLOC_CTX *ctx = p->mem_ctx;
5856 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5857 int snum;
5858 char *jobname = NULL;
5859 fstring datatype;
5860 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5862 if (!Printer) {
5863 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5864 return WERR_BADFID;
5868 * a nice thing with NT is it doesn't listen to what you tell it.
5869 * when asked to send _only_ RAW datas, it tries to send datas
5870 * in EMF format.
5872 * So I add checks like in NT Server ...
5875 if (info_1->p_datatype != 0) {
5876 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5877 if (strcmp(datatype, "RAW") != 0) {
5878 (*jobid)=0;
5879 return WERR_INVALID_DATATYPE;
5883 /* get the share number of the printer */
5884 if (!get_printer_snum(p, handle, &snum, NULL)) {
5885 return WERR_BADFID;
5888 jobname = unistr2_to_ascii_talloc(ctx, &info_1->docname);
5890 Printer->jobid = print_job_start(p->server_info, snum, jobname,
5891 Printer->nt_devmode);
5893 /* An error occured in print_job_start() so return an appropriate
5894 NT error code. */
5896 if (Printer->jobid == -1) {
5897 return map_werror_from_unix(errno);
5900 Printer->document_started=True;
5901 (*jobid) = Printer->jobid;
5903 return WERR_OK;
5906 /********************************************************************
5907 * api_spoolss_getprinter
5908 * called from the spoolss dispatcher
5910 ********************************************************************/
5912 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5914 POLICY_HND *handle = &q_u->handle;
5916 return _spoolss_enddocprinter_internal(p, handle);
5919 /****************************************************************************
5920 ****************************************************************************/
5922 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5924 POLICY_HND *handle = &q_u->handle;
5925 uint32 buffer_size = q_u->buffer_size;
5926 uint8 *buffer = q_u->buffer;
5927 uint32 *buffer_written = &q_u->buffer_size2;
5928 int snum;
5929 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5931 if (!Printer) {
5932 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5933 r_u->buffer_written = q_u->buffer_size2;
5934 return WERR_BADFID;
5937 if (!get_printer_snum(p, handle, &snum, NULL))
5938 return WERR_BADFID;
5940 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5941 (SMB_OFF_T)-1, (size_t)buffer_size);
5942 if (*buffer_written == (uint32)-1) {
5943 r_u->buffer_written = 0;
5944 if (errno == ENOSPC)
5945 return WERR_NO_SPOOL_SPACE;
5946 else
5947 return WERR_ACCESS_DENIED;
5950 r_u->buffer_written = q_u->buffer_size2;
5952 return WERR_OK;
5955 /********************************************************************
5956 * api_spoolss_getprinter
5957 * called from the spoolss dispatcher
5959 ********************************************************************/
5961 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5962 pipes_struct *p)
5964 int snum;
5965 WERROR errcode = WERR_BADFUNC;
5966 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5968 if (!Printer) {
5969 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5970 return WERR_BADFID;
5973 if (!get_printer_snum(p, handle, &snum, NULL))
5974 return WERR_BADFID;
5976 switch (command) {
5977 case PRINTER_CONTROL_PAUSE:
5978 if (print_queue_pause(p->server_info, snum, &errcode)) {
5979 errcode = WERR_OK;
5981 break;
5982 case PRINTER_CONTROL_RESUME:
5983 case PRINTER_CONTROL_UNPAUSE:
5984 if (print_queue_resume(p->server_info, snum, &errcode)) {
5985 errcode = WERR_OK;
5987 break;
5988 case PRINTER_CONTROL_PURGE:
5989 if (print_queue_purge(p->server_info, snum, &errcode)) {
5990 errcode = WERR_OK;
5992 break;
5993 default:
5994 return WERR_UNKNOWN_LEVEL;
5997 return errcode;
6000 /********************************************************************
6001 * api_spoolss_abortprinter
6002 * From MSDN: "Deletes printer's spool file if printer is configured
6003 * for spooling"
6004 ********************************************************************/
6006 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
6008 POLICY_HND *handle = &q_u->handle;
6009 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6010 int snum;
6011 WERROR errcode = WERR_OK;
6013 if (!Printer) {
6014 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
6015 return WERR_BADFID;
6018 if (!get_printer_snum(p, handle, &snum, NULL))
6019 return WERR_BADFID;
6021 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6023 return errcode;
6026 /********************************************************************
6027 * called by spoolss_api_setprinter
6028 * when updating a printer description
6029 ********************************************************************/
6031 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6032 const SPOOL_PRINTER_INFO_LEVEL *info,
6033 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6035 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6036 WERROR result;
6037 int snum;
6039 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6041 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6042 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6043 OUR_HANDLE(handle)));
6045 result = WERR_BADFID;
6046 goto done;
6049 if (!secdesc_ctr) {
6050 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6051 result = WERR_INVALID_PARAM;
6052 goto done;
6055 /* Check the user has permissions to change the security
6056 descriptor. By experimentation with two NT machines, the user
6057 requires Full Access to the printer to change security
6058 information. */
6060 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6061 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6062 result = WERR_ACCESS_DENIED;
6063 goto done;
6066 /* NT seems to like setting the security descriptor even though
6067 nothing may have actually changed. */
6069 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6070 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6071 result = WERR_BADFID;
6072 goto done;
6075 if (DEBUGLEVEL >= 10) {
6076 SEC_ACL *the_acl;
6077 int i;
6079 the_acl = old_secdesc_ctr->sd->dacl;
6080 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6081 PRINTERNAME(snum), the_acl->num_aces));
6083 for (i = 0; i < the_acl->num_aces; i++) {
6084 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6085 &the_acl->aces[i].trustee),
6086 the_acl->aces[i].access_mask));
6089 the_acl = secdesc_ctr->sd->dacl;
6091 if (the_acl) {
6092 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6093 PRINTERNAME(snum), the_acl->num_aces));
6095 for (i = 0; i < the_acl->num_aces; i++) {
6096 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6097 &the_acl->aces[i].trustee),
6098 the_acl->aces[i].access_mask));
6100 } else {
6101 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6105 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6106 if (!new_secdesc_ctr) {
6107 result = WERR_NOMEM;
6108 goto done;
6111 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6112 result = WERR_OK;
6113 goto done;
6116 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6118 done:
6120 return result;
6123 /********************************************************************
6124 Canonicalize printer info from a client
6126 ATTN: It does not matter what we set the servername to hear
6127 since we do the necessary work in get_a_printer() to set it to
6128 the correct value based on what the client sent in the
6129 _spoolss_open_printer_ex().
6130 ********************************************************************/
6132 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6134 fstring printername;
6135 const char *p;
6137 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6138 "portname=%s drivername=%s comment=%s location=%s\n",
6139 info->servername, info->printername, info->sharename,
6140 info->portname, info->drivername, info->comment, info->location));
6142 /* we force some elements to "correct" values */
6143 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6144 fstrcpy(info->sharename, lp_servicename(snum));
6146 /* check to see if we allow printername != sharename */
6148 if ( lp_force_printername(snum) ) {
6149 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6150 global_myname(), info->sharename );
6151 } else {
6153 /* make sure printername is in \\server\printername format */
6155 fstrcpy( printername, info->printername );
6156 p = printername;
6157 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6158 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6159 p++;
6162 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6163 global_myname(), p );
6166 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6167 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6171 return True;
6174 /****************************************************************************
6175 ****************************************************************************/
6177 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6179 char *cmd = lp_addport_cmd();
6180 char *command = NULL;
6181 int ret;
6182 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6183 bool is_print_op = False;
6185 if ( !*cmd ) {
6186 return WERR_ACCESS_DENIED;
6189 command = talloc_asprintf(ctx,
6190 "%s \"%s\" \"%s\"", cmd, portname, uri );
6191 if (!command) {
6192 return WERR_NOMEM;
6195 if ( token )
6196 is_print_op = user_has_privileges( token, &se_printop );
6198 DEBUG(10,("Running [%s]\n", command));
6200 /********* BEGIN SePrintOperatorPrivilege **********/
6202 if ( is_print_op )
6203 become_root();
6205 ret = smbrun(command, NULL);
6207 if ( is_print_op )
6208 unbecome_root();
6210 /********* END SePrintOperatorPrivilege **********/
6212 DEBUGADD(10,("returned [%d]\n", ret));
6214 TALLOC_FREE(command);
6216 if ( ret != 0 ) {
6217 return WERR_ACCESS_DENIED;
6220 return WERR_OK;
6223 /****************************************************************************
6224 ****************************************************************************/
6226 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6228 char *cmd = lp_addprinter_cmd();
6229 char **qlines;
6230 char *command = NULL;
6231 int numlines;
6232 int ret;
6233 int fd;
6234 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6235 bool is_print_op = False;
6236 char *remote_machine = talloc_strdup(ctx, "%m");
6238 if (!remote_machine) {
6239 return false;
6241 remote_machine = talloc_sub_basic(ctx,
6242 current_user_info.smb_name,
6243 current_user_info.domain,
6244 remote_machine);
6245 if (!remote_machine) {
6246 return false;
6249 command = talloc_asprintf(ctx,
6250 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6251 cmd, printer->info_2->printername, printer->info_2->sharename,
6252 printer->info_2->portname, printer->info_2->drivername,
6253 printer->info_2->location, printer->info_2->comment, remote_machine);
6254 if (!command) {
6255 return false;
6258 if ( token )
6259 is_print_op = user_has_privileges( token, &se_printop );
6261 DEBUG(10,("Running [%s]\n", command));
6263 /********* BEGIN SePrintOperatorPrivilege **********/
6265 if ( is_print_op )
6266 become_root();
6268 if ( (ret = smbrun(command, &fd)) == 0 ) {
6269 /* Tell everyone we updated smb.conf. */
6270 message_send_all(smbd_messaging_context(),
6271 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6274 if ( is_print_op )
6275 unbecome_root();
6277 /********* END SePrintOperatorPrivilege **********/
6279 DEBUGADD(10,("returned [%d]\n", ret));
6281 TALLOC_FREE(command);
6282 TALLOC_FREE(remote_machine);
6284 if ( ret != 0 ) {
6285 if (fd != -1)
6286 close(fd);
6287 return False;
6290 /* reload our services immediately */
6291 reload_services( False );
6293 numlines = 0;
6294 /* Get lines and convert them back to dos-codepage */
6295 qlines = fd_lines_load(fd, &numlines, 0);
6296 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6297 close(fd);
6299 /* Set the portname to what the script says the portname should be. */
6300 /* but don't require anything to be return from the script exit a good error code */
6302 if (numlines) {
6303 /* Set the portname to what the script says the portname should be. */
6304 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6305 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6308 file_lines_free(qlines);
6309 return True;
6313 /********************************************************************
6314 * Called by spoolss_api_setprinter
6315 * when updating a printer description.
6316 ********************************************************************/
6318 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6319 const SPOOL_PRINTER_INFO_LEVEL *info,
6320 DEVICEMODE *devmode)
6322 int snum;
6323 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6324 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6325 WERROR result;
6326 UNISTR2 buffer;
6327 fstring asc_buffer;
6329 DEBUG(8,("update_printer\n"));
6331 result = WERR_OK;
6333 if (!Printer) {
6334 result = WERR_BADFID;
6335 goto done;
6338 if (!get_printer_snum(p, handle, &snum, NULL)) {
6339 result = WERR_BADFID;
6340 goto done;
6343 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6344 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6345 result = WERR_BADFID;
6346 goto done;
6349 DEBUGADD(8,("Converting info_2 struct\n"));
6352 * convert_printer_info converts the incoming
6353 * info from the client and overwrites the info
6354 * just read from the tdb in the pointer 'printer'.
6357 if (!convert_printer_info(info, printer, level)) {
6358 result = WERR_NOMEM;
6359 goto done;
6362 if (devmode) {
6363 /* we have a valid devmode
6364 convert it and link it*/
6366 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6367 if (!convert_devicemode(printer->info_2->printername, devmode,
6368 &printer->info_2->devmode)) {
6369 result = WERR_NOMEM;
6370 goto done;
6374 /* Do sanity check on the requested changes for Samba */
6376 if (!check_printer_ok(printer->info_2, snum)) {
6377 result = WERR_INVALID_PARAM;
6378 goto done;
6381 /* FIXME!!! If the driver has changed we really should verify that
6382 it is installed before doing much else --jerry */
6384 /* Check calling user has permission to update printer description */
6386 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6387 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6388 result = WERR_ACCESS_DENIED;
6389 goto done;
6392 /* Call addprinter hook */
6393 /* Check changes to see if this is really needed */
6395 if ( *lp_addprinter_cmd()
6396 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6397 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6398 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6399 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6401 /* add_printer_hook() will call reload_services() */
6403 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
6404 result = WERR_ACCESS_DENIED;
6405 goto done;
6410 * When a *new* driver is bound to a printer, the drivername is used to
6411 * lookup previously saved driver initialization info, which is then
6412 * bound to the printer, simulating what happens in the Windows arch.
6414 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6416 if (!set_driver_init(printer, 2))
6418 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6419 printer->info_2->drivername));
6422 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6423 printer->info_2->drivername));
6425 notify_printer_driver(snum, printer->info_2->drivername);
6429 * flag which changes actually occured. This is a small subset of
6430 * all the possible changes. We also have to update things in the
6431 * DsSpooler key.
6434 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6435 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6436 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6437 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6439 notify_printer_comment(snum, printer->info_2->comment);
6442 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6443 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6444 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6445 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6447 notify_printer_sharename(snum, printer->info_2->sharename);
6450 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6451 char *pname;
6453 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6454 pname++;
6455 else
6456 pname = printer->info_2->printername;
6459 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6460 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6461 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6463 notify_printer_printername( snum, pname );
6466 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6467 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6468 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6469 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6471 notify_printer_port(snum, printer->info_2->portname);
6474 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6475 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6476 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6477 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6479 notify_printer_location(snum, printer->info_2->location);
6482 /* here we need to update some more DsSpooler keys */
6483 /* uNCName, serverName, shortServerName */
6485 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6486 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6487 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6488 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6489 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6491 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6492 global_myname(), printer->info_2->sharename );
6493 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6494 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6495 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6497 /* Update printer info */
6498 result = mod_a_printer(printer, 2);
6500 done:
6501 free_a_printer(&printer, 2);
6502 free_a_printer(&old_printer, 2);
6505 return result;
6508 /****************************************************************************
6509 ****************************************************************************/
6510 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6511 const SPOOL_PRINTER_INFO_LEVEL *info)
6513 #ifdef HAVE_ADS
6514 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6515 int snum;
6516 Printer_entry *Printer;
6518 if ( lp_security() != SEC_ADS ) {
6519 return WERR_UNKNOWN_LEVEL;
6522 Printer = find_printer_index_by_hnd(p, handle);
6524 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6526 if (!Printer)
6527 return WERR_BADFID;
6529 if (!get_printer_snum(p, handle, &snum, NULL))
6530 return WERR_BADFID;
6532 nt_printer_publish(Printer, snum, info7->action);
6534 return WERR_OK;
6535 #else
6536 return WERR_UNKNOWN_LEVEL;
6537 #endif
6539 /****************************************************************************
6540 ****************************************************************************/
6542 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6544 POLICY_HND *handle = &q_u->handle;
6545 uint32 level = q_u->level;
6546 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6547 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6548 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6549 uint32 command = q_u->command;
6550 WERROR result;
6552 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6554 if (!Printer) {
6555 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6556 return WERR_BADFID;
6559 /* check the level */
6560 switch (level) {
6561 case 0:
6562 return control_printer(handle, command, p);
6563 case 2:
6564 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6565 if (!W_ERROR_IS_OK(result))
6566 return result;
6567 if (secdesc_ctr)
6568 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6569 return result;
6570 case 3:
6571 return update_printer_sec(handle, level, info, p,
6572 secdesc_ctr);
6573 case 7:
6574 return publish_or_unpublish_printer(p, handle, info);
6575 default:
6576 return WERR_UNKNOWN_LEVEL;
6580 /****************************************************************************
6581 ****************************************************************************/
6583 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6585 POLICY_HND *handle = &q_u->handle;
6586 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6588 if (!Printer) {
6589 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6590 return WERR_BADFID;
6593 if (Printer->notify.client_connected==True) {
6594 int snum = -1;
6596 if ( Printer->printer_type == SPLHND_SERVER)
6597 snum = -1;
6598 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6599 !get_printer_snum(p, handle, &snum, NULL) )
6600 return WERR_BADFID;
6602 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6605 Printer->notify.flags=0;
6606 Printer->notify.options=0;
6607 Printer->notify.localmachine[0]='\0';
6608 Printer->notify.printerlocal=0;
6609 if (Printer->notify.option)
6610 free_spool_notify_option(&Printer->notify.option);
6611 Printer->notify.client_connected=False;
6613 return WERR_OK;
6616 /****************************************************************************
6617 ****************************************************************************/
6619 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6621 /* that's an [in out] buffer */
6623 if (!q_u->buffer && (q_u->offered!=0)) {
6624 return WERR_INVALID_PARAM;
6627 rpcbuf_move(q_u->buffer, &r_u->buffer);
6629 r_u->needed = 0;
6630 return WERR_INVALID_PARAM; /* this is what a NT server
6631 returns for AddJob. AddJob
6632 must fail on non-local
6633 printers */
6636 /****************************************************************************
6637 ****************************************************************************/
6639 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6640 int position, int snum,
6641 const NT_PRINTER_INFO_LEVEL *ntprinter)
6643 struct tm *t;
6645 t=gmtime(&queue->time);
6647 job_info->jobid=queue->job;
6648 init_unistr(&job_info->printername, lp_servicename(snum));
6649 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6650 init_unistr(&job_info->username, queue->fs_user);
6651 init_unistr(&job_info->document, queue->fs_file);
6652 init_unistr(&job_info->datatype, "RAW");
6653 init_unistr(&job_info->text_status, "");
6654 job_info->status=nt_printj_status(queue->status);
6655 job_info->priority=queue->priority;
6656 job_info->position=position;
6657 job_info->totalpages=queue->page_count;
6658 job_info->pagesprinted=0;
6660 make_systemtime(&job_info->submitted, t);
6663 /****************************************************************************
6664 ****************************************************************************/
6666 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6667 int position, int snum,
6668 const NT_PRINTER_INFO_LEVEL *ntprinter,
6669 DEVICEMODE *devmode)
6671 struct tm *t;
6673 t=gmtime(&queue->time);
6675 job_info->jobid=queue->job;
6677 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6679 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6680 init_unistr(&job_info->username, queue->fs_user);
6681 init_unistr(&job_info->document, queue->fs_file);
6682 init_unistr(&job_info->notifyname, queue->fs_user);
6683 init_unistr(&job_info->datatype, "RAW");
6684 init_unistr(&job_info->printprocessor, "winprint");
6685 init_unistr(&job_info->parameters, "");
6686 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6687 init_unistr(&job_info->text_status, "");
6689 /* and here the security descriptor */
6691 job_info->status=nt_printj_status(queue->status);
6692 job_info->priority=queue->priority;
6693 job_info->position=position;
6694 job_info->starttime=0;
6695 job_info->untiltime=0;
6696 job_info->totalpages=queue->page_count;
6697 job_info->size=queue->size;
6698 make_systemtime(&(job_info->submitted), t);
6699 job_info->timeelapsed=0;
6700 job_info->pagesprinted=0;
6702 job_info->devmode = devmode;
6704 return (True);
6707 /****************************************************************************
6708 Enumjobs at level 1.
6709 ****************************************************************************/
6711 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6712 const NT_PRINTER_INFO_LEVEL *ntprinter,
6713 RPC_BUFFER *buffer, uint32 offered,
6714 uint32 *needed, uint32 *returned)
6716 JOB_INFO_1 *info;
6717 int i;
6718 WERROR result = WERR_OK;
6720 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6721 if (info==NULL) {
6722 *returned=0;
6723 return WERR_NOMEM;
6726 for (i=0; i<*returned; i++)
6727 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6729 /* check the required size. */
6730 for (i=0; i<*returned; i++)
6731 (*needed) += spoolss_size_job_info_1(&info[i]);
6733 if (*needed > offered) {
6734 result = WERR_INSUFFICIENT_BUFFER;
6735 goto out;
6738 if (!rpcbuf_alloc_size(buffer, *needed)) {
6739 result = WERR_NOMEM;
6740 goto out;
6743 /* fill the buffer with the structures */
6744 for (i=0; i<*returned; i++)
6745 smb_io_job_info_1("", buffer, &info[i], 0);
6747 out:
6748 /* clear memory */
6749 SAFE_FREE(info);
6751 if ( !W_ERROR_IS_OK(result) )
6752 *returned = 0;
6754 return result;
6757 /****************************************************************************
6758 Enumjobs at level 2.
6759 ****************************************************************************/
6761 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6762 const NT_PRINTER_INFO_LEVEL *ntprinter,
6763 RPC_BUFFER *buffer, uint32 offered,
6764 uint32 *needed, uint32 *returned)
6766 JOB_INFO_2 *info = NULL;
6767 int i;
6768 WERROR result = WERR_OK;
6769 DEVICEMODE *devmode = NULL;
6771 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6772 *returned=0;
6773 return WERR_NOMEM;
6776 /* this should not be a failure condition if the devmode is NULL */
6778 devmode = construct_dev_mode(lp_const_servicename(snum));
6780 for (i=0; i<*returned; i++)
6781 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6783 /* check the required size. */
6784 for (i=0; i<*returned; i++)
6785 (*needed) += spoolss_size_job_info_2(&info[i]);
6787 if (*needed > offered) {
6788 result = WERR_INSUFFICIENT_BUFFER;
6789 goto out;
6792 if (!rpcbuf_alloc_size(buffer, *needed)) {
6793 result = WERR_NOMEM;
6794 goto out;
6797 /* fill the buffer with the structures */
6798 for (i=0; i<*returned; i++)
6799 smb_io_job_info_2("", buffer, &info[i], 0);
6801 out:
6802 free_devmode(devmode);
6803 SAFE_FREE(info);
6805 if ( !W_ERROR_IS_OK(result) )
6806 *returned = 0;
6808 return result;
6812 /****************************************************************************
6813 Enumjobs.
6814 ****************************************************************************/
6816 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6818 POLICY_HND *handle = &q_u->handle;
6819 uint32 level = q_u->level;
6820 RPC_BUFFER *buffer = NULL;
6821 uint32 offered = q_u->offered;
6822 uint32 *needed = &r_u->needed;
6823 uint32 *returned = &r_u->returned;
6824 WERROR wret;
6825 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6826 int snum;
6827 print_status_struct prt_status;
6828 print_queue_struct *queue=NULL;
6830 /* that's an [in out] buffer */
6832 if (!q_u->buffer && (offered!=0)) {
6833 return WERR_INVALID_PARAM;
6836 if (offered > MAX_RPC_DATA_SIZE) {
6837 return WERR_INVALID_PARAM;
6840 rpcbuf_move(q_u->buffer, &r_u->buffer);
6841 buffer = r_u->buffer;
6843 DEBUG(4,("_spoolss_enumjobs\n"));
6845 *needed=0;
6846 *returned=0;
6848 /* lookup the printer snum and tdb entry */
6850 if (!get_printer_snum(p, handle, &snum, NULL))
6851 return WERR_BADFID;
6853 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6854 if ( !W_ERROR_IS_OK(wret) )
6855 return wret;
6857 *returned = print_queue_status(snum, &queue, &prt_status);
6858 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6860 if (*returned == 0) {
6861 SAFE_FREE(queue);
6862 free_a_printer(&ntprinter, 2);
6863 return WERR_OK;
6866 switch (level) {
6867 case 1:
6868 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6869 break;
6870 case 2:
6871 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6872 break;
6873 default:
6874 *returned=0;
6875 wret = WERR_UNKNOWN_LEVEL;
6876 break;
6879 SAFE_FREE(queue);
6880 free_a_printer( &ntprinter, 2 );
6881 return wret;
6884 /****************************************************************************
6885 ****************************************************************************/
6887 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6889 return WERR_OK;
6892 /****************************************************************************
6893 ****************************************************************************/
6895 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6897 POLICY_HND *handle = &q_u->handle;
6898 uint32 jobid = q_u->jobid;
6899 uint32 command = q_u->command;
6901 int snum;
6902 WERROR errcode = WERR_BADFUNC;
6904 if (!get_printer_snum(p, handle, &snum, NULL)) {
6905 return WERR_BADFID;
6908 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6909 return WERR_INVALID_PRINTER_NAME;
6912 switch (command) {
6913 case JOB_CONTROL_CANCEL:
6914 case JOB_CONTROL_DELETE:
6915 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6916 errcode = WERR_OK;
6918 break;
6919 case JOB_CONTROL_PAUSE:
6920 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6921 errcode = WERR_OK;
6923 break;
6924 case JOB_CONTROL_RESTART:
6925 case JOB_CONTROL_RESUME:
6926 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6927 errcode = WERR_OK;
6929 break;
6930 default:
6931 return WERR_UNKNOWN_LEVEL;
6934 return errcode;
6937 /****************************************************************************
6938 Enumerates all printer drivers at level 1.
6939 ****************************************************************************/
6941 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6943 int i;
6944 int ndrivers;
6945 uint32 version;
6946 fstring *list = NULL;
6947 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6948 DRIVER_INFO_1 *driver_info_1=NULL;
6949 WERROR result = WERR_OK;
6951 *returned=0;
6953 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6954 list=NULL;
6955 ndrivers=get_ntdrivers(&list, architecture, version);
6956 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6958 if(ndrivers == -1) {
6959 SAFE_FREE(driver_info_1);
6960 return WERR_NOMEM;
6963 if(ndrivers != 0) {
6964 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6965 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6966 SAFE_FREE(list);
6967 return WERR_NOMEM;
6971 for (i=0; i<ndrivers; i++) {
6972 WERROR status;
6973 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6974 ZERO_STRUCT(driver);
6975 status = get_a_printer_driver(&driver, 3, list[i],
6976 architecture, version);
6977 if (!W_ERROR_IS_OK(status)) {
6978 SAFE_FREE(list);
6979 SAFE_FREE(driver_info_1);
6980 return status;
6982 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6983 free_a_printer_driver(driver, 3);
6986 *returned+=ndrivers;
6987 SAFE_FREE(list);
6990 /* check the required size. */
6991 for (i=0; i<*returned; i++) {
6992 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6993 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6996 if (*needed > offered) {
6997 result = WERR_INSUFFICIENT_BUFFER;
6998 goto out;
7001 if (!rpcbuf_alloc_size(buffer, *needed)) {
7002 result = WERR_NOMEM;
7003 goto out;
7006 /* fill the buffer with the driver structures */
7007 for (i=0; i<*returned; i++) {
7008 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7009 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7012 out:
7013 SAFE_FREE(driver_info_1);
7015 if ( !W_ERROR_IS_OK(result) )
7016 *returned = 0;
7018 return result;
7021 /****************************************************************************
7022 Enumerates all printer drivers at level 2.
7023 ****************************************************************************/
7025 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7027 int i;
7028 int ndrivers;
7029 uint32 version;
7030 fstring *list = NULL;
7031 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7032 DRIVER_INFO_2 *driver_info_2=NULL;
7033 WERROR result = WERR_OK;
7035 *returned=0;
7037 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7038 list=NULL;
7039 ndrivers=get_ntdrivers(&list, architecture, version);
7040 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7042 if(ndrivers == -1) {
7043 SAFE_FREE(driver_info_2);
7044 return WERR_NOMEM;
7047 if(ndrivers != 0) {
7048 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7049 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7050 SAFE_FREE(list);
7051 return WERR_NOMEM;
7055 for (i=0; i<ndrivers; i++) {
7056 WERROR status;
7058 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7059 ZERO_STRUCT(driver);
7060 status = get_a_printer_driver(&driver, 3, list[i],
7061 architecture, version);
7062 if (!W_ERROR_IS_OK(status)) {
7063 SAFE_FREE(list);
7064 SAFE_FREE(driver_info_2);
7065 return status;
7067 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7068 free_a_printer_driver(driver, 3);
7071 *returned+=ndrivers;
7072 SAFE_FREE(list);
7075 /* check the required size. */
7076 for (i=0; i<*returned; i++) {
7077 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7078 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7081 if (*needed > offered) {
7082 result = WERR_INSUFFICIENT_BUFFER;
7083 goto out;
7086 if (!rpcbuf_alloc_size(buffer, *needed)) {
7087 result = WERR_NOMEM;
7088 goto out;
7091 /* fill the buffer with the form structures */
7092 for (i=0; i<*returned; i++) {
7093 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7094 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7097 out:
7098 SAFE_FREE(driver_info_2);
7100 if ( !W_ERROR_IS_OK(result) )
7101 *returned = 0;
7103 return result;
7106 /****************************************************************************
7107 Enumerates all printer drivers at level 3.
7108 ****************************************************************************/
7110 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7112 int i;
7113 int ndrivers;
7114 uint32 version;
7115 fstring *list = NULL;
7116 DRIVER_INFO_3 *driver_info_3=NULL;
7117 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7118 WERROR result = WERR_OK;
7120 *returned=0;
7122 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7123 list=NULL;
7124 ndrivers=get_ntdrivers(&list, architecture, version);
7125 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7127 if(ndrivers == -1) {
7128 SAFE_FREE(driver_info_3);
7129 return WERR_NOMEM;
7132 if(ndrivers != 0) {
7133 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7134 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7135 SAFE_FREE(list);
7136 return WERR_NOMEM;
7140 for (i=0; i<ndrivers; i++) {
7141 WERROR status;
7143 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7144 ZERO_STRUCT(driver);
7145 status = get_a_printer_driver(&driver, 3, list[i],
7146 architecture, version);
7147 if (!W_ERROR_IS_OK(status)) {
7148 SAFE_FREE(list);
7149 SAFE_FREE(driver_info_3);
7150 return status;
7152 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7153 free_a_printer_driver(driver, 3);
7156 *returned+=ndrivers;
7157 SAFE_FREE(list);
7160 /* check the required size. */
7161 for (i=0; i<*returned; i++) {
7162 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7163 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7166 if (*needed > offered) {
7167 result = WERR_INSUFFICIENT_BUFFER;
7168 goto out;
7171 if (!rpcbuf_alloc_size(buffer, *needed)) {
7172 result = WERR_NOMEM;
7173 goto out;
7176 /* fill the buffer with the driver structures */
7177 for (i=0; i<*returned; i++) {
7178 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7179 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7182 out:
7183 for (i=0; i<*returned; i++) {
7184 SAFE_FREE(driver_info_3[i].dependentfiles);
7187 SAFE_FREE(driver_info_3);
7189 if ( !W_ERROR_IS_OK(result) )
7190 *returned = 0;
7192 return result;
7195 /****************************************************************************
7196 Enumerates all printer drivers.
7197 ****************************************************************************/
7199 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7201 uint32 level = q_u->level;
7202 RPC_BUFFER *buffer = NULL;
7203 uint32 offered = q_u->offered;
7204 uint32 *needed = &r_u->needed;
7205 uint32 *returned = &r_u->returned;
7206 const char *cservername;
7207 fstring servername;
7208 fstring architecture;
7210 /* that's an [in out] buffer */
7212 if (!q_u->buffer && (offered!=0)) {
7213 return WERR_INVALID_PARAM;
7216 if (offered > MAX_RPC_DATA_SIZE) {
7217 return WERR_INVALID_PARAM;
7220 rpcbuf_move(q_u->buffer, &r_u->buffer);
7221 buffer = r_u->buffer;
7223 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7225 *needed = 0;
7226 *returned = 0;
7228 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7229 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7231 cservername = canon_servername(servername);
7233 if (!is_myname_or_ipaddr(cservername))
7234 return WERR_UNKNOWN_PRINTER_DRIVER;
7236 switch (level) {
7237 case 1:
7238 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7239 case 2:
7240 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7241 case 3:
7242 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7243 default:
7244 return WERR_UNKNOWN_LEVEL;
7248 /****************************************************************************
7249 ****************************************************************************/
7251 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7253 form->flag=list->flag;
7254 init_unistr(&form->name, list->name);
7255 form->width=list->width;
7256 form->length=list->length;
7257 form->left=list->left;
7258 form->top=list->top;
7259 form->right=list->right;
7260 form->bottom=list->bottom;
7263 /****************************************************************************
7264 ****************************************************************************/
7266 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7268 uint32 level = q_u->level;
7269 RPC_BUFFER *buffer = NULL;
7270 uint32 offered = q_u->offered;
7271 uint32 *needed = &r_u->needed;
7272 uint32 *numofforms = &r_u->numofforms;
7273 uint32 numbuiltinforms;
7275 nt_forms_struct *list=NULL;
7276 nt_forms_struct *builtinlist=NULL;
7277 FORM_1 *forms_1;
7278 int buffer_size=0;
7279 int i;
7281 /* that's an [in out] buffer */
7283 if (!q_u->buffer && (offered!=0) ) {
7284 return WERR_INVALID_PARAM;
7287 if (offered > MAX_RPC_DATA_SIZE) {
7288 return WERR_INVALID_PARAM;
7291 rpcbuf_move(q_u->buffer, &r_u->buffer);
7292 buffer = r_u->buffer;
7294 DEBUG(4,("_spoolss_enumforms\n"));
7295 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7296 DEBUGADD(5,("Info level [%d]\n", level));
7298 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7299 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7300 *numofforms = get_ntforms(&list);
7301 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7302 *numofforms += numbuiltinforms;
7304 if (*numofforms == 0) {
7305 SAFE_FREE(builtinlist);
7306 SAFE_FREE(list);
7307 return WERR_NO_MORE_ITEMS;
7310 switch (level) {
7311 case 1:
7312 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7313 SAFE_FREE(builtinlist);
7314 SAFE_FREE(list);
7315 *numofforms=0;
7316 return WERR_NOMEM;
7319 /* construct the list of form structures */
7320 for (i=0; i<numbuiltinforms; i++) {
7321 DEBUGADD(6,("Filling form number [%d]\n",i));
7322 fill_form_1(&forms_1[i], &builtinlist[i]);
7325 SAFE_FREE(builtinlist);
7327 for (; i<*numofforms; i++) {
7328 DEBUGADD(6,("Filling form number [%d]\n",i));
7329 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7332 SAFE_FREE(list);
7334 /* check the required size. */
7335 for (i=0; i<numbuiltinforms; i++) {
7336 DEBUGADD(6,("adding form [%d]'s size\n",i));
7337 buffer_size += spoolss_size_form_1(&forms_1[i]);
7339 for (; i<*numofforms; i++) {
7340 DEBUGADD(6,("adding form [%d]'s size\n",i));
7341 buffer_size += spoolss_size_form_1(&forms_1[i]);
7344 *needed=buffer_size;
7346 if (*needed > offered) {
7347 SAFE_FREE(forms_1);
7348 *numofforms=0;
7349 return WERR_INSUFFICIENT_BUFFER;
7352 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7353 SAFE_FREE(forms_1);
7354 *numofforms=0;
7355 return WERR_NOMEM;
7358 /* fill the buffer with the form structures */
7359 for (i=0; i<numbuiltinforms; i++) {
7360 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7361 smb_io_form_1("", buffer, &forms_1[i], 0);
7363 for (; i<*numofforms; i++) {
7364 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7365 smb_io_form_1("", buffer, &forms_1[i], 0);
7368 SAFE_FREE(forms_1);
7370 return WERR_OK;
7372 default:
7373 SAFE_FREE(list);
7374 SAFE_FREE(builtinlist);
7375 return WERR_UNKNOWN_LEVEL;
7379 /****************************************************************************
7380 ****************************************************************************/
7382 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7384 uint32 level = q_u->level;
7385 UNISTR2 *uni_formname = &q_u->formname;
7386 RPC_BUFFER *buffer = NULL;
7387 uint32 offered = q_u->offered;
7388 uint32 *needed = &r_u->needed;
7390 nt_forms_struct *list=NULL;
7391 nt_forms_struct builtin_form;
7392 bool foundBuiltin;
7393 FORM_1 form_1;
7394 fstring form_name;
7395 int buffer_size=0;
7396 int numofforms=0, i=0;
7398 /* that's an [in out] buffer */
7400 if (!q_u->buffer && (offered!=0)) {
7401 return WERR_INVALID_PARAM;
7404 rpcbuf_move(q_u->buffer, &r_u->buffer);
7405 buffer = r_u->buffer;
7407 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7409 DEBUG(4,("_spoolss_getform\n"));
7410 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7411 DEBUGADD(5,("Info level [%d]\n", level));
7413 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7414 if (!foundBuiltin) {
7415 numofforms = get_ntforms(&list);
7416 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7418 if (numofforms == 0)
7419 return WERR_BADFID;
7422 switch (level) {
7423 case 1:
7424 if (foundBuiltin) {
7425 fill_form_1(&form_1, &builtin_form);
7426 } else {
7428 /* Check if the requested name is in the list of form structures */
7429 for (i=0; i<numofforms; i++) {
7431 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7433 if (strequal(form_name, list[i].name)) {
7434 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7435 fill_form_1(&form_1, &list[i]);
7436 break;
7440 SAFE_FREE(list);
7441 if (i == numofforms) {
7442 return WERR_BADFID;
7445 /* check the required size. */
7447 *needed=spoolss_size_form_1(&form_1);
7449 if (*needed > offered)
7450 return WERR_INSUFFICIENT_BUFFER;
7452 if (!rpcbuf_alloc_size(buffer, buffer_size))
7453 return WERR_NOMEM;
7455 /* fill the buffer with the form structures */
7456 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7457 smb_io_form_1("", buffer, &form_1, 0);
7459 return WERR_OK;
7461 default:
7462 SAFE_FREE(list);
7463 return WERR_UNKNOWN_LEVEL;
7467 /****************************************************************************
7468 ****************************************************************************/
7470 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7472 init_unistr(&port->port_name, name);
7475 /****************************************************************************
7476 TODO: This probably needs distinguish between TCP/IP and Local ports
7477 somehow.
7478 ****************************************************************************/
7480 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7482 init_unistr(&port->port_name, name);
7483 init_unistr(&port->monitor_name, "Local Monitor");
7484 init_unistr(&port->description, SPL_LOCAL_PORT );
7485 port->port_type=PORT_TYPE_WRITE;
7486 port->reserved=0x0;
7490 /****************************************************************************
7491 wrapper around the enumer ports command
7492 ****************************************************************************/
7494 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7496 char *cmd = lp_enumports_cmd();
7497 char **qlines = NULL;
7498 char *command = NULL;
7499 int numlines;
7500 int ret;
7501 int fd;
7503 *count = 0;
7504 *lines = NULL;
7506 /* if no hook then just fill in the default port */
7508 if ( !*cmd ) {
7509 if (!(qlines = SMB_MALLOC_ARRAY( char*, 2 ))) {
7510 return WERR_NOMEM;
7512 if (!(qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME ))) {
7513 SAFE_FREE(qlines);
7514 return WERR_NOMEM;
7516 qlines[1] = NULL;
7517 numlines = 1;
7519 else {
7520 /* we have a valid enumport command */
7522 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7523 if (!command) {
7524 return WERR_NOMEM;
7527 DEBUG(10,("Running [%s]\n", command));
7528 ret = smbrun(command, &fd);
7529 DEBUG(10,("Returned [%d]\n", ret));
7530 TALLOC_FREE(command);
7531 if (ret != 0) {
7532 if (fd != -1) {
7533 close(fd);
7535 return WERR_ACCESS_DENIED;
7538 numlines = 0;
7539 qlines = fd_lines_load(fd, &numlines, 0);
7540 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7541 close(fd);
7544 *count = numlines;
7545 *lines = qlines;
7547 return WERR_OK;
7550 /****************************************************************************
7551 enumports level 1.
7552 ****************************************************************************/
7554 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7556 PORT_INFO_1 *ports=NULL;
7557 int i=0;
7558 WERROR result = WERR_OK;
7559 char **qlines = NULL;
7560 int numlines = 0;
7562 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7563 if (!W_ERROR_IS_OK(result)) {
7564 file_lines_free(qlines);
7565 return result;
7568 if(numlines) {
7569 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7570 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7571 dos_errstr(WERR_NOMEM)));
7572 file_lines_free(qlines);
7573 return WERR_NOMEM;
7576 for (i=0; i<numlines; i++) {
7577 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7578 fill_port_1(&ports[i], qlines[i]);
7581 file_lines_free(qlines);
7583 *returned = numlines;
7585 /* check the required size. */
7586 for (i=0; i<*returned; i++) {
7587 DEBUGADD(6,("adding port [%d]'s size\n", i));
7588 *needed += spoolss_size_port_info_1(&ports[i]);
7591 if (*needed > offered) {
7592 result = WERR_INSUFFICIENT_BUFFER;
7593 goto out;
7596 if (!rpcbuf_alloc_size(buffer, *needed)) {
7597 result = WERR_NOMEM;
7598 goto out;
7601 /* fill the buffer with the ports structures */
7602 for (i=0; i<*returned; i++) {
7603 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7604 smb_io_port_1("", buffer, &ports[i], 0);
7607 out:
7608 SAFE_FREE(ports);
7610 if ( !W_ERROR_IS_OK(result) )
7611 *returned = 0;
7613 return result;
7616 /****************************************************************************
7617 enumports level 2.
7618 ****************************************************************************/
7620 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7622 PORT_INFO_2 *ports=NULL;
7623 int i=0;
7624 WERROR result = WERR_OK;
7625 char **qlines = NULL;
7626 int numlines = 0;
7628 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7629 if ( !W_ERROR_IS_OK(result)) {
7630 file_lines_free(qlines);
7631 return result;
7634 if(numlines) {
7635 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7636 file_lines_free(qlines);
7637 return WERR_NOMEM;
7640 for (i=0; i<numlines; i++) {
7641 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7642 fill_port_2(&(ports[i]), qlines[i]);
7646 file_lines_free(qlines);
7648 *returned = numlines;
7650 /* check the required size. */
7651 for (i=0; i<*returned; i++) {
7652 DEBUGADD(6,("adding port [%d]'s size\n", i));
7653 *needed += spoolss_size_port_info_2(&ports[i]);
7656 if (*needed > offered) {
7657 result = WERR_INSUFFICIENT_BUFFER;
7658 goto out;
7661 if (!rpcbuf_alloc_size(buffer, *needed)) {
7662 result = WERR_NOMEM;
7663 goto out;
7666 /* fill the buffer with the ports structures */
7667 for (i=0; i<*returned; i++) {
7668 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7669 smb_io_port_2("", buffer, &ports[i], 0);
7672 out:
7673 SAFE_FREE(ports);
7675 if ( !W_ERROR_IS_OK(result) )
7676 *returned = 0;
7678 return result;
7681 /****************************************************************************
7682 enumports.
7683 ****************************************************************************/
7685 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7687 uint32 level = q_u->level;
7688 RPC_BUFFER *buffer = NULL;
7689 uint32 offered = q_u->offered;
7690 uint32 *needed = &r_u->needed;
7691 uint32 *returned = &r_u->returned;
7693 /* that's an [in out] buffer */
7695 if (!q_u->buffer && (offered!=0)) {
7696 return WERR_INVALID_PARAM;
7699 if (offered > MAX_RPC_DATA_SIZE) {
7700 return WERR_INVALID_PARAM;
7703 rpcbuf_move(q_u->buffer, &r_u->buffer);
7704 buffer = r_u->buffer;
7706 DEBUG(4,("_spoolss_enumports\n"));
7708 *returned=0;
7709 *needed=0;
7711 switch (level) {
7712 case 1:
7713 return enumports_level_1(buffer, offered, needed, returned);
7714 case 2:
7715 return enumports_level_2(buffer, offered, needed, returned);
7716 default:
7717 return WERR_UNKNOWN_LEVEL;
7721 /****************************************************************************
7722 ****************************************************************************/
7724 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7725 const SPOOL_PRINTER_INFO_LEVEL *info,
7726 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7727 uint32 user_switch, const SPOOL_USER_CTR *user,
7728 POLICY_HND *handle)
7730 NT_PRINTER_INFO_LEVEL *printer = NULL;
7731 fstring name;
7732 int snum;
7733 WERROR err = WERR_OK;
7735 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7736 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7737 return WERR_NOMEM;
7740 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7741 if (!convert_printer_info(info, printer, 2)) {
7742 free_a_printer(&printer, 2);
7743 return WERR_NOMEM;
7746 /* check to see if the printer already exists */
7748 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7749 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7750 printer->info_2->sharename));
7751 free_a_printer(&printer, 2);
7752 return WERR_PRINTER_ALREADY_EXISTS;
7755 /* FIXME!!! smbd should check to see if the driver is installed before
7756 trying to add a printer like this --jerry */
7758 if (*lp_addprinter_cmd() ) {
7759 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
7760 free_a_printer(&printer,2);
7761 return WERR_ACCESS_DENIED;
7763 } else {
7764 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7765 "smb.conf parameter \"addprinter command\" is defined. This"
7766 "parameter must exist for this call to succeed\n",
7767 printer->info_2->sharename ));
7770 /* use our primary netbios name since get_a_printer() will convert
7771 it to what the client expects on a case by case basis */
7773 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7774 printer->info_2->sharename);
7777 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7778 free_a_printer(&printer,2);
7779 return WERR_ACCESS_DENIED;
7782 /* you must be a printer admin to add a new printer */
7783 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7784 free_a_printer(&printer,2);
7785 return WERR_ACCESS_DENIED;
7789 * Do sanity check on the requested changes for Samba.
7792 if (!check_printer_ok(printer->info_2, snum)) {
7793 free_a_printer(&printer,2);
7794 return WERR_INVALID_PARAM;
7798 * When a printer is created, the drivername bound to the printer is used
7799 * to lookup previously saved driver initialization info, which is then
7800 * bound to the new printer, simulating what happens in the Windows arch.
7803 if (!devmode)
7805 set_driver_init(printer, 2);
7807 else
7809 /* A valid devmode was included, convert and link it
7811 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7813 if (!convert_devicemode(printer->info_2->printername, devmode,
7814 &printer->info_2->devmode))
7815 return WERR_NOMEM;
7818 /* write the ASCII on disk */
7819 err = mod_a_printer(printer, 2);
7820 if (!W_ERROR_IS_OK(err)) {
7821 free_a_printer(&printer,2);
7822 return err;
7825 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7826 /* Handle open failed - remove addition. */
7827 del_a_printer(printer->info_2->sharename);
7828 free_a_printer(&printer,2);
7829 return WERR_ACCESS_DENIED;
7832 update_c_setprinter(False);
7833 free_a_printer(&printer,2);
7835 return WERR_OK;
7838 /****************************************************************************
7839 ****************************************************************************/
7841 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7843 UNISTR2 *uni_srv_name = q_u->server_name;
7844 uint32 level = q_u->level;
7845 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7846 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7847 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7848 uint32 user_switch = q_u->user_switch;
7849 SPOOL_USER_CTR *user = &q_u->user_ctr;
7850 POLICY_HND *handle = &r_u->handle;
7852 switch (level) {
7853 case 1:
7854 /* we don't handle yet */
7855 /* but I know what to do ... */
7856 return WERR_UNKNOWN_LEVEL;
7857 case 2:
7858 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7859 devmode, sdb,
7860 user_switch, user, handle);
7861 default:
7862 return WERR_UNKNOWN_LEVEL;
7866 /****************************************************************************
7867 ****************************************************************************/
7869 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7871 uint32 level = q_u->level;
7872 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7873 WERROR err = WERR_OK;
7874 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7875 fstring driver_name;
7876 uint32 version;
7878 ZERO_STRUCT(driver);
7880 if (!convert_printer_driver_info(info, &driver, level)) {
7881 err = WERR_NOMEM;
7882 goto done;
7885 DEBUG(5,("Cleaning driver's information\n"));
7886 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7887 if (!W_ERROR_IS_OK(err))
7888 goto done;
7890 DEBUG(5,("Moving driver to final destination\n"));
7891 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7892 goto done;
7895 if (add_a_printer_driver(driver, level)!=0) {
7896 err = WERR_ACCESS_DENIED;
7897 goto done;
7900 switch(level) {
7901 case 3:
7902 fstrcpy(driver_name,
7903 driver.info_3->name ? driver.info_3->name : "");
7904 break;
7905 case 6:
7906 fstrcpy(driver_name,
7907 driver.info_6->name ? driver.info_6->name : "");
7908 break;
7912 * I think this is where he DrvUpgradePrinter() hook would be
7913 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7914 * server. Right now, we just need to send ourselves a message
7915 * to update each printer bound to this driver. --jerry
7918 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7919 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7920 driver_name));
7924 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7925 * decide if the driver init data should be deleted. The rules are:
7926 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7927 * 2) delete init data only if there is no 2k/Xp driver
7928 * 3) always delete init data
7929 * The generalized rule is always use init data from the highest order driver.
7930 * It is necessary to follow the driver install by an initialization step to
7931 * finish off this process.
7933 if (level == 3)
7934 version = driver.info_3->cversion;
7935 else if (level == 6)
7936 version = driver.info_6->version;
7937 else
7938 version = -1;
7939 switch (version) {
7941 * 9x printer driver - never delete init data
7943 case 0:
7944 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7945 driver_name));
7946 break;
7949 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7950 * there is no 2k/Xp driver init data for this driver name.
7952 case 2:
7954 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7956 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7958 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7960 if (!del_driver_init(driver_name))
7961 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7962 } else {
7964 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7966 free_a_printer_driver(driver1,3);
7967 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7968 driver_name));
7971 break;
7974 * 2k or Xp printer driver - always delete init data
7976 case 3:
7977 if (!del_driver_init(driver_name))
7978 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7979 break;
7981 default:
7982 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7983 break;
7987 done:
7988 free_a_printer_driver(driver, level);
7989 return err;
7992 /********************************************************************
7993 * spoolss_addprinterdriverex
7994 ********************************************************************/
7996 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7998 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7999 SPOOL_R_ADDPRINTERDRIVER r_u_local;
8002 * we only support the semantics of AddPrinterDriver()
8003 * i.e. only copy files that are newer than existing ones
8006 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
8007 return WERR_ACCESS_DENIED;
8009 ZERO_STRUCT(q_u_local);
8010 ZERO_STRUCT(r_u_local);
8012 /* just pass the information off to _spoolss_addprinterdriver() */
8013 q_u_local.server_name_ptr = q_u->server_name_ptr;
8014 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
8015 q_u_local.level = q_u->level;
8016 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
8018 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
8021 /****************************************************************************
8022 ****************************************************************************/
8024 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
8026 init_unistr(&info->name, name);
8029 /****************************************************************************
8030 ****************************************************************************/
8032 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
8034 char *path = NULL;
8035 char *long_archi = NULL;
8036 char *servername = NULL;
8037 const char *pservername = NULL;
8038 const char *short_archi;
8039 DRIVER_DIRECTORY_1 *info=NULL;
8040 WERROR result = WERR_OK;
8041 TALLOC_CTX *ctx = talloc_tos();
8043 servername = unistr2_to_ascii_talloc(ctx, name);
8044 if (!servername) {
8045 return WERR_NOMEM;
8047 long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
8048 if (!long_archi) {
8049 return WERR_NOMEM;
8052 pservername = canon_servername(servername);
8054 if ( !is_myname_or_ipaddr(pservername))
8055 return WERR_INVALID_PARAM;
8057 if (!(short_archi = get_short_archi(long_archi)))
8058 return WERR_INVALID_ENVIRONMENT;
8060 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8061 return WERR_NOMEM;
8063 path = talloc_asprintf(ctx,
8064 "\\\\%s\\print$\\%s", pservername, short_archi);
8065 if (!path) {
8066 result = WERR_NOMEM;
8067 goto out;
8070 DEBUG(4,("printer driver directory: [%s]\n", path));
8072 fill_driverdir_1(info, path);
8074 *needed += spoolss_size_driverdir_info_1(info);
8076 if (*needed > offered) {
8077 result = WERR_INSUFFICIENT_BUFFER;
8078 goto out;
8081 if (!rpcbuf_alloc_size(buffer, *needed)) {
8082 result = WERR_NOMEM;
8083 goto out;
8086 smb_io_driverdir_1("", buffer, info, 0);
8088 out:
8089 SAFE_FREE(info);
8091 return result;
8094 /****************************************************************************
8095 ****************************************************************************/
8097 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8099 UNISTR2 *name = &q_u->name;
8100 UNISTR2 *uni_environment = &q_u->environment;
8101 uint32 level = q_u->level;
8102 RPC_BUFFER *buffer = NULL;
8103 uint32 offered = q_u->offered;
8104 uint32 *needed = &r_u->needed;
8106 /* that's an [in out] buffer */
8108 if (!q_u->buffer && (offered!=0)) {
8109 return WERR_INVALID_PARAM;
8112 if (offered > MAX_RPC_DATA_SIZE) {
8113 return WERR_INVALID_PARAM;
8116 rpcbuf_move(q_u->buffer, &r_u->buffer);
8117 buffer = r_u->buffer;
8119 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8121 *needed=0;
8123 switch(level) {
8124 case 1:
8125 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8126 default:
8127 return WERR_UNKNOWN_LEVEL;
8131 /****************************************************************************
8132 ****************************************************************************/
8134 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8136 POLICY_HND *handle = &q_u->handle;
8137 uint32 idx = q_u->index;
8138 uint32 in_value_len = q_u->valuesize;
8139 uint32 in_data_len = q_u->datasize;
8140 uint32 *out_max_value_len = &r_u->valuesize;
8141 uint16 **out_value = &r_u->value;
8142 uint32 *out_value_len = &r_u->realvaluesize;
8143 uint32 *out_type = &r_u->type;
8144 uint32 *out_max_data_len = &r_u->datasize;
8145 uint8 **data_out = &r_u->data;
8146 uint32 *out_data_len = &r_u->realdatasize;
8148 NT_PRINTER_INFO_LEVEL *printer = NULL;
8150 uint32 biggest_valuesize;
8151 uint32 biggest_datasize;
8152 uint32 data_len;
8153 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8154 int snum;
8155 WERROR result;
8156 REGISTRY_VALUE *val = NULL;
8157 NT_PRINTER_DATA *p_data;
8158 int i, key_index, num_values;
8159 int name_length;
8161 *out_type = 0;
8163 *out_max_data_len = 0;
8164 *data_out = NULL;
8165 *out_data_len = 0;
8167 DEBUG(5,("spoolss_enumprinterdata\n"));
8169 if (!Printer) {
8170 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8171 return WERR_BADFID;
8174 if (!get_printer_snum(p,handle, &snum, NULL))
8175 return WERR_BADFID;
8177 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8178 if (!W_ERROR_IS_OK(result))
8179 return result;
8181 p_data = printer->info_2->data;
8182 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8184 result = WERR_OK;
8187 * The NT machine wants to know the biggest size of value and data
8189 * cf: MSDN EnumPrinterData remark section
8192 if ( !in_value_len && !in_data_len && (key_index != -1) )
8194 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8196 biggest_valuesize = 0;
8197 biggest_datasize = 0;
8199 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8201 for ( i=0; i<num_values; i++ )
8203 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8205 name_length = strlen(val->valuename);
8206 if ( strlen(val->valuename) > biggest_valuesize )
8207 biggest_valuesize = name_length;
8209 if ( val->size > biggest_datasize )
8210 biggest_datasize = val->size;
8212 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8213 biggest_datasize));
8216 /* the value is an UNICODE string but real_value_size is the length
8217 in bytes including the trailing 0 */
8219 *out_value_len = 2 * (1+biggest_valuesize);
8220 *out_data_len = biggest_datasize;
8222 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8224 goto done;
8228 * the value len is wrong in NT sp3
8229 * that's the number of bytes not the number of unicode chars
8232 if ( key_index != -1 )
8233 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8235 if ( !val )
8238 /* out_value should default to "" or else NT4 has
8239 problems unmarshalling the response */
8241 *out_max_value_len=(in_value_len/sizeof(uint16));
8243 if (in_value_len) {
8244 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8246 result = WERR_NOMEM;
8247 goto done;
8249 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8250 } else {
8251 *out_value=NULL;
8252 *out_value_len = 0;
8255 /* the data is counted in bytes */
8257 *out_max_data_len = in_data_len;
8258 *out_data_len = in_data_len;
8260 /* only allocate when given a non-zero data_len */
8262 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8264 result = WERR_NOMEM;
8265 goto done;
8268 result = WERR_NO_MORE_ITEMS;
8270 else
8273 * the value is:
8274 * - counted in bytes in the request
8275 * - counted in UNICODE chars in the max reply
8276 * - counted in bytes in the real size
8278 * take a pause *before* coding not *during* coding
8281 /* name */
8282 *out_max_value_len=(in_value_len/sizeof(uint16));
8283 if (in_value_len) {
8284 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8286 result = WERR_NOMEM;
8287 goto done;
8290 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8291 } else {
8292 *out_value = NULL;
8293 *out_value_len = 0;
8296 /* type */
8298 *out_type = regval_type( val );
8300 /* data - counted in bytes */
8302 *out_max_data_len = in_data_len;
8303 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8305 result = WERR_NOMEM;
8306 goto done;
8308 data_len = regval_size(val);
8309 if ( *data_out && data_len )
8310 memcpy( *data_out, regval_data_p(val), data_len );
8311 *out_data_len = data_len;
8314 done:
8315 free_a_printer(&printer, 2);
8316 return result;
8319 /****************************************************************************
8320 ****************************************************************************/
8322 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8324 POLICY_HND *handle = &q_u->handle;
8325 UNISTR2 *value = &q_u->value;
8326 uint32 type = q_u->type;
8327 uint8 *data = q_u->data;
8328 uint32 real_len = q_u->real_len;
8330 NT_PRINTER_INFO_LEVEL *printer = NULL;
8331 int snum=0;
8332 WERROR status = WERR_OK;
8333 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8334 fstring valuename;
8336 DEBUG(5,("spoolss_setprinterdata\n"));
8338 if (!Printer) {
8339 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8340 return WERR_BADFID;
8343 if ( Printer->printer_type == SPLHND_SERVER ) {
8344 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8345 return WERR_INVALID_PARAM;
8348 if (!get_printer_snum(p,handle, &snum, NULL))
8349 return WERR_BADFID;
8352 * Access check : NT returns "access denied" if you make a
8353 * SetPrinterData call without the necessary privildge.
8354 * we were originally returning OK if nothing changed
8355 * which made Win2k issue **a lot** of SetPrinterData
8356 * when connecting to a printer --jerry
8359 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8361 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8362 status = WERR_ACCESS_DENIED;
8363 goto done;
8366 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8367 if (!W_ERROR_IS_OK(status))
8368 return status;
8370 unistr2_to_ascii(valuename, value, sizeof(valuename));
8373 * When client side code sets a magic printer data key, detect it and save
8374 * the current printer data and the magic key's data (its the DEVMODE) for
8375 * future printer/driver initializations.
8377 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8379 /* Set devmode and printer initialization info */
8380 status = save_driver_init( printer, 2, data, real_len );
8382 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8384 else
8386 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8387 type, data, real_len );
8388 if ( W_ERROR_IS_OK(status) )
8389 status = mod_a_printer(printer, 2);
8392 done:
8393 free_a_printer(&printer, 2);
8395 return status;
8398 /****************************************************************************
8399 ****************************************************************************/
8401 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8403 POLICY_HND *handle = &q_u->handle;
8404 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8405 int snum;
8407 DEBUG(5,("_spoolss_resetprinter\n"));
8410 * All we do is to check to see if the handle and queue is valid.
8411 * This call really doesn't mean anything to us because we only
8412 * support RAW printing. --jerry
8415 if (!Printer) {
8416 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8417 return WERR_BADFID;
8420 if (!get_printer_snum(p,handle, &snum, NULL))
8421 return WERR_BADFID;
8424 /* blindly return success */
8425 return WERR_OK;
8429 /****************************************************************************
8430 ****************************************************************************/
8432 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8434 POLICY_HND *handle = &q_u->handle;
8435 UNISTR2 *value = &q_u->valuename;
8437 NT_PRINTER_INFO_LEVEL *printer = NULL;
8438 int snum=0;
8439 WERROR status = WERR_OK;
8440 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8441 char *valuename = NULL;
8442 TALLOC_CTX *ctx = p->mem_ctx;
8444 DEBUG(5,("spoolss_deleteprinterdata\n"));
8446 if (!Printer) {
8447 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8448 return WERR_BADFID;
8451 if (!get_printer_snum(p, handle, &snum, NULL))
8452 return WERR_BADFID;
8454 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8455 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8456 return WERR_ACCESS_DENIED;
8459 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8460 if (!W_ERROR_IS_OK(status))
8461 return status;
8463 valuename = unistr2_to_ascii_talloc(ctx, value);
8464 if (!valuename) {
8465 free_a_printer(&printer, 2);
8466 return WERR_NOMEM;
8469 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8471 if ( W_ERROR_IS_OK(status) )
8472 mod_a_printer( printer, 2 );
8474 free_a_printer(&printer, 2);
8475 TALLOC_FREE(valuename);
8477 return status;
8480 /****************************************************************************
8481 ****************************************************************************/
8483 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8485 POLICY_HND *handle = &q_u->handle;
8486 FORM *form = &q_u->form;
8487 nt_forms_struct tmpForm;
8488 int snum;
8489 WERROR status = WERR_OK;
8490 NT_PRINTER_INFO_LEVEL *printer = NULL;
8492 int count=0;
8493 nt_forms_struct *list=NULL;
8494 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8496 DEBUG(5,("spoolss_addform\n"));
8498 if (!Printer) {
8499 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8500 return WERR_BADFID;
8504 /* forms can be added on printer of on the print server handle */
8506 if ( Printer->printer_type == SPLHND_PRINTER )
8508 if (!get_printer_snum(p,handle, &snum, NULL))
8509 return WERR_BADFID;
8511 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8512 if (!W_ERROR_IS_OK(status))
8513 goto done;
8516 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8517 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8518 status = WERR_ACCESS_DENIED;
8519 goto done;
8522 /* can't add if builtin */
8524 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8525 status = WERR_ALREADY_EXISTS;
8526 goto done;
8529 count = get_ntforms(&list);
8531 if(!add_a_form(&list, form, &count)) {
8532 status = WERR_NOMEM;
8533 goto done;
8536 write_ntforms(&list, count);
8539 * ChangeID must always be set if this is a printer
8542 if ( Printer->printer_type == SPLHND_PRINTER )
8543 status = mod_a_printer(printer, 2);
8545 done:
8546 if ( printer )
8547 free_a_printer(&printer, 2);
8548 SAFE_FREE(list);
8550 return status;
8553 /****************************************************************************
8554 ****************************************************************************/
8556 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8558 POLICY_HND *handle = &q_u->handle;
8559 UNISTR2 *form_name = &q_u->name;
8560 nt_forms_struct tmpForm;
8561 int count=0;
8562 nt_forms_struct *list=NULL;
8563 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8564 int snum;
8565 WERROR status = WERR_OK;
8566 NT_PRINTER_INFO_LEVEL *printer = NULL;
8568 DEBUG(5,("spoolss_deleteform\n"));
8570 if (!Printer) {
8571 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8572 return WERR_BADFID;
8575 /* forms can be deleted on printer of on the print server handle */
8577 if ( Printer->printer_type == SPLHND_PRINTER )
8579 if (!get_printer_snum(p,handle, &snum, NULL))
8580 return WERR_BADFID;
8582 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8583 if (!W_ERROR_IS_OK(status))
8584 goto done;
8587 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8588 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8589 status = WERR_ACCESS_DENIED;
8590 goto done;
8593 /* can't delete if builtin */
8595 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8596 status = WERR_INVALID_PARAM;
8597 goto done;
8600 count = get_ntforms(&list);
8602 if ( !delete_a_form(&list, form_name, &count, &status ))
8603 goto done;
8606 * ChangeID must always be set if this is a printer
8609 if ( Printer->printer_type == SPLHND_PRINTER )
8610 status = mod_a_printer(printer, 2);
8612 done:
8613 if ( printer )
8614 free_a_printer(&printer, 2);
8615 SAFE_FREE(list);
8617 return status;
8620 /****************************************************************************
8621 ****************************************************************************/
8623 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8625 POLICY_HND *handle = &q_u->handle;
8626 FORM *form = &q_u->form;
8627 nt_forms_struct tmpForm;
8628 int snum;
8629 WERROR status = WERR_OK;
8630 NT_PRINTER_INFO_LEVEL *printer = NULL;
8632 int count=0;
8633 nt_forms_struct *list=NULL;
8634 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8636 DEBUG(5,("spoolss_setform\n"));
8638 if (!Printer) {
8639 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8640 return WERR_BADFID;
8643 /* forms can be modified on printer of on the print server handle */
8645 if ( Printer->printer_type == SPLHND_PRINTER )
8647 if (!get_printer_snum(p,handle, &snum, NULL))
8648 return WERR_BADFID;
8650 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8651 if (!W_ERROR_IS_OK(status))
8652 goto done;
8655 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8656 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8657 status = WERR_ACCESS_DENIED;
8658 goto done;
8661 /* can't set if builtin */
8662 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8663 status = WERR_INVALID_PARAM;
8664 goto done;
8667 count = get_ntforms(&list);
8668 update_a_form(&list, form, count);
8669 write_ntforms(&list, count);
8672 * ChangeID must always be set if this is a printer
8675 if ( Printer->printer_type == SPLHND_PRINTER )
8676 status = mod_a_printer(printer, 2);
8679 done:
8680 if ( printer )
8681 free_a_printer(&printer, 2);
8682 SAFE_FREE(list);
8684 return status;
8687 /****************************************************************************
8688 enumprintprocessors level 1.
8689 ****************************************************************************/
8691 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8693 PRINTPROCESSOR_1 *info_1=NULL;
8694 WERROR result = WERR_OK;
8696 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8697 return WERR_NOMEM;
8699 (*returned) = 0x1;
8701 init_unistr(&info_1->name, "winprint");
8703 *needed += spoolss_size_printprocessor_info_1(info_1);
8705 if (*needed > offered) {
8706 result = WERR_INSUFFICIENT_BUFFER;
8707 goto out;
8710 if (!rpcbuf_alloc_size(buffer, *needed)) {
8711 result = WERR_NOMEM;
8712 goto out;
8715 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8717 out:
8718 SAFE_FREE(info_1);
8720 if ( !W_ERROR_IS_OK(result) )
8721 *returned = 0;
8723 return result;
8726 /****************************************************************************
8727 ****************************************************************************/
8729 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8731 uint32 level = q_u->level;
8732 RPC_BUFFER *buffer = NULL;
8733 uint32 offered = q_u->offered;
8734 uint32 *needed = &r_u->needed;
8735 uint32 *returned = &r_u->returned;
8737 /* that's an [in out] buffer */
8739 if (!q_u->buffer && (offered!=0)) {
8740 return WERR_INVALID_PARAM;
8743 if (offered > MAX_RPC_DATA_SIZE) {
8744 return WERR_INVALID_PARAM;
8747 rpcbuf_move(q_u->buffer, &r_u->buffer);
8748 buffer = r_u->buffer;
8750 DEBUG(5,("spoolss_enumprintprocessors\n"));
8753 * Enumerate the print processors ...
8755 * Just reply with "winprint", to keep NT happy
8756 * and I can use my nice printer checker.
8759 *returned=0;
8760 *needed=0;
8762 switch (level) {
8763 case 1:
8764 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8765 default:
8766 return WERR_UNKNOWN_LEVEL;
8770 /****************************************************************************
8771 enumprintprocdatatypes level 1.
8772 ****************************************************************************/
8774 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8776 PRINTPROCDATATYPE_1 *info_1=NULL;
8777 WERROR result = WERR_OK;
8779 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8780 return WERR_NOMEM;
8782 (*returned) = 0x1;
8784 init_unistr(&info_1->name, "RAW");
8786 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8788 if (*needed > offered) {
8789 result = WERR_INSUFFICIENT_BUFFER;
8790 goto out;
8793 if (!rpcbuf_alloc_size(buffer, *needed)) {
8794 result = WERR_NOMEM;
8795 goto out;
8798 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8800 out:
8801 SAFE_FREE(info_1);
8803 if ( !W_ERROR_IS_OK(result) )
8804 *returned = 0;
8806 return result;
8809 /****************************************************************************
8810 ****************************************************************************/
8812 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8814 uint32 level = q_u->level;
8815 RPC_BUFFER *buffer = NULL;
8816 uint32 offered = q_u->offered;
8817 uint32 *needed = &r_u->needed;
8818 uint32 *returned = &r_u->returned;
8820 /* that's an [in out] buffer */
8822 if (!q_u->buffer && (offered!=0)) {
8823 return WERR_INVALID_PARAM;
8826 if (offered > MAX_RPC_DATA_SIZE) {
8827 return WERR_INVALID_PARAM;
8830 rpcbuf_move(q_u->buffer, &r_u->buffer);
8831 buffer = r_u->buffer;
8833 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8835 *returned=0;
8836 *needed=0;
8838 switch (level) {
8839 case 1:
8840 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8841 default:
8842 return WERR_UNKNOWN_LEVEL;
8846 /****************************************************************************
8847 enumprintmonitors level 1.
8848 ****************************************************************************/
8850 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8852 PRINTMONITOR_1 *info_1;
8853 WERROR result = WERR_OK;
8854 int i;
8856 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8857 return WERR_NOMEM;
8859 *returned = 2;
8861 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8862 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8864 for ( i=0; i<*returned; i++ ) {
8865 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8868 if (*needed > offered) {
8869 result = WERR_INSUFFICIENT_BUFFER;
8870 goto out;
8873 if (!rpcbuf_alloc_size(buffer, *needed)) {
8874 result = WERR_NOMEM;
8875 goto out;
8878 for ( i=0; i<*returned; i++ ) {
8879 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8882 out:
8883 SAFE_FREE(info_1);
8885 if ( !W_ERROR_IS_OK(result) )
8886 *returned = 0;
8888 return result;
8891 /****************************************************************************
8892 enumprintmonitors level 2.
8893 ****************************************************************************/
8895 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8897 PRINTMONITOR_2 *info_2;
8898 WERROR result = WERR_OK;
8899 int i;
8901 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8902 return WERR_NOMEM;
8904 *returned = 2;
8906 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8907 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8908 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8910 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8911 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8912 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8914 for ( i=0; i<*returned; i++ ) {
8915 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8918 if (*needed > offered) {
8919 result = WERR_INSUFFICIENT_BUFFER;
8920 goto out;
8923 if (!rpcbuf_alloc_size(buffer, *needed)) {
8924 result = WERR_NOMEM;
8925 goto out;
8928 for ( i=0; i<*returned; i++ ) {
8929 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8932 out:
8933 SAFE_FREE(info_2);
8935 if ( !W_ERROR_IS_OK(result) )
8936 *returned = 0;
8938 return result;
8941 /****************************************************************************
8942 ****************************************************************************/
8944 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8946 uint32 level = q_u->level;
8947 RPC_BUFFER *buffer = NULL;
8948 uint32 offered = q_u->offered;
8949 uint32 *needed = &r_u->needed;
8950 uint32 *returned = &r_u->returned;
8952 /* that's an [in out] buffer */
8954 if (!q_u->buffer && (offered!=0)) {
8955 return WERR_INVALID_PARAM;
8958 if (offered > MAX_RPC_DATA_SIZE) {
8959 return WERR_INVALID_PARAM;
8962 rpcbuf_move(q_u->buffer, &r_u->buffer);
8963 buffer = r_u->buffer;
8965 DEBUG(5,("spoolss_enumprintmonitors\n"));
8968 * Enumerate the print monitors ...
8970 * Just reply with "Local Port", to keep NT happy
8971 * and I can use my nice printer checker.
8974 *returned=0;
8975 *needed=0;
8977 switch (level) {
8978 case 1:
8979 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8980 case 2:
8981 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8982 default:
8983 return WERR_UNKNOWN_LEVEL;
8987 /****************************************************************************
8988 ****************************************************************************/
8990 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8991 NT_PRINTER_INFO_LEVEL *ntprinter,
8992 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8993 uint32 *needed)
8995 int i=0;
8996 bool found=False;
8997 JOB_INFO_1 *info_1=NULL;
8998 WERROR result = WERR_OK;
9000 info_1=SMB_MALLOC_P(JOB_INFO_1);
9002 if (info_1 == NULL) {
9003 return WERR_NOMEM;
9006 for (i=0; i<count && found==False; i++) {
9007 if ((*queue)[i].job==(int)jobid)
9008 found=True;
9011 if (found==False) {
9012 SAFE_FREE(info_1);
9013 /* NT treats not found as bad param... yet another bad choice */
9014 return WERR_INVALID_PARAM;
9017 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9019 *needed += spoolss_size_job_info_1(info_1);
9021 if (*needed > offered) {
9022 result = WERR_INSUFFICIENT_BUFFER;
9023 goto out;
9026 if (!rpcbuf_alloc_size(buffer, *needed)) {
9027 result = WERR_NOMEM;
9028 goto out;
9031 smb_io_job_info_1("", buffer, info_1, 0);
9033 out:
9034 SAFE_FREE(info_1);
9036 return result;
9039 /****************************************************************************
9040 ****************************************************************************/
9042 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9043 NT_PRINTER_INFO_LEVEL *ntprinter,
9044 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9045 uint32 *needed)
9047 int i = 0;
9048 bool found = False;
9049 JOB_INFO_2 *info_2;
9050 WERROR result;
9051 DEVICEMODE *devmode = NULL;
9052 NT_DEVICEMODE *nt_devmode = NULL;
9054 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9055 return WERR_NOMEM;
9057 ZERO_STRUCTP(info_2);
9059 for ( i=0; i<count && found==False; i++ )
9061 if ((*queue)[i].job == (int)jobid)
9062 found = True;
9065 if ( !found ) {
9066 /* NT treats not found as bad param... yet another bad
9067 choice */
9068 result = WERR_INVALID_PARAM;
9069 goto done;
9073 * if the print job does not have a DEVMODE associated with it,
9074 * just use the one for the printer. A NULL devicemode is not
9075 * a failure condition
9078 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9079 devmode = construct_dev_mode(lp_const_servicename(snum));
9080 else {
9081 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9082 ZERO_STRUCTP( devmode );
9083 convert_nt_devicemode( devmode, nt_devmode );
9087 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9089 *needed += spoolss_size_job_info_2(info_2);
9091 if (*needed > offered) {
9092 result = WERR_INSUFFICIENT_BUFFER;
9093 goto done;
9096 if (!rpcbuf_alloc_size(buffer, *needed)) {
9097 result = WERR_NOMEM;
9098 goto done;
9101 smb_io_job_info_2("", buffer, info_2, 0);
9103 result = WERR_OK;
9105 done:
9106 /* Cleanup allocated memory */
9108 free_job_info_2(info_2); /* Also frees devmode */
9109 SAFE_FREE(info_2);
9111 return result;
9114 /****************************************************************************
9115 ****************************************************************************/
9117 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9119 POLICY_HND *handle = &q_u->handle;
9120 uint32 jobid = q_u->jobid;
9121 uint32 level = q_u->level;
9122 RPC_BUFFER *buffer = NULL;
9123 uint32 offered = q_u->offered;
9124 uint32 *needed = &r_u->needed;
9125 WERROR wstatus = WERR_OK;
9126 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9127 int snum;
9128 int count;
9129 print_queue_struct *queue = NULL;
9130 print_status_struct prt_status;
9132 /* that's an [in out] buffer */
9134 if (!q_u->buffer && (offered!=0)) {
9135 return WERR_INVALID_PARAM;
9138 if (offered > MAX_RPC_DATA_SIZE) {
9139 return WERR_INVALID_PARAM;
9142 rpcbuf_move(q_u->buffer, &r_u->buffer);
9143 buffer = r_u->buffer;
9145 DEBUG(5,("spoolss_getjob\n"));
9147 *needed = 0;
9149 if (!get_printer_snum(p, handle, &snum, NULL))
9150 return WERR_BADFID;
9152 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9153 if ( !W_ERROR_IS_OK(wstatus) )
9154 return wstatus;
9156 count = print_queue_status(snum, &queue, &prt_status);
9158 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9159 count, prt_status.status, prt_status.message));
9161 switch ( level ) {
9162 case 1:
9163 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9164 buffer, offered, needed);
9165 break;
9166 case 2:
9167 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9168 buffer, offered, needed);
9169 break;
9170 default:
9171 wstatus = WERR_UNKNOWN_LEVEL;
9172 break;
9175 SAFE_FREE(queue);
9176 free_a_printer( &ntprinter, 2 );
9178 return wstatus;
9181 /********************************************************************
9182 spoolss_getprinterdataex
9184 From MSDN documentation of GetPrinterDataEx: pass request
9185 to GetPrinterData if key is "PrinterDriverData".
9186 ********************************************************************/
9188 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9190 POLICY_HND *handle = &q_u->handle;
9191 uint32 in_size = q_u->size;
9192 uint32 *type = &r_u->type;
9193 uint32 *out_size = &r_u->size;
9194 uint8 **data = &r_u->data;
9195 uint32 *needed = &r_u->needed;
9196 fstring keyname, valuename;
9198 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9200 NT_PRINTER_INFO_LEVEL *printer = NULL;
9201 int snum = 0;
9202 WERROR status = WERR_OK;
9204 DEBUG(4,("_spoolss_getprinterdataex\n"));
9206 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9207 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9209 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9210 keyname, valuename));
9212 /* in case of problem, return some default values */
9214 *needed = 0;
9215 *type = 0;
9216 *out_size = in_size;
9218 if (!Printer) {
9219 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9220 status = WERR_BADFID;
9221 goto done;
9224 /* Is the handle to a printer or to the server? */
9226 if (Printer->printer_type == SPLHND_SERVER) {
9227 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9228 status = WERR_INVALID_PARAM;
9229 goto done;
9232 if ( !get_printer_snum(p,handle, &snum, NULL) )
9233 return WERR_BADFID;
9235 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9236 if ( !W_ERROR_IS_OK(status) )
9237 goto done;
9239 /* check to see if the keyname is valid */
9240 if ( !strlen(keyname) ) {
9241 status = WERR_INVALID_PARAM;
9242 goto done;
9245 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9246 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9247 free_a_printer( &printer, 2 );
9248 status = WERR_BADFILE;
9249 goto done;
9252 /* When given a new keyname, we should just create it */
9254 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9256 if (*needed > *out_size)
9257 status = WERR_MORE_DATA;
9259 done:
9260 if ( !W_ERROR_IS_OK(status) )
9262 DEBUG(5, ("error: allocating %d\n", *out_size));
9264 /* reply this param doesn't exist */
9266 if ( *out_size )
9268 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9269 status = WERR_NOMEM;
9270 goto done;
9272 } else {
9273 *data = NULL;
9277 if ( printer )
9278 free_a_printer( &printer, 2 );
9280 return status;
9283 /********************************************************************
9284 * spoolss_setprinterdataex
9285 ********************************************************************/
9287 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9289 POLICY_HND *handle = &q_u->handle;
9290 uint32 type = q_u->type;
9291 uint8 *data = q_u->data;
9292 uint32 real_len = q_u->real_len;
9294 NT_PRINTER_INFO_LEVEL *printer = NULL;
9295 int snum = 0;
9296 WERROR status = WERR_OK;
9297 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9298 fstring valuename;
9299 fstring keyname;
9300 char *oid_string;
9302 DEBUG(4,("_spoolss_setprinterdataex\n"));
9304 /* From MSDN documentation of SetPrinterDataEx: pass request to
9305 SetPrinterData if key is "PrinterDriverData" */
9307 if (!Printer) {
9308 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9309 return WERR_BADFID;
9312 if ( Printer->printer_type == SPLHND_SERVER ) {
9313 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9314 return WERR_INVALID_PARAM;
9317 if ( !get_printer_snum(p,handle, &snum, NULL) )
9318 return WERR_BADFID;
9321 * Access check : NT returns "access denied" if you make a
9322 * SetPrinterData call without the necessary privildge.
9323 * we were originally returning OK if nothing changed
9324 * which made Win2k issue **a lot** of SetPrinterData
9325 * when connecting to a printer --jerry
9328 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9330 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9331 return WERR_ACCESS_DENIED;
9334 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9335 if (!W_ERROR_IS_OK(status))
9336 return status;
9338 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9339 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9341 /* check for OID in valuename */
9343 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9345 *oid_string = '\0';
9346 oid_string++;
9349 /* save the registry data */
9351 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9353 if ( W_ERROR_IS_OK(status) )
9355 /* save the OID if one was specified */
9356 if ( oid_string ) {
9357 fstrcat( keyname, "\\" );
9358 fstrcat( keyname, SPOOL_OID_KEY );
9361 * I'm not checking the status here on purpose. Don't know
9362 * if this is right, but I'm returning the status from the
9363 * previous set_printer_dataex() call. I have no idea if
9364 * this is right. --jerry
9367 set_printer_dataex( printer, keyname, valuename,
9368 REG_SZ, (uint8 *)oid_string,
9369 strlen(oid_string)+1 );
9372 status = mod_a_printer(printer, 2);
9375 free_a_printer(&printer, 2);
9377 return status;
9381 /********************************************************************
9382 * spoolss_deleteprinterdataex
9383 ********************************************************************/
9385 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9387 POLICY_HND *handle = &q_u->handle;
9388 UNISTR2 *value = &q_u->valuename;
9389 UNISTR2 *key = &q_u->keyname;
9391 NT_PRINTER_INFO_LEVEL *printer = NULL;
9392 int snum=0;
9393 WERROR status = WERR_OK;
9394 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9395 char *valuename = NULL;
9396 char *keyname = NULL;
9397 TALLOC_CTX *ctx = p->mem_ctx;
9399 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9401 if (!Printer) {
9402 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9403 return WERR_BADFID;
9406 if (!get_printer_snum(p, handle, &snum, NULL))
9407 return WERR_BADFID;
9409 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9410 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9411 return WERR_ACCESS_DENIED;
9414 valuename = unistr2_to_ascii_talloc(ctx, value);
9415 keyname = unistr2_to_ascii_talloc(ctx, key);
9416 if (!valuename || !keyname) {
9417 return WERR_NOMEM;
9420 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9421 if (!W_ERROR_IS_OK(status))
9422 return status;
9424 status = delete_printer_dataex( printer, keyname, valuename );
9426 if ( W_ERROR_IS_OK(status) )
9427 mod_a_printer( printer, 2 );
9429 free_a_printer(&printer, 2);
9431 return status;
9434 /********************************************************************
9435 * spoolss_enumprinterkey
9436 ********************************************************************/
9439 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9441 fstring key;
9442 fstring *keynames = NULL;
9443 uint16 *enumkeys = NULL;
9444 int num_keys;
9445 int printerkey_len;
9446 POLICY_HND *handle = &q_u->handle;
9447 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9448 NT_PRINTER_DATA *data;
9449 NT_PRINTER_INFO_LEVEL *printer = NULL;
9450 int snum = 0;
9451 WERROR status = WERR_BADFILE;
9454 DEBUG(4,("_spoolss_enumprinterkey\n"));
9456 if (!Printer) {
9457 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9458 return WERR_BADFID;
9461 if ( !get_printer_snum(p,handle, &snum, NULL) )
9462 return WERR_BADFID;
9464 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9465 if (!W_ERROR_IS_OK(status))
9466 return status;
9468 /* get the list of subkey names */
9470 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9471 data = printer->info_2->data;
9473 num_keys = get_printer_subkeys( data, key, &keynames );
9475 if ( num_keys == -1 ) {
9476 status = WERR_BADFILE;
9477 goto done;
9480 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9482 r_u->needed = printerkey_len*2;
9484 if ( q_u->size < r_u->needed ) {
9485 status = WERR_MORE_DATA;
9486 goto done;
9489 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9490 status = WERR_NOMEM;
9491 goto done;
9494 status = WERR_OK;
9496 if ( q_u->size < r_u->needed )
9497 status = WERR_MORE_DATA;
9499 done:
9500 free_a_printer( &printer, 2 );
9501 SAFE_FREE( keynames );
9503 return status;
9506 /********************************************************************
9507 * spoolss_deleteprinterkey
9508 ********************************************************************/
9510 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9512 POLICY_HND *handle = &q_u->handle;
9513 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9514 fstring key;
9515 NT_PRINTER_INFO_LEVEL *printer = NULL;
9516 int snum=0;
9517 WERROR status;
9519 DEBUG(5,("spoolss_deleteprinterkey\n"));
9521 if (!Printer) {
9522 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9523 return WERR_BADFID;
9526 /* if keyname == NULL, return error */
9528 if ( !q_u->keyname.buffer )
9529 return WERR_INVALID_PARAM;
9531 if (!get_printer_snum(p, handle, &snum, NULL))
9532 return WERR_BADFID;
9534 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9535 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9536 return WERR_ACCESS_DENIED;
9539 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9540 if (!W_ERROR_IS_OK(status))
9541 return status;
9543 /* delete the key and all subneys */
9545 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9547 status = delete_all_printer_data( printer->info_2, key );
9549 if ( W_ERROR_IS_OK(status) )
9550 status = mod_a_printer(printer, 2);
9552 free_a_printer( &printer, 2 );
9554 return status;
9558 /********************************************************************
9559 * spoolss_enumprinterdataex
9560 ********************************************************************/
9562 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9564 POLICY_HND *handle = &q_u->handle;
9565 uint32 in_size = q_u->size;
9566 uint32 num_entries,
9567 needed;
9568 NT_PRINTER_INFO_LEVEL *printer = NULL;
9569 PRINTER_ENUM_VALUES *enum_values = NULL;
9570 NT_PRINTER_DATA *p_data;
9571 fstring key;
9572 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9573 int snum;
9574 WERROR result;
9575 int key_index;
9576 int i;
9577 REGISTRY_VALUE *val;
9578 char *value_name;
9579 uint32 data_len;
9582 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9584 if (!Printer) {
9585 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9586 return WERR_BADFID;
9590 * first check for a keyname of NULL or "". Win2k seems to send
9591 * this a lot and we should send back WERR_INVALID_PARAM
9592 * no need to spend time looking up the printer in this case.
9593 * --jerry
9596 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9597 if ( !strlen(key) ) {
9598 result = WERR_INVALID_PARAM;
9599 goto done;
9602 /* get the printer off of disk */
9604 if (!get_printer_snum(p,handle, &snum, NULL))
9605 return WERR_BADFID;
9607 ZERO_STRUCT(printer);
9608 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9609 if (!W_ERROR_IS_OK(result))
9610 return result;
9612 /* now look for a match on the key name */
9614 p_data = printer->info_2->data;
9616 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9617 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9619 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9620 result = WERR_INVALID_PARAM;
9621 goto done;
9624 result = WERR_OK;
9625 needed = 0;
9627 /* allocate the memory for the array of pointers -- if necessary */
9629 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9630 if ( num_entries )
9632 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9634 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9635 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9636 result = WERR_NOMEM;
9637 goto done;
9640 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9644 * loop through all params and build the array to pass
9645 * back to the client
9648 for ( i=0; i<num_entries; i++ )
9650 /* lookup the registry value */
9652 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9653 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9655 /* copy the data */
9657 value_name = regval_name( val );
9658 init_unistr( &enum_values[i].valuename, value_name );
9659 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9660 enum_values[i].type = regval_type( val );
9662 data_len = regval_size( val );
9663 if ( data_len ) {
9664 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9666 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9667 data_len ));
9668 result = WERR_NOMEM;
9669 goto done;
9672 enum_values[i].data_len = data_len;
9674 /* keep track of the size of the array in bytes */
9676 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9679 /* housekeeping information in the reply */
9681 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9682 * the hand marshalled container size is a multiple
9683 * of 4 bytes for RPC alignment.
9686 if (needed % 4) {
9687 needed += 4-(needed % 4);
9690 r_u->needed = needed;
9691 r_u->returned = num_entries;
9693 if (needed > in_size) {
9694 result = WERR_MORE_DATA;
9695 goto done;
9698 /* copy data into the reply */
9700 /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9701 response buffer size is != the offered buffer size
9703 r_u->ctr.size = r_u->needed;
9705 r_u->ctr.size = in_size;
9707 r_u->ctr.size_of_array = r_u->returned;
9708 r_u->ctr.values = enum_values;
9710 done:
9711 if ( printer )
9712 free_a_printer(&printer, 2);
9714 return result;
9717 /****************************************************************************
9718 ****************************************************************************/
9720 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9722 init_unistr(&info->name, name);
9725 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9726 UNISTR2 *environment,
9727 RPC_BUFFER *buffer,
9728 uint32 offered,
9729 uint32 *needed)
9731 char *long_archi = NULL;
9732 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9733 WERROR result = WERR_OK;
9734 TALLOC_CTX *ctx = talloc_tos();
9736 long_archi = unistr2_to_ascii_talloc(ctx, environment);
9737 if (!long_archi) {
9738 return WERR_NOMEM;
9741 if (!get_short_archi(long_archi))
9742 return WERR_INVALID_ENVIRONMENT;
9744 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9745 return WERR_NOMEM;
9747 fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9749 *needed += spoolss_size_printprocessordirectory_info_1(info);
9751 if (*needed > offered) {
9752 result = WERR_INSUFFICIENT_BUFFER;
9753 goto out;
9756 if (!rpcbuf_alloc_size(buffer, *needed)) {
9757 result = WERR_INSUFFICIENT_BUFFER;
9758 goto out;
9761 smb_io_printprocessordirectory_1("", buffer, info, 0);
9763 out:
9764 SAFE_FREE(info);
9766 return result;
9769 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9771 uint32 level = q_u->level;
9772 RPC_BUFFER *buffer = NULL;
9773 uint32 offered = q_u->offered;
9774 uint32 *needed = &r_u->needed;
9775 WERROR result;
9777 /* that's an [in out] buffer */
9779 if (!q_u->buffer && (offered!=0)) {
9780 return WERR_INVALID_PARAM;
9783 if (offered > MAX_RPC_DATA_SIZE) {
9784 return WERR_INVALID_PARAM;
9787 rpcbuf_move(q_u->buffer, &r_u->buffer);
9788 buffer = r_u->buffer;
9790 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9792 *needed=0;
9794 switch(level) {
9795 case 1:
9796 result = getprintprocessordirectory_level_1
9797 (&q_u->name, &q_u->environment, buffer, offered, needed);
9798 break;
9799 default:
9800 result = WERR_UNKNOWN_LEVEL;
9803 return result;
9806 /*******************************************************************
9807 Streams the monitor UI DLL name in UNICODE
9808 *******************************************************************/
9810 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9811 RPC_BUFFER *out, uint32 *needed )
9813 const char *dllname = "tcpmonui.dll";
9815 *needed = (strlen(dllname)+1) * 2;
9817 if ( rpcbuf_get_size(out) < *needed ) {
9818 return WERR_INSUFFICIENT_BUFFER;
9821 if ( !make_monitorui_buf( out, dllname ) ) {
9822 return WERR_NOMEM;
9825 return WERR_OK;
9828 /*******************************************************************
9829 Create a new TCP/IP port
9830 *******************************************************************/
9832 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9833 RPC_BUFFER *out, uint32 *needed )
9835 NT_PORT_DATA_1 port1;
9836 TALLOC_CTX *ctx = talloc_tos();
9837 char *device_uri = NULL;
9839 ZERO_STRUCT( port1 );
9841 /* convert to our internal port data structure */
9843 if ( !convert_port_data_1( &port1, in ) ) {
9844 return WERR_NOMEM;
9847 /* create the device URI and call the add_port_hook() */
9849 switch ( port1.protocol ) {
9850 case PORT_PROTOCOL_DIRECT:
9851 device_uri = talloc_asprintf(ctx,
9852 "socket://%s:%d/", port1.hostaddr, port1.port );
9853 break;
9855 case PORT_PROTOCOL_LPR:
9856 device_uri = talloc_asprintf(ctx,
9857 "lpr://%s/%s", port1.hostaddr, port1.queue );
9858 break;
9860 default:
9861 return WERR_UNKNOWN_PORT;
9864 if (!device_uri) {
9865 return WERR_NOMEM;
9868 return add_port_hook(ctx, token, port1.name, device_uri );
9871 /*******************************************************************
9872 *******************************************************************/
9874 struct xcv_api_table xcvtcp_cmds[] = {
9875 { "MonitorUI", xcvtcp_monitorui },
9876 { "AddPort", xcvtcp_addport},
9877 { NULL, NULL }
9880 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9881 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9882 uint32 *needed )
9884 int i;
9886 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9888 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9889 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9890 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9893 return WERR_BADFUNC;
9896 /*******************************************************************
9897 *******************************************************************/
9898 #if 0 /* don't support management using the "Local Port" monitor */
9900 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9901 RPC_BUFFER *out, uint32 *needed )
9903 const char *dllname = "localui.dll";
9905 *needed = (strlen(dllname)+1) * 2;
9907 if ( rpcbuf_get_size(out) < *needed ) {
9908 return WERR_INSUFFICIENT_BUFFER;
9911 if ( !make_monitorui_buf( out, dllname )) {
9912 return WERR_NOMEM;
9915 return WERR_OK;
9918 /*******************************************************************
9919 *******************************************************************/
9921 struct xcv_api_table xcvlocal_cmds[] = {
9922 { "MonitorUI", xcvlocal_monitorui },
9923 { NULL, NULL }
9925 #else
9926 struct xcv_api_table xcvlocal_cmds[] = {
9927 { NULL, NULL }
9929 #endif
9933 /*******************************************************************
9934 *******************************************************************/
9936 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9937 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9938 uint32 *needed )
9940 int i;
9942 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9944 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9945 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9946 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9948 return WERR_BADFUNC;
9951 /*******************************************************************
9952 *******************************************************************/
9954 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9956 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9957 fstring command;
9959 if (!Printer) {
9960 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9961 return WERR_BADFID;
9964 /* Has to be a handle to the TCP/IP port monitor */
9966 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9967 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9968 return WERR_BADFID;
9971 /* requires administrative access to the server */
9973 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9974 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9975 return WERR_ACCESS_DENIED;
9978 /* Get the command name. There's numerous commands supported by the
9979 TCPMON interface. */
9981 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9982 q_u->dataname.uni_str_len*2, 0);
9984 /* Allocate the outgoing buffer */
9986 if (!rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx ))
9987 return WERR_NOMEM;
9989 switch ( Printer->printer_type ) {
9990 case SPLHND_PORTMON_TCP:
9991 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9992 &q_u->indata, &r_u->outdata, &r_u->needed );
9993 case SPLHND_PORTMON_LOCAL:
9994 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9995 &q_u->indata, &r_u->outdata, &r_u->needed );
9998 return WERR_INVALID_PRINT_MONITOR;