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. */
30 extern userdom_struct current_user_info;
33 #define DBGC_CLASS DBGC_RPC_SRV
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
43 const char *long_archi;
44 const char *short_archi;
48 static Printer_entry *printers_list;
50 typedef struct _counter_printer_0 {
51 struct _counter_printer_0 *next;
52 struct _counter_printer_0 *prev;
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 {
72 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
76 /* translate between internal status numbers and NT status numbers */
77 static int nt_printj_status(int v)
83 return JOB_STATUS_PAUSED;
85 return JOB_STATUS_SPOOLING;
87 return JOB_STATUS_PRINTING;
89 return JOB_STATUS_ERROR;
91 return JOB_STATUS_DELETING;
93 return JOB_STATUS_OFFLINE;
95 return JOB_STATUS_PAPEROUT;
97 return JOB_STATUS_PRINTED;
99 return JOB_STATUS_DELETED;
101 return JOB_STATUS_BLOCKED;
102 case LPQ_USER_INTERVENTION:
103 return JOB_STATUS_USER_INTERVENTION;
108 static int nt_printq_status(int v)
112 return PRINTER_STATUS_PAUSED;
121 /****************************************************************************
122 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
123 ****************************************************************************/
125 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
130 SAFE_FREE((*pp)->ctr.type);
134 /***************************************************************************
135 Disconnect from the client
136 ****************************************************************************/
138 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
143 * Tell the specific printing tdb we no longer want messages for this printer
144 * by deregistering our PID.
147 if (!print_notify_deregister_pid(snum))
148 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
150 /* weird if the test succeds !!! */
151 if (smb_connections==0) {
152 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
156 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe,
160 if (!W_ERROR_IS_OK(result))
161 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
162 dos_errstr(result)));
164 /* if it's the last connection, deconnect the IPC$ share */
165 if (smb_connections==1) {
167 cli_shutdown( notify_cli_pipe->cli );
168 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
170 messaging_deregister(smbd_messaging_context(),
171 MSG_PRINTER_NOTIFY2, NULL);
173 /* Tell the connections db we're no longer interested in
174 * printer notify messages. */
176 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
182 /****************************************************************************
183 Functions to free a printer entry datastruct.
184 ****************************************************************************/
186 static void free_printer_entry(void *ptr)
188 Printer_entry *Printer = (Printer_entry *)ptr;
190 if (Printer->notify.client_connected==True) {
193 if ( Printer->printer_type == SPLHND_SERVER) {
195 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
196 } else if (Printer->printer_type == SPLHND_PRINTER) {
197 snum = print_queue_snum(Printer->sharename);
199 srv_spoolss_replycloseprinter(snum,
200 &Printer->notify.client_hnd);
204 Printer->notify.flags=0;
205 Printer->notify.options=0;
206 Printer->notify.localmachine[0]='\0';
207 Printer->notify.printerlocal=0;
208 free_spool_notify_option(&Printer->notify.option);
209 Printer->notify.option=NULL;
210 Printer->notify.client_connected=False;
212 free_nt_devicemode( &Printer->nt_devmode );
213 free_a_printer( &Printer->printer_info, 2 );
215 talloc_destroy( Printer->ctx );
217 /* Remove from the internal list. */
218 DLIST_REMOVE(printers_list, Printer);
223 /****************************************************************************
224 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
225 ****************************************************************************/
227 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
229 SPOOL_NOTIFY_OPTION *new_sp = NULL;
234 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
241 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
243 if (!new_sp->ctr.type) {
252 /****************************************************************************
253 find printer index by handle
254 ****************************************************************************/
256 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
258 Printer_entry *find_printer = NULL;
260 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
261 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
268 /****************************************************************************
269 Close printer index by handle.
270 ****************************************************************************/
272 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
274 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
277 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
281 close_policy_hnd(p, hnd);
286 /****************************************************************************
287 Delete a printer given a handle.
288 ****************************************************************************/
290 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
292 char *cmd = lp_deleteprinter_cmd();
293 char *command = NULL;
295 SE_PRIV se_printop = SE_PRINT_OPERATOR;
296 bool is_print_op = False;
298 /* can't fail if we don't try */
303 command = talloc_asprintf(ctx,
310 is_print_op = user_has_privileges( token, &se_printop );
312 DEBUG(10,("Running [%s]\n", command));
314 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
319 if ( (ret = smbrun(command, NULL)) == 0 ) {
320 /* Tell everyone we updated smb.conf. */
321 message_send_all(smbd_messaging_context(),
322 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
328 /********** END SePrintOperatorPrivlege BLOCK **********/
330 DEBUGADD(10,("returned [%d]\n", ret));
332 TALLOC_FREE(command);
335 return WERR_BADFID; /* What to return here? */
337 /* go ahead and re-read the services immediately */
338 reload_services( False );
340 if ( lp_servicenumber( sharename ) < 0 )
341 return WERR_ACCESS_DENIED;
346 /****************************************************************************
347 Delete a printer given a handle.
348 ****************************************************************************/
350 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
355 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
360 * It turns out that Windows allows delete printer on a handle
361 * opened by an admin user, then used on a pipe handle created
362 * by an anonymous user..... but they're working on security.... riiight !
366 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
367 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368 return WERR_ACCESS_DENIED;
371 /* this does not need a become root since the access check has been
372 done on the handle already */
374 if (del_a_printer( Printer->sharename ) != 0) {
375 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
379 return delete_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, Printer->sharename );
382 /****************************************************************************
383 Return the snum of a printer corresponding to an handle.
384 ****************************************************************************/
386 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
387 struct share_params **params)
389 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
392 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
396 switch (Printer->printer_type) {
398 DEBUG(4,("short name:%s\n", Printer->sharename));
399 *number = print_queue_snum(Printer->sharename);
400 return (*number != -1);
408 /****************************************************************************
409 Set printer handle type.
410 Check if it's \\server or \\server\printer
411 ****************************************************************************/
413 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
415 DEBUG(3,("Setting printer type=%s\n", handlename));
417 if ( strlen(handlename) < 3 ) {
418 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
422 /* it's a print server */
423 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
424 DEBUGADD(4,("Printer is a print server\n"));
425 Printer->printer_type = SPLHND_SERVER;
427 /* it's a printer (set_printer_hnd_name() will handle port monitors */
429 DEBUGADD(4,("Printer is a printer\n"));
430 Printer->printer_type = SPLHND_PRINTER;
436 /****************************************************************************
437 Set printer handle name.. Accept names like \\server, \\server\printer,
438 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
439 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
440 XcvDataPort() interface.
441 ****************************************************************************/
443 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
446 int n_services=lp_numservices();
447 char *aprinter, *printername;
448 const char *servername;
451 NT_PRINTER_INFO_LEVEL *printer = NULL;
454 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
456 aprinter = handlename;
457 if ( *handlename == '\\' ) {
458 servername = handlename + 2;
459 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
468 /* save the servername to fill in replies on this handle */
470 if ( !is_myname_or_ipaddr( servername ) )
473 fstrcpy( Printer->servername, servername );
475 if ( Printer->printer_type == SPLHND_SERVER )
478 if ( Printer->printer_type != SPLHND_PRINTER )
481 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
483 /* check for the Port Monitor Interface */
485 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
486 Printer->printer_type = SPLHND_PORTMON_TCP;
487 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
490 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
491 Printer->printer_type = SPLHND_PORTMON_LOCAL;
492 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
496 /* Search all sharenames first as this is easier than pulling
497 the printer_info_2 off of disk. Don't use find_service() since
498 that calls out to map_username() */
500 /* do another loop to look for printernames */
502 for (snum=0; !found && snum<n_services; snum++) {
504 /* no point going on if this is not a printer */
506 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
509 fstrcpy(sname, lp_servicename(snum));
510 if ( strequal( aprinter, sname ) ) {
515 /* no point looking up the printer object if
516 we aren't allowing printername != sharename */
518 if ( lp_force_printername(snum) )
521 fstrcpy(sname, lp_servicename(snum));
524 result = get_a_printer( NULL, &printer, 2, sname );
525 if ( !W_ERROR_IS_OK(result) ) {
526 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
527 sname, dos_errstr(result)));
531 /* printername is always returned as \\server\printername */
532 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
533 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
534 printer->info_2->printername));
535 free_a_printer( &printer, 2);
541 if ( strequal(printername, aprinter) ) {
542 free_a_printer( &printer, 2);
547 DEBUGADD(10, ("printername: %s\n", printername));
549 free_a_printer( &printer, 2);
552 free_a_printer( &printer, 2);
555 DEBUGADD(4,("Printer not found\n"));
559 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
561 fstrcpy(Printer->sharename, sname);
566 /****************************************************************************
567 Find first available printer slot. creates a printer handle for you.
568 ****************************************************************************/
570 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
572 Printer_entry *new_printer;
574 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
576 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
579 ZERO_STRUCTP(new_printer);
581 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
582 SAFE_FREE(new_printer);
586 /* Add to the internal list. */
587 DLIST_ADD(printers_list, new_printer);
589 new_printer->notify.option=NULL;
591 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
592 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
593 close_printer_handle(p, hnd);
597 if (!set_printer_hnd_printertype(new_printer, name)) {
598 close_printer_handle(p, hnd);
602 if (!set_printer_hnd_name(new_printer, name)) {
603 close_printer_handle(p, hnd);
607 new_printer->access_granted = access_granted;
609 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
614 /***************************************************************************
615 check to see if the client motify handle is monitoring the notification
616 given by (notify_type, notify_field).
617 **************************************************************************/
619 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
625 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
628 SPOOL_NOTIFY_OPTION *option = p->notify.option;
632 * Flags should always be zero when the change notify
633 * is registered by the client's spooler. A user Win32 app
634 * might use the flags though instead of the NOTIFY_OPTION_INFO
643 return is_monitoring_event_flags(
644 p->notify.flags, notify_type, notify_field);
646 for (i = 0; i < option->count; i++) {
648 /* Check match for notify_type */
650 if (option->ctr.type[i].type != notify_type)
653 /* Check match for field */
655 for (j = 0; j < option->ctr.type[i].count; j++) {
656 if (option->ctr.type[i].fields[j] == notify_field) {
662 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
663 p->servername, p->sharename, notify_type, notify_field));
668 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
670 static void notify_one_value(struct spoolss_notify_msg *msg,
671 SPOOL_NOTIFY_INFO_DATA *data,
674 data->notify_data.value[0] = msg->notify.value[0];
675 data->notify_data.value[1] = 0;
678 static void notify_string(struct spoolss_notify_msg *msg,
679 SPOOL_NOTIFY_INFO_DATA *data,
684 /* The length of the message includes the trailing \0 */
686 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
688 data->notify_data.data.length = msg->len * 2;
689 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
691 if (!data->notify_data.data.string) {
692 data->notify_data.data.length = 0;
696 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
699 static void notify_system_time(struct spoolss_notify_msg *msg,
700 SPOOL_NOTIFY_INFO_DATA *data,
706 if (msg->len != sizeof(time_t)) {
707 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
712 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
713 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
717 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
718 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
723 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
728 data->notify_data.data.length = prs_offset(&ps);
729 if (prs_offset(&ps)) {
730 data->notify_data.data.string = (uint16 *)
731 TALLOC(mem_ctx, prs_offset(&ps));
732 if (!data->notify_data.data.string) {
736 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
738 data->notify_data.data.string = NULL;
744 struct notify2_message_table {
746 void (*fn)(struct spoolss_notify_msg *msg,
747 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
750 static struct notify2_message_table printer_notify_table[] = {
751 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
752 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
753 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
754 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
755 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
756 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
757 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
758 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
759 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
760 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
761 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
762 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
763 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
764 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
765 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
766 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
767 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
768 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
769 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
772 static struct notify2_message_table job_notify_table[] = {
773 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
774 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
775 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
776 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
777 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
778 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
779 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
780 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
781 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
782 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
783 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
784 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
785 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
786 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
787 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
788 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
789 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
790 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
791 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
792 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
793 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
794 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
795 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
796 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
800 /***********************************************************************
801 Allocate talloc context for container object
802 **********************************************************************/
804 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
809 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
814 /***********************************************************************
815 release all allocated memory and zero out structure
816 **********************************************************************/
818 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
824 talloc_destroy(ctr->ctx);
831 /***********************************************************************
832 **********************************************************************/
834 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
842 /***********************************************************************
843 **********************************************************************/
845 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
847 if ( !ctr || !ctr->msg_groups )
850 if ( idx >= ctr->num_groups )
853 return &ctr->msg_groups[idx];
857 /***********************************************************************
858 How many groups of change messages do we have ?
859 **********************************************************************/
861 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
866 return ctr->num_groups;
869 /***********************************************************************
870 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
871 **********************************************************************/
873 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
875 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
876 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
877 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
883 /* loop over all groups looking for a matching printer name */
885 for ( i=0; i<ctr->num_groups; i++ ) {
886 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
890 /* add a new group? */
892 if ( i == ctr->num_groups ) {
895 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
896 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
899 ctr->msg_groups = groups;
901 /* clear the new entry and set the printer name */
903 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
904 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
907 /* add the change messages; 'i' is the correct index now regardless */
909 msg_grp = &ctr->msg_groups[i];
913 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
914 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
917 msg_grp->msgs = msg_list;
919 new_slot = msg_grp->num_msgs-1;
920 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
922 /* need to allocate own copy of data */
925 msg_grp->msgs[new_slot].notify.data = (char *)
926 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
928 return ctr->num_groups;
931 /***********************************************************************
932 Send a change notication message on all handles which have a call
934 **********************************************************************/
936 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
939 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
940 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
941 SPOOLSS_NOTIFY_MSG *messages;
942 int sending_msg_count;
945 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
949 messages = msg_group->msgs;
952 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
956 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
958 /* loop over all printers */
960 for (p = printers_list; p; p = p->next) {
961 SPOOL_NOTIFY_INFO_DATA *data;
966 /* Is there notification on this handle? */
968 if ( !p->notify.client_connected )
971 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
973 /* For this printer? Print servers always receive
976 if ( ( p->printer_type == SPLHND_PRINTER ) &&
977 ( !strequal(msg_group->printername, p->sharename) ) )
980 DEBUG(10,("Our printer\n"));
982 /* allocate the max entries possible */
984 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
991 /* build the array of change notifications */
993 sending_msg_count = 0;
995 for ( i=0; i<msg_group->num_msgs; i++ ) {
996 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
998 /* Are we monitoring this event? */
1000 if (!is_monitoring_event(p, msg->type, msg->field))
1003 sending_msg_count++;
1006 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1007 msg->type, msg->field, p->sharename));
1010 * if the is a printer notification handle and not a job notification
1011 * type, then set the id to 0. Other wise just use what was specified
1014 * When registering change notification on a print server handle
1015 * we always need to send back the id (snum) matching the printer
1016 * for which the change took place. For change notify registered
1017 * on a printer handle, this does not matter and the id should be 0.
1022 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1028 /* Convert unix jobid to smb jobid */
1030 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1031 id = sysjob_to_jobid(msg->id);
1034 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1039 construct_info_data( &data[data_len], msg->type, msg->field, id );
1042 case PRINTER_NOTIFY_TYPE:
1043 if ( printer_notify_table[msg->field].fn )
1044 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1047 case JOB_NOTIFY_TYPE:
1048 if ( job_notify_table[msg->field].fn )
1049 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1053 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1060 if ( sending_msg_count ) {
1061 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1062 data_len, data, p->notify.change, 0 );
1067 DEBUG(8,("send_notify2_changes: Exit...\n"));
1071 /***********************************************************************
1072 **********************************************************************/
1074 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1077 uint32 tv_sec, tv_usec;
1080 /* Unpack message */
1082 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1085 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1087 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1090 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1091 &msg->notify.value[0], &msg->notify.value[1]);
1093 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1094 &msg->len, &msg->notify.data);
1096 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1097 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1099 tv->tv_sec = tv_sec;
1100 tv->tv_usec = tv_usec;
1103 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1104 msg->notify.value[1]));
1106 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1111 /********************************************************************
1112 Receive a notify2 message list
1113 ********************************************************************/
1115 static void receive_notify2_message_list(struct messaging_context *msg,
1118 struct server_id server_id,
1121 size_t msg_count, i;
1122 char *buf = (char *)data->data;
1125 SPOOLSS_NOTIFY_MSG notify;
1126 SPOOLSS_NOTIFY_MSG_CTR messages;
1129 if (data->length < 4) {
1130 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1134 msg_count = IVAL(buf, 0);
1137 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1139 if (msg_count == 0) {
1140 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1144 /* initialize the container */
1146 ZERO_STRUCT( messages );
1147 notify_msg_ctr_init( &messages );
1150 * build message groups for each printer identified
1151 * in a change_notify msg. Remember that a PCN message
1152 * includes the handle returned for the srv_spoolss_replyopenprinter()
1153 * call. Therefore messages are grouped according to printer handle.
1156 for ( i=0; i<msg_count; i++ ) {
1157 struct timeval msg_tv;
1159 if (msg_ptr + 4 - buf > data->length) {
1160 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1164 msg_len = IVAL(msg_ptr,0);
1167 if (msg_ptr + msg_len - buf > data->length) {
1168 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1172 /* unpack messages */
1174 ZERO_STRUCT( notify );
1175 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1178 /* add to correct list in container */
1180 notify_msg_ctr_addmsg( &messages, ¬ify );
1182 /* free memory that might have been allocated by notify2_unpack_msg() */
1184 if ( notify.len != 0 )
1185 SAFE_FREE( notify.notify.data );
1188 /* process each group of messages */
1190 num_groups = notify_msg_ctr_numgroups( &messages );
1191 for ( i=0; i<num_groups; i++ )
1192 send_notify2_changes( &messages, i );
1197 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1199 notify_msg_ctr_destroy( &messages );
1204 /********************************************************************
1205 Send a message to ourself about new driver being installed
1206 so we can upgrade the information for each printer bound to this
1208 ********************************************************************/
1210 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1212 int len = strlen(drivername);
1217 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1220 messaging_send_buf(smbd_messaging_context(), procid_self(),
1221 MSG_PRINTER_DRVUPGRADE,
1222 (uint8 *)drivername, len+1);
1227 /**********************************************************************
1228 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1229 over all printers, upgrading ones as necessary
1230 **********************************************************************/
1232 void do_drv_upgrade_printer(struct messaging_context *msg,
1235 struct server_id server_id,
1240 int n_services = lp_numservices();
1243 len = MIN(data->length,sizeof(drivername)-1);
1244 strncpy(drivername, (const char *)data->data, len);
1246 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1248 /* Iterate the printer list */
1250 for (snum=0; snum<n_services; snum++)
1252 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1255 NT_PRINTER_INFO_LEVEL *printer = NULL;
1257 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1258 if (!W_ERROR_IS_OK(result))
1261 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1263 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1265 /* all we care about currently is the change_id */
1267 result = mod_a_printer(printer, 2);
1268 if (!W_ERROR_IS_OK(result)) {
1269 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1270 dos_errstr(result)));
1274 free_a_printer(&printer, 2);
1281 /********************************************************************
1282 Update the cache for all printq's with a registered client
1284 ********************************************************************/
1286 void update_monitored_printq_cache( void )
1288 Printer_entry *printer = printers_list;
1291 /* loop through all printers and update the cache where
1292 client_connected == True */
1295 if ( (printer->printer_type == SPLHND_PRINTER)
1296 && printer->notify.client_connected )
1298 snum = print_queue_snum(printer->sharename);
1299 print_queue_status( snum, NULL, NULL );
1302 printer = printer->next;
1307 /********************************************************************
1308 Send a message to ourself about new driver being installed
1309 so we can upgrade the information for each printer bound to this
1311 ********************************************************************/
1313 static bool srv_spoolss_reset_printerdata(char* drivername)
1315 int len = strlen(drivername);
1320 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1323 messaging_send_buf(smbd_messaging_context(), procid_self(),
1324 MSG_PRINTERDATA_INIT_RESET,
1325 (uint8 *)drivername, len+1);
1330 /**********************************************************************
1331 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1332 over all printers, resetting printer data as neessary
1333 **********************************************************************/
1335 void reset_all_printerdata(struct messaging_context *msg,
1338 struct server_id server_id,
1343 int n_services = lp_numservices();
1346 len = MIN( data->length, sizeof(drivername)-1 );
1347 strncpy( drivername, (const char *)data->data, len );
1349 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1351 /* Iterate the printer list */
1353 for ( snum=0; snum<n_services; snum++ )
1355 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1358 NT_PRINTER_INFO_LEVEL *printer = NULL;
1360 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1361 if ( !W_ERROR_IS_OK(result) )
1365 * if the printer is bound to the driver,
1366 * then reset to the new driver initdata
1369 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1371 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1373 if ( !set_driver_init(printer, 2) ) {
1374 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1375 printer->info_2->printername, printer->info_2->drivername));
1378 result = mod_a_printer( printer, 2 );
1379 if ( !W_ERROR_IS_OK(result) ) {
1380 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1381 get_dos_error_msg(result)));
1385 free_a_printer( &printer, 2 );
1394 /********************************************************************
1395 Copy routines used by convert_to_openprinterex()
1396 *******************************************************************/
1398 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1406 DEBUG (8,("dup_devmode\n"));
1408 /* bulk copy first */
1410 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1414 /* dup the pointer members separately */
1416 len = unistrlen(devmode->devicename.buffer);
1418 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1419 if (!d->devicename.buffer) {
1422 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1427 len = unistrlen(devmode->formname.buffer);
1429 d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
1430 if (!d->formname.buffer) {
1433 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1437 if (devmode->driverextra) {
1438 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1439 devmode->driverextra);
1440 if (!d->dev_private) {
1444 d->dev_private = NULL;
1449 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1451 if (!new_ctr || !ctr)
1454 DEBUG(8,("copy_devmode_ctr\n"));
1456 new_ctr->size = ctr->size;
1457 new_ctr->devmode_ptr = ctr->devmode_ptr;
1459 if(ctr->devmode_ptr)
1460 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1463 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1465 if (!new_def || !def)
1468 DEBUG(8,("copy_printer_defaults\n"));
1470 new_def->datatype_ptr = def->datatype_ptr;
1472 if (def->datatype_ptr)
1473 copy_unistr2(&new_def->datatype, &def->datatype);
1475 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1477 new_def->access_required = def->access_required;
1480 /********************************************************************
1481 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1482 * SPOOL_Q_OPEN_PRINTER_EX structure
1483 ********************************************************************/
1485 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1487 if (!q_u_ex || !q_u)
1490 DEBUG(8,("convert_to_openprinterex\n"));
1492 if ( q_u->printername ) {
1493 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1494 if (q_u_ex->printername == NULL)
1496 copy_unistr2(q_u_ex->printername, q_u->printername);
1499 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1504 /********************************************************************
1505 * spoolss_open_printer
1507 * called from the spoolss dispatcher
1508 ********************************************************************/
1510 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1512 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1513 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1518 ZERO_STRUCT(q_u_ex);
1519 ZERO_STRUCT(r_u_ex);
1521 /* convert the OpenPrinter() call to OpenPrinterEx() */
1523 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1524 if (!W_ERROR_IS_OK(r_u_ex.status))
1525 return r_u_ex.status;
1527 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1529 /* convert back to OpenPrinter() */
1531 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1536 /********************************************************************
1537 ********************************************************************/
1539 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1541 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1542 POLICY_HND *handle = &r_u->handle;
1546 Printer_entry *Printer=NULL;
1548 if ( !q_u->printername )
1549 return WERR_INVALID_PRINTER_NAME;
1551 /* some sanity check because you can open a printer or a print server */
1552 /* aka: \\server\printer or \\server */
1554 unistr2_to_ascii(name, q_u->printername, sizeof(name));
1556 DEBUGADD(3,("checking name: %s\n",name));
1558 if (!open_printer_hnd(p, handle, name, 0))
1559 return WERR_INVALID_PRINTER_NAME;
1561 Printer=find_printer_index_by_hnd(p, handle);
1563 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1564 "handle we created for printer %s\n", name ));
1565 close_printer_handle(p,handle);
1566 return WERR_INVALID_PRINTER_NAME;
1570 * First case: the user is opening the print server:
1572 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1573 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1575 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1576 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1577 * or if the user is listed in the smb.conf printer admin parameter.
1579 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1580 * client view printer folder, but does not show the MSAPW.
1582 * Note: this test needs code to check access rights here too. Jeremy
1583 * could you look at this?
1585 * Second case: the user is opening a printer:
1586 * NT doesn't let us connect to a printer if the connecting user
1587 * doesn't have print permission.
1589 * Third case: user is opening a Port Monitor
1590 * access checks same as opening a handle to the print server.
1593 switch (Printer->printer_type )
1596 case SPLHND_PORTMON_TCP:
1597 case SPLHND_PORTMON_LOCAL:
1598 /* Printserver handles use global struct... */
1602 /* Map standard access rights to object specific access rights */
1604 se_map_standard(&printer_default->access_required,
1605 &printserver_std_mapping);
1607 /* Deny any object specific bits that don't apply to print
1608 servers (i.e printer and job specific bits) */
1610 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1612 if (printer_default->access_required &
1613 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1614 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1615 close_printer_handle(p, handle);
1616 return WERR_ACCESS_DENIED;
1619 /* Allow admin access */
1621 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1623 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1625 if (!lp_ms_add_printer_wizard()) {
1626 close_printer_handle(p, handle);
1627 return WERR_ACCESS_DENIED;
1630 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1631 and not a printer admin, then fail */
1633 if ((p->pipe_user.ut.uid != 0) &&
1634 !user_has_privileges(p->pipe_user.nt_user_token,
1636 !token_contains_name_in_list(
1637 uidtoname(p->pipe_user.ut.uid), NULL,
1638 p->pipe_user.nt_user_token,
1639 lp_printer_admin(snum))) {
1640 close_printer_handle(p, handle);
1641 return WERR_ACCESS_DENIED;
1644 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1648 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1651 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1652 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1654 /* We fall through to return WERR_OK */
1657 case SPLHND_PRINTER:
1658 /* NT doesn't let us connect to a printer if the connecting user
1659 doesn't have print permission. */
1661 if (!get_printer_snum(p, handle, &snum, NULL)) {
1662 close_printer_handle(p, handle);
1666 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1668 /* map an empty access mask to the minimum access mask */
1669 if (printer_default->access_required == 0x0)
1670 printer_default->access_required = PRINTER_ACCESS_USE;
1673 * If we are not serving the printer driver for this printer,
1674 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1675 * will keep NT clients happy --jerry
1678 if (lp_use_client_driver(snum)
1679 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1681 printer_default->access_required = PRINTER_ACCESS_USE;
1684 /* check smb.conf parameters and the the sec_desc */
1686 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1687 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1688 return WERR_ACCESS_DENIED;
1691 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1692 p->pipe_user.nt_user_token, snum) ||
1693 !print_access_check(&p->pipe_user, snum,
1694 printer_default->access_required)) {
1695 DEBUG(3, ("access DENIED for printer open\n"));
1696 close_printer_handle(p, handle);
1697 return WERR_ACCESS_DENIED;
1700 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1701 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1702 close_printer_handle(p, handle);
1703 return WERR_ACCESS_DENIED;
1706 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1707 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1709 printer_default->access_required = PRINTER_ACCESS_USE;
1711 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1712 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1717 /* sanity check to prevent programmer error */
1721 Printer->access_granted = printer_default->access_required;
1724 * If the client sent a devmode in the OpenPrinter() call, then
1725 * save it here in case we get a job submission on this handle
1728 if ( (Printer->printer_type != SPLHND_SERVER)
1729 && q_u->printer_default.devmode_cont.devmode_ptr )
1731 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1732 &Printer->nt_devmode );
1735 #if 0 /* JERRY -- I'm doubtful this is really effective */
1736 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1737 optimization in Windows 2000 clients --jerry */
1739 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1740 && (RA_WIN2K == get_remote_arch()) )
1742 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1743 sys_usleep( 500000 );
1750 /****************************************************************************
1751 ****************************************************************************/
1753 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1754 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1760 /* allocate memory if needed. Messy because
1761 convert_printer_info is used to update an existing
1762 printer or build a new one */
1764 if ( !printer->info_2 ) {
1765 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1766 if ( !printer->info_2 ) {
1767 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1772 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1773 printer->info_2->setuptime = time(NULL);
1781 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1782 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1788 printer->info_3=NULL;
1789 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1793 printer->info_6=NULL;
1794 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1804 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1805 NT_DEVICEMODE **pp_nt_devmode)
1807 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1810 * Ensure nt_devmode is a valid pointer
1811 * as we will be overwriting it.
1814 if (nt_devmode == NULL) {
1815 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1816 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1820 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1821 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1823 nt_devmode->specversion=devmode->specversion;
1824 nt_devmode->driverversion=devmode->driverversion;
1825 nt_devmode->size=devmode->size;
1826 nt_devmode->fields=devmode->fields;
1827 nt_devmode->orientation=devmode->orientation;
1828 nt_devmode->papersize=devmode->papersize;
1829 nt_devmode->paperlength=devmode->paperlength;
1830 nt_devmode->paperwidth=devmode->paperwidth;
1831 nt_devmode->scale=devmode->scale;
1832 nt_devmode->copies=devmode->copies;
1833 nt_devmode->defaultsource=devmode->defaultsource;
1834 nt_devmode->printquality=devmode->printquality;
1835 nt_devmode->color=devmode->color;
1836 nt_devmode->duplex=devmode->duplex;
1837 nt_devmode->yresolution=devmode->yresolution;
1838 nt_devmode->ttoption=devmode->ttoption;
1839 nt_devmode->collate=devmode->collate;
1841 nt_devmode->logpixels=devmode->logpixels;
1842 nt_devmode->bitsperpel=devmode->bitsperpel;
1843 nt_devmode->pelswidth=devmode->pelswidth;
1844 nt_devmode->pelsheight=devmode->pelsheight;
1845 nt_devmode->displayflags=devmode->displayflags;
1846 nt_devmode->displayfrequency=devmode->displayfrequency;
1847 nt_devmode->icmmethod=devmode->icmmethod;
1848 nt_devmode->icmintent=devmode->icmintent;
1849 nt_devmode->mediatype=devmode->mediatype;
1850 nt_devmode->dithertype=devmode->dithertype;
1851 nt_devmode->reserved1=devmode->reserved1;
1852 nt_devmode->reserved2=devmode->reserved2;
1853 nt_devmode->panningwidth=devmode->panningwidth;
1854 nt_devmode->panningheight=devmode->panningheight;
1857 * Only change private and driverextra if the incoming devmode
1858 * has a new one. JRA.
1861 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1862 SAFE_FREE(nt_devmode->nt_dev_private);
1863 nt_devmode->driverextra=devmode->driverextra;
1864 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1866 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1869 *pp_nt_devmode = nt_devmode;
1874 /********************************************************************
1875 * _spoolss_enddocprinter_internal.
1876 ********************************************************************/
1878 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1880 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1884 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1888 if (!get_printer_snum(p, handle, &snum, NULL))
1891 Printer->document_started=False;
1892 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1893 /* error codes unhandled so far ... */
1898 /********************************************************************
1899 * api_spoolss_closeprinter
1900 ********************************************************************/
1902 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1904 POLICY_HND *handle = &q_u->handle;
1906 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1908 if (Printer && Printer->document_started)
1909 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1911 if (!close_printer_handle(p, handle))
1914 /* clear the returned printer handle. Observed behavior
1915 from Win2k server. Don't think this really matters.
1916 Previous code just copied the value of the closed
1919 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1924 /********************************************************************
1925 * api_spoolss_deleteprinter
1927 ********************************************************************/
1929 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1931 POLICY_HND *handle = &q_u->handle;
1932 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 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1940 result = delete_printer_handle(p, handle);
1942 update_c_setprinter(False);
1947 /*******************************************************************
1948 * static function to lookup the version id corresponding to an
1949 * long architecture string
1950 ******************************************************************/
1952 static int get_version_id (char * arch)
1955 struct table_node archi_table[]= {
1957 {"Windows 4.0", "WIN40", 0 },
1958 {"Windows NT x86", "W32X86", 2 },
1959 {"Windows NT R4000", "W32MIPS", 2 },
1960 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1961 {"Windows NT PowerPC", "W32PPC", 2 },
1962 {"Windows IA64", "IA64", 3 },
1963 {"Windows x64", "x64", 3 },
1967 for (i=0; archi_table[i].long_archi != NULL; i++)
1969 if (strcmp(arch, archi_table[i].long_archi) == 0)
1970 return (archi_table[i].version);
1976 /********************************************************************
1977 * _spoolss_deleteprinterdriver
1978 ********************************************************************/
1980 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1984 NT_PRINTER_DRIVER_INFO_LEVEL info;
1985 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1988 WERROR status_win2k = WERR_ACCESS_DENIED;
1989 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1991 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1992 and not a printer admin, then fail */
1994 if ( (p->pipe_user.ut.uid != 0)
1995 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1996 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1997 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1999 return WERR_ACCESS_DENIED;
2002 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2003 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2005 /* check that we have a valid driver name first */
2007 if ((version=get_version_id(arch)) == -1)
2008 return WERR_INVALID_ENVIRONMENT;
2011 ZERO_STRUCT(info_win2k);
2013 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2015 /* try for Win2k driver if "Windows NT x86" */
2017 if ( version == 2 ) {
2019 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2020 status = WERR_UNKNOWN_PRINTER_DRIVER;
2024 /* otherwise it was a failure */
2026 status = WERR_UNKNOWN_PRINTER_DRIVER;
2032 if (printer_driver_in_use(info.info_3)) {
2033 status = WERR_PRINTER_DRIVER_IN_USE;
2039 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2041 /* if we get to here, we now have 2 driver info structures to remove */
2042 /* remove the Win2k driver first*/
2044 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2045 free_a_printer_driver( info_win2k, 3 );
2047 /* this should not have failed---if it did, report to client */
2048 if ( !W_ERROR_IS_OK(status_win2k) )
2050 status = status_win2k;
2056 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2058 /* if at least one of the deletes succeeded return OK */
2060 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2064 free_a_printer_driver( info, 3 );
2069 /********************************************************************
2070 * spoolss_deleteprinterdriverex
2071 ********************************************************************/
2073 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2077 NT_PRINTER_DRIVER_INFO_LEVEL info;
2078 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2080 uint32 flags = q_u->delete_flags;
2083 WERROR status_win2k = WERR_ACCESS_DENIED;
2084 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2086 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2087 and not a printer admin, then fail */
2089 if ( (p->pipe_user.ut.uid != 0)
2090 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2091 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2092 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2094 return WERR_ACCESS_DENIED;
2097 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2098 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2100 /* check that we have a valid driver name first */
2101 if ((version=get_version_id(arch)) == -1) {
2102 /* this is what NT returns */
2103 return WERR_INVALID_ENVIRONMENT;
2106 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2107 version = q_u->version;
2110 ZERO_STRUCT(info_win2k);
2112 status = get_a_printer_driver(&info, 3, driver, arch, version);
2114 if ( !W_ERROR_IS_OK(status) )
2117 * if the client asked for a specific version,
2118 * or this is something other than Windows NT x86,
2122 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2125 /* try for Win2k driver if "Windows NT x86" */
2128 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2129 status = WERR_UNKNOWN_PRINTER_DRIVER;
2134 if ( printer_driver_in_use(info.info_3) ) {
2135 status = WERR_PRINTER_DRIVER_IN_USE;
2140 * we have a couple of cases to consider.
2141 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2142 * then the delete should fail if **any** files overlap with
2144 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2145 * non-overlapping files
2146 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2147 * is set, the do not delete any files
2148 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2151 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2153 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2155 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2156 /* no idea of the correct error here */
2157 status = WERR_ACCESS_DENIED;
2162 /* also check for W32X86/3 if necessary; maybe we already have? */
2164 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2165 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2168 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2169 /* no idea of the correct error here */
2170 free_a_printer_driver( info_win2k, 3 );
2171 status = WERR_ACCESS_DENIED;
2175 /* if we get to here, we now have 2 driver info structures to remove */
2176 /* remove the Win2k driver first*/
2178 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2179 free_a_printer_driver( info_win2k, 3 );
2181 /* this should not have failed---if it did, report to client */
2183 if ( !W_ERROR_IS_OK(status_win2k) )
2188 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2190 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2193 free_a_printer_driver( info, 3 );
2199 /****************************************************************************
2200 Internal routine for retreiving printerdata
2201 ***************************************************************************/
2203 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2204 const char *key, const char *value, uint32 *type, uint8 **data,
2205 uint32 *needed, uint32 in_size )
2207 REGISTRY_VALUE *val;
2211 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2212 return WERR_BADFILE;
2214 *type = regval_type( val );
2216 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2218 size = regval_size( val );
2220 /* copy the min(in_size, len) */
2223 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2225 /* special case for 0 length values */
2227 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2231 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2240 DEBUG(5,("get_printer_dataex: copy done\n"));
2245 /****************************************************************************
2246 Internal routine for removing printerdata
2247 ***************************************************************************/
2249 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2251 return delete_printer_data( printer->info_2, key, value );
2254 /****************************************************************************
2255 Internal routine for storing printerdata
2256 ***************************************************************************/
2258 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2259 uint32 type, uint8 *data, int real_len )
2261 /* the registry objects enforce uniqueness based on value name */
2263 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2266 /********************************************************************
2267 GetPrinterData on a printer server Handle.
2268 ********************************************************************/
2270 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2274 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2276 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2278 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2280 SIVAL(*data, 0, 0x00);
2285 if (!StrCaseCmp(value, "BeepEnabled")) {
2287 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2289 SIVAL(*data, 0, 0x00);
2294 if (!StrCaseCmp(value, "EventLog")) {
2296 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2298 /* formally was 0x1b */
2299 SIVAL(*data, 0, 0x0);
2304 if (!StrCaseCmp(value, "NetPopup")) {
2306 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2308 SIVAL(*data, 0, 0x00);
2313 if (!StrCaseCmp(value, "MajorVersion")) {
2315 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2318 /* Windows NT 4.0 seems to not allow uploading of drivers
2319 to a server that reports 0x3 as the MajorVersion.
2320 need to investigate more how Win2k gets around this .
2323 if ( RA_WINNT == get_remote_arch() )
2332 if (!StrCaseCmp(value, "MinorVersion")) {
2334 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2342 * uint32 size = 0x114
2344 * uint32 minor = [0|1]
2345 * uint32 build = [2195|2600]
2346 * extra unicode string = e.g. "Service Pack 3"
2348 if (!StrCaseCmp(value, "OSVersion")) {
2352 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2355 SIVAL(*data, 0, *needed); /* size */
2356 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2358 SIVAL(*data, 12, 2195); /* build */
2360 /* leave extra string empty */
2366 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2367 const char *string="C:\\PRINTERS";
2369 *needed = 2*(strlen(string)+1);
2370 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2372 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2374 /* it's done by hand ready to go on the wire */
2375 for (i=0; i<strlen(string); i++) {
2376 (*data)[2*i]=string[i];
2377 (*data)[2*i+1]='\0';
2382 if (!StrCaseCmp(value, "Architecture")) {
2383 const char *string="Windows NT x86";
2385 *needed = 2*(strlen(string)+1);
2386 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2388 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2389 for (i=0; i<strlen(string); i++) {
2390 (*data)[2*i]=string[i];
2391 (*data)[2*i+1]='\0';
2396 if (!StrCaseCmp(value, "DsPresent")) {
2398 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2401 /* only show the publish check box if we are a
2402 memeber of a AD domain */
2404 if ( lp_security() == SEC_ADS )
2405 SIVAL(*data, 0, 0x01);
2407 SIVAL(*data, 0, 0x00);
2413 if (!StrCaseCmp(value, "DNSMachineName")) {
2414 const char *hostname = get_mydnsfullname();
2417 return WERR_BADFILE;
2419 *needed = 2*(strlen(hostname)+1);
2420 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2422 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2423 for (i=0; i<strlen(hostname); i++) {
2424 (*data)[2*i]=hostname[i];
2425 (*data)[2*i+1]='\0';
2431 return WERR_BADFILE;
2434 /********************************************************************
2435 * spoolss_getprinterdata
2436 ********************************************************************/
2438 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2440 POLICY_HND *handle = &q_u->handle;
2441 UNISTR2 *valuename = &q_u->valuename;
2442 uint32 in_size = q_u->size;
2443 uint32 *type = &r_u->type;
2444 uint32 *out_size = &r_u->size;
2445 uint8 **data = &r_u->data;
2446 uint32 *needed = &r_u->needed;
2449 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2450 NT_PRINTER_INFO_LEVEL *printer = NULL;
2454 * Reminder: when it's a string, the length is in BYTES
2455 * even if UNICODE is negociated.
2460 *out_size = in_size;
2462 /* in case of problem, return some default values */
2467 DEBUG(4,("_spoolss_getprinterdata\n"));
2470 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2471 status = WERR_BADFID;
2475 unistr2_to_ascii(value, valuename, sizeof(value));
2477 if ( Printer->printer_type == SPLHND_SERVER )
2478 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2481 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2482 status = WERR_BADFID;
2486 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2487 if ( !W_ERROR_IS_OK(status) )
2490 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2492 if ( strequal(value, "ChangeId") ) {
2494 *needed = sizeof(uint32);
2495 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2496 status = WERR_NOMEM;
2499 SIVAL( *data, 0, printer->info_2->changeid );
2503 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2506 if (*needed > *out_size)
2507 status = WERR_MORE_DATA;
2510 if ( !W_ERROR_IS_OK(status) )
2512 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2514 /* reply this param doesn't exist */
2517 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2519 free_a_printer( &printer, 2 );
2527 /* cleanup & exit */
2530 free_a_printer( &printer, 2 );
2535 /*********************************************************
2536 Connect to the client machine.
2537 **********************************************************/
2539 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2540 struct sockaddr_storage *client_ss, const char *remote_machine)
2543 struct cli_state *the_cli;
2544 struct sockaddr_storage rm_addr;
2546 if ( is_zero_addr(client_ss) ) {
2547 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2548 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2552 if (ismyaddr(&rm_addr)) {
2553 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2557 char addr[INET6_ADDRSTRLEN];
2558 rm_addr = *client_ss;
2559 print_sockaddr(addr, sizeof(addr), &rm_addr);
2560 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2564 /* setup the connection */
2566 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2567 &rm_addr, 0, "IPC$", "IPC",
2571 0, lp_client_signing(), NULL );
2573 if ( !NT_STATUS_IS_OK( ret ) ) {
2574 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2579 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2580 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2581 cli_shutdown(the_cli);
2586 * Ok - we have an anonymous connection to the IPC$ share.
2587 * Now start the NT Domain stuff :-).
2590 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2591 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2592 remote_machine, nt_errstr(ret)));
2593 cli_shutdown(the_cli);
2597 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2599 (*pp_pipe)->cli = the_cli;
2604 /***************************************************************************
2605 Connect to the client.
2606 ****************************************************************************/
2608 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2609 uint32 localprinter, uint32 type,
2610 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2615 * If it's the first connection, contact the client
2616 * and connect to the IPC$ share anonymously
2618 if (smb_connections==0) {
2619 fstring unix_printer;
2621 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2623 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2626 messaging_register(smbd_messaging_context(), NULL,
2627 MSG_PRINTER_NOTIFY2,
2628 receive_notify2_message_list);
2629 /* Tell the connections db we're now interested in printer
2630 * notify messages. */
2631 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2635 * Tell the specific printing tdb we want messages for this printer
2636 * by registering our PID.
2639 if (!print_notify_register_pid(snum))
2640 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2644 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe,
2651 if (!W_ERROR_IS_OK(result))
2652 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2653 dos_errstr(result)));
2655 return (W_ERROR_IS_OK(result));
2658 /********************************************************************
2660 * ReplyFindFirstPrinterChangeNotifyEx
2662 * before replying OK: status=0 a rpc call is made to the workstation
2663 * asking ReplyOpenPrinter
2665 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2666 * called from api_spoolss_rffpcnex
2667 ********************************************************************/
2669 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2671 POLICY_HND *handle = &q_u->handle;
2672 uint32 flags = q_u->flags;
2673 uint32 options = q_u->options;
2674 UNISTR2 *localmachine = &q_u->localmachine;
2675 uint32 printerlocal = q_u->printerlocal;
2677 SPOOL_NOTIFY_OPTION *option = q_u->option;
2678 struct sockaddr_storage client_ss;
2680 /* store the notify value in the printer struct */
2682 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2685 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2689 Printer->notify.flags=flags;
2690 Printer->notify.options=options;
2691 Printer->notify.printerlocal=printerlocal;
2693 if (Printer->notify.option)
2694 free_spool_notify_option(&Printer->notify.option);
2696 Printer->notify.option=dup_spool_notify_option(option);
2698 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2699 sizeof(Printer->notify.localmachine));
2701 /* Connect to the client machine and send a ReplyOpenPrinter */
2703 if ( Printer->printer_type == SPLHND_SERVER)
2705 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2706 !get_printer_snum(p, handle, &snum, NULL) )
2709 if (!interpret_string_addr(&client_ss,
2710 p->conn->client_address,
2712 return WERR_SERVER_UNAVAILABLE;
2715 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2716 Printer->notify.printerlocal, 1,
2717 &Printer->notify.client_hnd, &client_ss))
2718 return WERR_SERVER_UNAVAILABLE;
2720 Printer->notify.client_connected=True;
2725 /*******************************************************************
2726 * fill a notify_info_data with the servername
2727 ********************************************************************/
2729 void spoolss_notify_server_name(int snum,
2730 SPOOL_NOTIFY_INFO_DATA *data,
2731 print_queue_struct *queue,
2732 NT_PRINTER_INFO_LEVEL *printer,
2733 TALLOC_CTX *mem_ctx)
2735 smb_ucs2_t *temp = NULL;
2738 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2739 if (len == (uint32)-1) {
2743 data->notify_data.data.length = len;
2745 data->notify_data.data.string = (uint16 *)temp;
2747 data->notify_data.data.string = NULL;
2751 /*******************************************************************
2752 * fill a notify_info_data with the printername (not including the servername).
2753 ********************************************************************/
2755 void spoolss_notify_printer_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;
2764 /* the notify name should not contain the \\server\ part */
2765 char *p = strrchr(printer->info_2->printername, '\\');
2768 p = printer->info_2->printername;
2773 len = rpcstr_push_talloc(mem_ctx, &temp, p);
2774 if (len == (uint32)-1) {
2778 data->notify_data.data.length = len;
2780 data->notify_data.data.string = (uint16 *)temp;
2782 data->notify_data.data.string = NULL;
2786 /*******************************************************************
2787 * fill a notify_info_data with the servicename
2788 ********************************************************************/
2790 void spoolss_notify_share_name(int snum,
2791 SPOOL_NOTIFY_INFO_DATA *data,
2792 print_queue_struct *queue,
2793 NT_PRINTER_INFO_LEVEL *printer,
2794 TALLOC_CTX *mem_ctx)
2796 smb_ucs2_t *temp = NULL;
2799 len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2800 if (len == (uint32)-1) {
2804 data->notify_data.data.length = len;
2806 data->notify_data.data.string = (uint16 *)temp;
2808 data->notify_data.data.string = NULL;
2813 /*******************************************************************
2814 * fill a notify_info_data with the port name
2815 ********************************************************************/
2817 void spoolss_notify_port_name(int snum,
2818 SPOOL_NOTIFY_INFO_DATA *data,
2819 print_queue_struct *queue,
2820 NT_PRINTER_INFO_LEVEL *printer,
2821 TALLOC_CTX *mem_ctx)
2823 smb_ucs2_t *temp = NULL;
2826 /* even if it's strange, that's consistant in all the code */
2828 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2829 if (len == (uint32)-1) {
2833 data->notify_data.data.length = len;
2835 data->notify_data.data.string = (uint16 *)temp;
2837 data->notify_data.data.string = NULL;
2841 /*******************************************************************
2842 * fill a notify_info_data with the printername
2843 * but it doesn't exist, have to see what to do
2844 ********************************************************************/
2846 void spoolss_notify_driver_name(int snum,
2847 SPOOL_NOTIFY_INFO_DATA *data,
2848 print_queue_struct *queue,
2849 NT_PRINTER_INFO_LEVEL *printer,
2850 TALLOC_CTX *mem_ctx)
2852 smb_ucs2_t *temp = NULL;
2855 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2856 if (len == (uint32)-1) {
2860 data->notify_data.data.length = len;
2862 data->notify_data.data.string = (uint16 *)temp;
2864 data->notify_data.data.string = NULL;
2868 /*******************************************************************
2869 * fill a notify_info_data with the comment
2870 ********************************************************************/
2872 void spoolss_notify_comment(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;
2881 if (*printer->info_2->comment == '\0')
2882 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2884 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2886 if (len == (uint32)-1) {
2889 data->notify_data.data.length = len;
2891 data->notify_data.data.string = (uint16 *)temp;
2893 data->notify_data.data.string = NULL;
2897 /*******************************************************************
2898 * fill a notify_info_data with the comment
2899 * location = "Room 1, floor 2, building 3"
2900 ********************************************************************/
2902 void spoolss_notify_location(int snum,
2903 SPOOL_NOTIFY_INFO_DATA *data,
2904 print_queue_struct *queue,
2905 NT_PRINTER_INFO_LEVEL *printer,
2906 TALLOC_CTX *mem_ctx)
2908 smb_ucs2_t *temp = NULL;
2911 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2912 if (len == (uint32)-1) {
2916 data->notify_data.data.length = len;
2918 data->notify_data.data.string = (uint16 *)temp;
2920 data->notify_data.data.string = NULL;
2924 /*******************************************************************
2925 * fill a notify_info_data with the device mode
2926 * jfm:xxxx don't to it for know but that's a real problem !!!
2927 ********************************************************************/
2929 static void spoolss_notify_devmode(int snum,
2930 SPOOL_NOTIFY_INFO_DATA *data,
2931 print_queue_struct *queue,
2932 NT_PRINTER_INFO_LEVEL *printer,
2933 TALLOC_CTX *mem_ctx)
2935 /* for a dummy implementation we have to zero the fields */
2936 data->notify_data.data.length = 0;
2937 data->notify_data.data.string = NULL;
2940 /*******************************************************************
2941 * fill a notify_info_data with the separator file name
2942 ********************************************************************/
2944 void spoolss_notify_sepfile(int snum,
2945 SPOOL_NOTIFY_INFO_DATA *data,
2946 print_queue_struct *queue,
2947 NT_PRINTER_INFO_LEVEL *printer,
2948 TALLOC_CTX *mem_ctx)
2950 smb_ucs2_t *temp = NULL;
2953 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2954 if (len == (uint32)-1) {
2958 data->notify_data.data.length = len;
2960 data->notify_data.data.string = (uint16 *)temp;
2962 data->notify_data.data.string = NULL;
2966 /*******************************************************************
2967 * fill a notify_info_data with the print processor
2968 * jfm:xxxx return always winprint to indicate we don't do anything to it
2969 ********************************************************************/
2971 void spoolss_notify_print_processor(int snum,
2972 SPOOL_NOTIFY_INFO_DATA *data,
2973 print_queue_struct *queue,
2974 NT_PRINTER_INFO_LEVEL *printer,
2975 TALLOC_CTX *mem_ctx)
2977 smb_ucs2_t *temp = NULL;
2980 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
2981 if (len == (uint32)-1) {
2985 data->notify_data.data.length = len;
2987 data->notify_data.data.string = (uint16 *)temp;
2989 data->notify_data.data.string = NULL;
2993 /*******************************************************************
2994 * fill a notify_info_data with the print processor options
2995 * jfm:xxxx send an empty string
2996 ********************************************************************/
2998 void spoolss_notify_parameters(int snum,
2999 SPOOL_NOTIFY_INFO_DATA *data,
3000 print_queue_struct *queue,
3001 NT_PRINTER_INFO_LEVEL *printer,
3002 TALLOC_CTX *mem_ctx)
3004 smb_ucs2_t *temp = NULL;
3007 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3008 if (len == (uint32)-1) {
3012 data->notify_data.data.length = len;
3014 data->notify_data.data.string = (uint16 *)temp;
3016 data->notify_data.data.string = NULL;
3020 /*******************************************************************
3021 * fill a notify_info_data with the data type
3022 * jfm:xxxx always send RAW as data type
3023 ********************************************************************/
3025 void spoolss_notify_datatype(int snum,
3026 SPOOL_NOTIFY_INFO_DATA *data,
3027 print_queue_struct *queue,
3028 NT_PRINTER_INFO_LEVEL *printer,
3029 TALLOC_CTX *mem_ctx)
3031 smb_ucs2_t *temp = NULL;
3034 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3035 if (len == (uint32)-1) {
3039 data->notify_data.data.length = len;
3041 data->notify_data.data.string = (uint16 *)temp;
3043 data->notify_data.data.string = NULL;
3047 /*******************************************************************
3048 * fill a notify_info_data with the security descriptor
3049 * jfm:xxxx send an null pointer to say no security desc
3050 * have to implement security before !
3051 ********************************************************************/
3053 static void spoolss_notify_security_desc(int snum,
3054 SPOOL_NOTIFY_INFO_DATA *data,
3055 print_queue_struct *queue,
3056 NT_PRINTER_INFO_LEVEL *printer,
3057 TALLOC_CTX *mem_ctx)
3059 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3060 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3063 /*******************************************************************
3064 * fill a notify_info_data with the attributes
3065 * jfm:xxxx a samba printer is always shared
3066 ********************************************************************/
3068 void spoolss_notify_attributes(int snum,
3069 SPOOL_NOTIFY_INFO_DATA *data,
3070 print_queue_struct *queue,
3071 NT_PRINTER_INFO_LEVEL *printer,
3072 TALLOC_CTX *mem_ctx)
3074 data->notify_data.value[0] = printer->info_2->attributes;
3075 data->notify_data.value[1] = 0;
3078 /*******************************************************************
3079 * fill a notify_info_data with the priority
3080 ********************************************************************/
3082 static void spoolss_notify_priority(int snum,
3083 SPOOL_NOTIFY_INFO_DATA *data,
3084 print_queue_struct *queue,
3085 NT_PRINTER_INFO_LEVEL *printer,
3086 TALLOC_CTX *mem_ctx)
3088 data->notify_data.value[0] = printer->info_2->priority;
3089 data->notify_data.value[1] = 0;
3092 /*******************************************************************
3093 * fill a notify_info_data with the default priority
3094 ********************************************************************/
3096 static void spoolss_notify_default_priority(int snum,
3097 SPOOL_NOTIFY_INFO_DATA *data,
3098 print_queue_struct *queue,
3099 NT_PRINTER_INFO_LEVEL *printer,
3100 TALLOC_CTX *mem_ctx)
3102 data->notify_data.value[0] = printer->info_2->default_priority;
3103 data->notify_data.value[1] = 0;
3106 /*******************************************************************
3107 * fill a notify_info_data with the start time
3108 ********************************************************************/
3110 static void spoolss_notify_start_time(int snum,
3111 SPOOL_NOTIFY_INFO_DATA *data,
3112 print_queue_struct *queue,
3113 NT_PRINTER_INFO_LEVEL *printer,
3114 TALLOC_CTX *mem_ctx)
3116 data->notify_data.value[0] = printer->info_2->starttime;
3117 data->notify_data.value[1] = 0;
3120 /*******************************************************************
3121 * fill a notify_info_data with the until time
3122 ********************************************************************/
3124 static void spoolss_notify_until_time(int snum,
3125 SPOOL_NOTIFY_INFO_DATA *data,
3126 print_queue_struct *queue,
3127 NT_PRINTER_INFO_LEVEL *printer,
3128 TALLOC_CTX *mem_ctx)
3130 data->notify_data.value[0] = printer->info_2->untiltime;
3131 data->notify_data.value[1] = 0;
3134 /*******************************************************************
3135 * fill a notify_info_data with the status
3136 ********************************************************************/
3138 static void spoolss_notify_status(int snum,
3139 SPOOL_NOTIFY_INFO_DATA *data,
3140 print_queue_struct *queue,
3141 NT_PRINTER_INFO_LEVEL *printer,
3142 TALLOC_CTX *mem_ctx)
3144 print_status_struct status;
3146 print_queue_length(snum, &status);
3147 data->notify_data.value[0]=(uint32) status.status;
3148 data->notify_data.value[1] = 0;
3151 /*******************************************************************
3152 * fill a notify_info_data with the number of jobs queued
3153 ********************************************************************/
3155 void spoolss_notify_cjobs(int snum,
3156 SPOOL_NOTIFY_INFO_DATA *data,
3157 print_queue_struct *queue,
3158 NT_PRINTER_INFO_LEVEL *printer,
3159 TALLOC_CTX *mem_ctx)
3161 data->notify_data.value[0] = print_queue_length(snum, NULL);
3162 data->notify_data.value[1] = 0;
3165 /*******************************************************************
3166 * fill a notify_info_data with the average ppm
3167 ********************************************************************/
3169 static void spoolss_notify_average_ppm(int snum,
3170 SPOOL_NOTIFY_INFO_DATA *data,
3171 print_queue_struct *queue,
3172 NT_PRINTER_INFO_LEVEL *printer,
3173 TALLOC_CTX *mem_ctx)
3175 /* always respond 8 pages per minutes */
3176 /* a little hard ! */
3177 data->notify_data.value[0] = printer->info_2->averageppm;
3178 data->notify_data.value[1] = 0;
3181 /*******************************************************************
3182 * fill a notify_info_data with username
3183 ********************************************************************/
3185 static void spoolss_notify_username(int snum,
3186 SPOOL_NOTIFY_INFO_DATA *data,
3187 print_queue_struct *queue,
3188 NT_PRINTER_INFO_LEVEL *printer,
3189 TALLOC_CTX *mem_ctx)
3191 smb_ucs2_t *temp = NULL;
3194 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3195 if (len == (uint32)-1) {
3199 data->notify_data.data.length = len;
3201 data->notify_data.data.string = (uint16 *)temp;
3203 data->notify_data.data.string = NULL;
3207 /*******************************************************************
3208 * fill a notify_info_data with job status
3209 ********************************************************************/
3211 static void spoolss_notify_job_status(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 data->notify_data.value[0]=nt_printj_status(queue->status);
3218 data->notify_data.value[1] = 0;
3221 /*******************************************************************
3222 * fill a notify_info_data with job name
3223 ********************************************************************/
3225 static void spoolss_notify_job_name(int snum,
3226 SPOOL_NOTIFY_INFO_DATA *data,
3227 print_queue_struct *queue,
3228 NT_PRINTER_INFO_LEVEL *printer,
3229 TALLOC_CTX *mem_ctx)
3231 smb_ucs2_t *temp = NULL;
3234 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3235 if (len == (uint32)-1) {
3239 data->notify_data.data.length = len;
3241 data->notify_data.data.string = (uint16 *)temp;
3243 data->notify_data.data.string = NULL;
3247 /*******************************************************************
3248 * fill a notify_info_data with job status
3249 ********************************************************************/
3251 static void spoolss_notify_job_status_string(int snum,
3252 SPOOL_NOTIFY_INFO_DATA *data,
3253 print_queue_struct *queue,
3254 NT_PRINTER_INFO_LEVEL *printer,
3255 TALLOC_CTX *mem_ctx)
3258 * Now we're returning job status codes we just return a "" here. JRA.
3262 smb_ucs2_t *temp = NULL;
3265 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3268 switch (queue->status) {
3273 p = ""; /* NT provides the paused string */
3282 #endif /* NO LONGER NEEDED. */
3284 len = rpcstr_push_talloc(mem_ctx, &temp, p);
3285 if (len == (uint32)-1) {
3289 data->notify_data.data.length = len;
3291 data->notify_data.data.string = (uint16 *)temp;
3293 data->notify_data.data.string = NULL;
3297 /*******************************************************************
3298 * fill a notify_info_data with job time
3299 ********************************************************************/
3301 static void spoolss_notify_job_time(int snum,
3302 SPOOL_NOTIFY_INFO_DATA *data,
3303 print_queue_struct *queue,
3304 NT_PRINTER_INFO_LEVEL *printer,
3305 TALLOC_CTX *mem_ctx)
3307 data->notify_data.value[0]=0x0;
3308 data->notify_data.value[1]=0;
3311 /*******************************************************************
3312 * fill a notify_info_data with job size
3313 ********************************************************************/
3315 static void spoolss_notify_job_size(int snum,
3316 SPOOL_NOTIFY_INFO_DATA *data,
3317 print_queue_struct *queue,
3318 NT_PRINTER_INFO_LEVEL *printer,
3319 TALLOC_CTX *mem_ctx)
3321 data->notify_data.value[0]=queue->size;
3322 data->notify_data.value[1]=0;
3325 /*******************************************************************
3326 * fill a notify_info_data with page info
3327 ********************************************************************/
3328 static void spoolss_notify_total_pages(int snum,
3329 SPOOL_NOTIFY_INFO_DATA *data,
3330 print_queue_struct *queue,
3331 NT_PRINTER_INFO_LEVEL *printer,
3332 TALLOC_CTX *mem_ctx)
3334 data->notify_data.value[0]=queue->page_count;
3335 data->notify_data.value[1]=0;
3338 /*******************************************************************
3339 * fill a notify_info_data with pages printed info.
3340 ********************************************************************/
3341 static void spoolss_notify_pages_printed(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]=0; /* Add code when back-end tracks this */
3348 data->notify_data.value[1]=0;
3351 /*******************************************************************
3352 Fill a notify_info_data with job position.
3353 ********************************************************************/
3355 static void spoolss_notify_job_position(int snum,
3356 SPOOL_NOTIFY_INFO_DATA *data,
3357 print_queue_struct *queue,
3358 NT_PRINTER_INFO_LEVEL *printer,
3359 TALLOC_CTX *mem_ctx)
3361 data->notify_data.value[0]=queue->job;
3362 data->notify_data.value[1]=0;
3365 /*******************************************************************
3366 Fill a notify_info_data with submitted time.
3367 ********************************************************************/
3369 static void spoolss_notify_submitted_time(int snum,
3370 SPOOL_NOTIFY_INFO_DATA *data,
3371 print_queue_struct *queue,
3372 NT_PRINTER_INFO_LEVEL *printer,
3373 TALLOC_CTX *mem_ctx)
3380 t=gmtime(&queue->time);
3382 len = sizeof(SYSTEMTIME);
3384 data->notify_data.data.length = len;
3385 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3387 if (!data->notify_data.data.string) {
3388 data->notify_data.data.length = 0;
3392 make_systemtime(&st, t);
3395 * Systemtime must be linearized as a set of UINT16's.
3396 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3399 p = (char *)data->notify_data.data.string;
3400 SSVAL(p, 0, st.year);
3401 SSVAL(p, 2, st.month);
3402 SSVAL(p, 4, st.dayofweek);
3403 SSVAL(p, 6, st.day);
3404 SSVAL(p, 8, st.hour);
3405 SSVAL(p, 10, st.minute);
3406 SSVAL(p, 12, st.second);
3407 SSVAL(p, 14, st.milliseconds);
3410 struct s_notify_info_data_table
3416 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3417 print_queue_struct *queue,
3418 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3421 /* A table describing the various print notification constants and
3422 whether the notification data is a pointer to a variable sized
3423 buffer, a one value uint32 or a two value uint32. */
3425 static const struct s_notify_info_data_table notify_info_data_table[] =
3427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3453 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3454 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3455 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3456 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3457 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3458 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3463 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3476 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3479 /*******************************************************************
3480 Return the size of info_data structure.
3481 ********************************************************************/
3483 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3487 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3488 if ( (notify_info_data_table[i].type == type)
3489 && (notify_info_data_table[i].field == field) ) {
3490 switch(notify_info_data_table[i].size) {
3491 case NOTIFY_ONE_VALUE:
3492 case NOTIFY_TWO_VALUE:
3497 /* The only pointer notify data I have seen on
3498 the wire is the submitted time and this has
3499 the notify size set to 4. -tpot */
3501 case NOTIFY_POINTER:
3504 case NOTIFY_SECDESC:
3510 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3515 /*******************************************************************
3516 Return the type of notify_info_data.
3517 ********************************************************************/
3519 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3523 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3524 if (notify_info_data_table[i].type == type &&
3525 notify_info_data_table[i].field == field)
3526 return notify_info_data_table[i].size;
3532 /****************************************************************************
3533 ****************************************************************************/
3535 static bool search_notify(uint16 type, uint16 field, int *value)
3539 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3540 if (notify_info_data_table[i].type == type &&
3541 notify_info_data_table[i].field == field &&
3542 notify_info_data_table[i].fn != NULL) {
3551 /****************************************************************************
3552 ****************************************************************************/
3554 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3556 info_data->type = type;
3557 info_data->field = field;
3558 info_data->reserved = 0;
3560 info_data->size = size_of_notify_info_data(type, field);
3561 info_data->enc_type = type_of_notify_info_data(type, field);
3566 /*******************************************************************
3568 * fill a notify_info struct with info asked
3570 ********************************************************************/
3572 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3573 snum, SPOOL_NOTIFY_OPTION_TYPE
3574 *option_type, uint32 id,
3575 TALLOC_CTX *mem_ctx)
3581 SPOOL_NOTIFY_INFO_DATA *current_data;
3582 NT_PRINTER_INFO_LEVEL *printer = NULL;
3583 print_queue_struct *queue=NULL;
3585 type=option_type->type;
3587 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3588 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3589 option_type->count, lp_servicename(snum)));
3591 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3594 for(field_num=0; field_num<option_type->count; field_num++) {
3595 field = option_type->fields[field_num];
3597 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3599 if (!search_notify(type, field, &j) )
3602 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3603 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3604 free_a_printer(&printer, 2);
3608 current_data = &info->data[info->count];
3610 construct_info_data(current_data, type, field, id);
3612 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3613 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3615 notify_info_data_table[j].fn(snum, current_data, queue,
3621 free_a_printer(&printer, 2);
3625 /*******************************************************************
3627 * fill a notify_info struct with info asked
3629 ********************************************************************/
3631 static bool construct_notify_jobs_info(print_queue_struct *queue,
3632 SPOOL_NOTIFY_INFO *info,
3633 NT_PRINTER_INFO_LEVEL *printer,
3634 int snum, SPOOL_NOTIFY_OPTION_TYPE
3635 *option_type, uint32 id,
3636 TALLOC_CTX *mem_ctx)
3642 SPOOL_NOTIFY_INFO_DATA *current_data;
3644 DEBUG(4,("construct_notify_jobs_info\n"));
3646 type = option_type->type;
3648 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3649 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3650 option_type->count));
3652 for(field_num=0; field_num<option_type->count; field_num++) {
3653 field = option_type->fields[field_num];
3655 if (!search_notify(type, field, &j) )
3658 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3659 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3663 current_data=&(info->data[info->count]);
3665 construct_info_data(current_data, type, field, id);
3666 notify_info_data_table[j].fn(snum, current_data, queue,
3675 * JFM: The enumeration is not that simple, it's even non obvious.
3677 * let's take an example: I want to monitor the PRINTER SERVER for
3678 * the printer's name and the number of jobs currently queued.
3679 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3680 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3682 * I have 3 printers on the back of my server.
3684 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3687 * 1 printer 1 name 1
3688 * 2 printer 1 cjob 1
3689 * 3 printer 2 name 2
3690 * 4 printer 2 cjob 2
3691 * 5 printer 3 name 3
3692 * 6 printer 3 name 3
3694 * that's the print server case, the printer case is even worse.
3697 /*******************************************************************
3699 * enumerate all printers on the printserver
3700 * fill a notify_info struct with info asked
3702 ********************************************************************/
3704 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3705 SPOOL_NOTIFY_INFO *info,
3706 TALLOC_CTX *mem_ctx)
3709 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3710 int n_services=lp_numservices();
3712 SPOOL_NOTIFY_OPTION *option;
3713 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3715 DEBUG(4,("printserver_notify_info\n"));
3720 option=Printer->notify.option;
3725 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3726 sending a ffpcn() request first */
3731 for (i=0; i<option->count; i++) {
3732 option_type=&(option->ctr.type[i]);
3734 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3737 for (snum=0; snum<n_services; snum++)
3739 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3740 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3746 * Debugging information, don't delete.
3749 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3750 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3751 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3753 for (i=0; i<info->count; i++) {
3754 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3755 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3756 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3763 /*******************************************************************
3765 * fill a notify_info struct with info asked
3767 ********************************************************************/
3769 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3770 TALLOC_CTX *mem_ctx)
3773 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3776 SPOOL_NOTIFY_OPTION *option;
3777 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3779 print_queue_struct *queue=NULL;
3780 print_status_struct status;
3782 DEBUG(4,("printer_notify_info\n"));
3787 option=Printer->notify.option;
3793 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3794 sending a ffpcn() request first */
3799 get_printer_snum(p, hnd, &snum, NULL);
3801 for (i=0; i<option->count; i++) {
3802 option_type=&option->ctr.type[i];
3804 switch ( option_type->type ) {
3805 case PRINTER_NOTIFY_TYPE:
3806 if(construct_notify_printer_info(Printer, info, snum,
3812 case JOB_NOTIFY_TYPE: {
3813 NT_PRINTER_INFO_LEVEL *printer = NULL;
3815 count = print_queue_status(snum, &queue, &status);
3817 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3820 for (j=0; j<count; j++) {
3821 construct_notify_jobs_info(&queue[j], info,
3828 free_a_printer(&printer, 2);
3838 * Debugging information, don't delete.
3841 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3842 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3843 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3845 for (i=0; i<info->count; i++) {
3846 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3847 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3848 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3854 /********************************************************************
3856 ********************************************************************/
3858 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3860 POLICY_HND *handle = &q_u->handle;
3861 SPOOL_NOTIFY_INFO *info = &r_u->info;
3863 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3864 WERROR result = WERR_BADFID;
3866 /* we always have a NOTIFY_INFO struct */
3870 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3871 OUR_HANDLE(handle)));
3875 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3878 * We are now using the change value, and
3879 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3880 * I don't have a global notification system, I'm sending back all the
3881 * informations even when _NOTHING_ has changed.
3884 /* We need to keep track of the change value to send back in
3885 RRPCN replies otherwise our updates are ignored. */
3887 Printer->notify.fnpcn = True;
3889 if (Printer->notify.client_connected) {
3890 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3891 Printer->notify.change = q_u->change;
3894 /* just ignore the SPOOL_NOTIFY_OPTION */
3896 switch (Printer->printer_type) {
3898 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3901 case SPLHND_PRINTER:
3902 result = printer_notify_info(p, handle, info, p->mem_ctx);
3906 Printer->notify.fnpcn = False;
3912 /********************************************************************
3913 * construct_printer_info_0
3914 * fill a printer_info_0 struct
3915 ********************************************************************/
3917 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3919 char *chaine = NULL;
3921 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3922 counter_printer_0 *session_counter;
3923 uint32 global_counter;
3926 print_status_struct status;
3927 TALLOC_CTX *ctx = talloc_tos();
3929 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3932 init_unistr(&printer->printername, ntprinter->info_2->printername);
3934 chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3936 free_a_printer(&ntprinter,2);
3940 count = print_queue_length(snum, &status);
3942 /* check if we already have a counter for this printer */
3943 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3944 if (session_counter->snum == snum)
3948 init_unistr(&printer->servername, chaine);
3950 /* it's the first time, add it to the list */
3951 if (session_counter==NULL) {
3952 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3953 free_a_printer(&ntprinter, 2);
3956 ZERO_STRUCTP(session_counter);
3957 session_counter->snum=snum;
3958 session_counter->counter=0;
3959 DLIST_ADD(counter_list, session_counter);
3963 session_counter->counter++;
3966 * the global_counter should be stored in a TDB as it's common to all the clients
3967 * and should be zeroed on samba startup
3969 global_counter=session_counter->counter;
3970 printer->cjobs = count;
3971 printer->total_jobs = 0;
3972 printer->total_bytes = 0;
3974 setuptime = (time_t)ntprinter->info_2->setuptime;
3975 t=gmtime(&setuptime);
3977 printer->year = t->tm_year+1900;
3978 printer->month = t->tm_mon+1;
3979 printer->dayofweek = t->tm_wday;
3980 printer->day = t->tm_mday;
3981 printer->hour = t->tm_hour;
3982 printer->minute = t->tm_min;
3983 printer->second = t->tm_sec;
3984 printer->milliseconds = 0;
3986 printer->global_counter = global_counter;
3987 printer->total_pages = 0;
3989 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3990 printer->major_version = 0x0005; /* NT 5 */
3991 printer->build_version = 0x0893; /* build 2195 */
3993 printer->unknown7 = 0x1;
3994 printer->unknown8 = 0x0;
3995 printer->unknown9 = 0x0;
3996 printer->session_counter = session_counter->counter;
3997 printer->unknown11 = 0x0;
3998 printer->printer_errors = 0x0; /* number of print failure */
3999 printer->unknown13 = 0x0;
4000 printer->unknown14 = 0x1;
4001 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4002 printer->unknown16 = 0x0;
4003 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4004 printer->unknown18 = 0x0;
4005 printer->status = nt_printq_status(status.status);
4006 printer->unknown20 = 0x0;
4007 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4008 printer->unknown22 = 0x0;
4009 printer->unknown23 = 0x6; /* 6 ???*/
4010 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4011 printer->unknown25 = 0;
4012 printer->unknown26 = 0;
4013 printer->unknown27 = 0;
4014 printer->unknown28 = 0;
4015 printer->unknown29 = 0;
4017 free_a_printer(&ntprinter,2);
4021 /********************************************************************
4022 * construct_printer_info_1
4023 * fill a printer_info_1 struct
4024 ********************************************************************/
4025 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4027 char *chaine = NULL;
4028 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4029 TALLOC_CTX *ctx = talloc_tos();
4031 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4034 printer->flags=flags;
4036 if (*ntprinter->info_2->comment == '\0') {
4037 init_unistr(&printer->comment, lp_comment(snum));
4038 chaine = talloc_asprintf(ctx,
4039 "%s,%s,%s", ntprinter->info_2->printername,
4040 ntprinter->info_2->drivername, lp_comment(snum));
4043 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4044 chaine = talloc_asprintf(ctx,
4045 "%s,%s,%s", ntprinter->info_2->printername,
4046 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4050 free_a_printer(&ntprinter,2);
4054 init_unistr(&printer->description, chaine);
4055 init_unistr(&printer->name, ntprinter->info_2->printername);
4057 free_a_printer(&ntprinter,2);
4062 /****************************************************************************
4063 Free a DEVMODE struct.
4064 ****************************************************************************/
4066 static void free_dev_mode(DEVICEMODE *dev)
4071 SAFE_FREE(dev->dev_private);
4076 /****************************************************************************
4077 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4078 should be valid upon entry
4079 ****************************************************************************/
4081 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4083 if ( !devmode || !ntdevmode )
4086 init_unistr(&devmode->devicename, ntdevmode->devicename);
4088 init_unistr(&devmode->formname, ntdevmode->formname);
4090 devmode->specversion = ntdevmode->specversion;
4091 devmode->driverversion = ntdevmode->driverversion;
4092 devmode->size = ntdevmode->size;
4093 devmode->driverextra = ntdevmode->driverextra;
4094 devmode->fields = ntdevmode->fields;
4096 devmode->orientation = ntdevmode->orientation;
4097 devmode->papersize = ntdevmode->papersize;
4098 devmode->paperlength = ntdevmode->paperlength;
4099 devmode->paperwidth = ntdevmode->paperwidth;
4100 devmode->scale = ntdevmode->scale;
4101 devmode->copies = ntdevmode->copies;
4102 devmode->defaultsource = ntdevmode->defaultsource;
4103 devmode->printquality = ntdevmode->printquality;
4104 devmode->color = ntdevmode->color;
4105 devmode->duplex = ntdevmode->duplex;
4106 devmode->yresolution = ntdevmode->yresolution;
4107 devmode->ttoption = ntdevmode->ttoption;
4108 devmode->collate = ntdevmode->collate;
4109 devmode->icmmethod = ntdevmode->icmmethod;
4110 devmode->icmintent = ntdevmode->icmintent;
4111 devmode->mediatype = ntdevmode->mediatype;
4112 devmode->dithertype = ntdevmode->dithertype;
4114 if (ntdevmode->nt_dev_private != NULL) {
4115 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4122 /****************************************************************************
4123 Create a DEVMODE struct. Returns malloced memory.
4124 ****************************************************************************/
4126 DEVICEMODE *construct_dev_mode(const char *servicename)
4128 NT_PRINTER_INFO_LEVEL *printer = NULL;
4129 DEVICEMODE *devmode = NULL;
4131 DEBUG(7,("construct_dev_mode\n"));
4133 DEBUGADD(8,("getting printer characteristics\n"));
4135 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4138 if ( !printer->info_2->devmode ) {
4139 DEBUG(5, ("BONG! There was no device mode!\n"));
4143 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4144 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4148 ZERO_STRUCTP(devmode);
4150 DEBUGADD(8,("loading DEVICEMODE\n"));
4152 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4153 free_dev_mode( devmode );
4158 free_a_printer(&printer,2);
4163 /********************************************************************
4164 * construct_printer_info_2
4165 * fill a printer_info_2 struct
4166 ********************************************************************/
4168 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4171 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4173 print_status_struct status;
4175 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4178 count = print_queue_length(snum, &status);
4180 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4181 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4182 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4183 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4184 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4186 if (*ntprinter->info_2->comment == '\0')
4187 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4189 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4191 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4192 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4193 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4194 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4195 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4197 printer->attributes = ntprinter->info_2->attributes;
4199 printer->priority = ntprinter->info_2->priority; /* priority */
4200 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4201 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4202 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4203 printer->status = nt_printq_status(status.status); /* status */
4204 printer->cjobs = count; /* jobs */
4205 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4207 if ( !(printer->devmode = construct_dev_mode(
4208 lp_const_servicename(snum))) )
4209 DEBUG(8, ("Returning NULL Devicemode!\n"));
4211 printer->secdesc = NULL;
4213 if ( ntprinter->info_2->secdesc_buf
4214 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4216 /* don't use talloc_steal() here unless you do a deep steal of all
4217 the SEC_DESC members */
4219 printer->secdesc = dup_sec_desc( talloc_tos(),
4220 ntprinter->info_2->secdesc_buf->sd );
4223 free_a_printer(&ntprinter, 2);
4228 /********************************************************************
4229 * construct_printer_info_3
4230 * fill a printer_info_3 struct
4231 ********************************************************************/
4233 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4235 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4236 PRINTER_INFO_3 *printer = NULL;
4238 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4242 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4243 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4244 free_a_printer(&ntprinter, 2);
4248 ZERO_STRUCTP(printer);
4250 /* These are the components of the SD we are returning. */
4252 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4253 /* don't use talloc_steal() here unless you do a deep steal of all
4254 the SEC_DESC members */
4256 printer->secdesc = dup_sec_desc( talloc_tos(),
4257 ntprinter->info_2->secdesc_buf->sd );
4260 free_a_printer(&ntprinter, 2);
4262 *pp_printer = printer;
4266 /********************************************************************
4267 * construct_printer_info_4
4268 * fill a printer_info_4 struct
4269 ********************************************************************/
4271 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4273 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4275 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4278 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4279 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4280 printer->attributes = ntprinter->info_2->attributes;
4282 free_a_printer(&ntprinter, 2);
4286 /********************************************************************
4287 * construct_printer_info_5
4288 * fill a printer_info_5 struct
4289 ********************************************************************/
4291 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4293 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4295 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4298 init_unistr(&printer->printername, ntprinter->info_2->printername);
4299 init_unistr(&printer->portname, ntprinter->info_2->portname);
4300 printer->attributes = ntprinter->info_2->attributes;
4302 /* these two are not used by NT+ according to MSDN */
4304 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4305 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4307 free_a_printer(&ntprinter, 2);
4312 /********************************************************************
4313 * construct_printer_info_6
4314 * fill a printer_info_6 struct
4315 ********************************************************************/
4317 static bool construct_printer_info_6(Printer_entry *print_hnd,
4318 PRINTER_INFO_6 *printer,
4321 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4323 print_status_struct status;
4325 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4326 lp_const_servicename(snum))))
4329 count = print_queue_length(snum, &status);
4331 printer->status = nt_printq_status(status.status);
4333 free_a_printer(&ntprinter, 2);
4338 /********************************************************************
4339 * construct_printer_info_7
4340 * fill a printer_info_7 struct
4341 ********************************************************************/
4343 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4345 char *guid_str = NULL;
4348 if (is_printer_published(print_hnd, snum, &guid)) {
4349 asprintf(&guid_str, "{%s}",
4350 smb_uuid_string(talloc_tos(), guid));
4351 strupper_m(guid_str);
4352 init_unistr(&printer->guid, guid_str);
4353 printer->action = SPOOL_DS_PUBLISH;
4355 init_unistr(&printer->guid, "");
4356 printer->action = SPOOL_DS_UNPUBLISH;
4362 /********************************************************************
4363 Spoolss_enumprinters.
4364 ********************************************************************/
4366 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4370 int n_services=lp_numservices();
4371 PRINTER_INFO_1 *printers=NULL;
4372 PRINTER_INFO_1 current_prt;
4373 WERROR result = WERR_OK;
4375 DEBUG(4,("enum_all_printers_info_1\n"));
4377 for (snum=0; snum<n_services; snum++) {
4378 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4379 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4381 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4382 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4383 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4387 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4389 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4395 /* check the required size. */
4396 for (i=0; i<*returned; i++)
4397 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4399 if (*needed > offered) {
4400 result = WERR_INSUFFICIENT_BUFFER;
4404 if (!rpcbuf_alloc_size(buffer, *needed)) {
4405 result = WERR_NOMEM;
4409 /* fill the buffer with the structures */
4410 for (i=0; i<*returned; i++)
4411 smb_io_printer_info_1("", buffer, &printers[i], 0);
4416 SAFE_FREE(printers);
4418 if ( !W_ERROR_IS_OK(result) )
4424 /********************************************************************
4425 enum_all_printers_info_1_local.
4426 *********************************************************************/
4428 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4430 DEBUG(4,("enum_all_printers_info_1_local\n"));
4432 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4435 /********************************************************************
4436 enum_all_printers_info_1_name.
4437 *********************************************************************/
4439 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4443 DEBUG(4,("enum_all_printers_info_1_name\n"));
4445 if ((name[0] == '\\') && (name[1] == '\\'))
4448 if (is_myname_or_ipaddr(s)) {
4449 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4452 return WERR_INVALID_NAME;
4455 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4456 /********************************************************************
4457 enum_all_printers_info_1_remote.
4458 *********************************************************************/
4460 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4462 PRINTER_INFO_1 *printer;
4463 fstring printername;
4466 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4467 WERROR result = WERR_OK;
4469 /* JFM: currently it's more a place holder than anything else.
4470 * In the spooler world there is a notion of server registration.
4471 * the print servers are registered on the PDC (in the same domain)
4473 * We should have a TDB here. The registration is done thru an
4474 * undocumented RPC call.
4477 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4482 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4483 slprintf(desc, sizeof(desc)-1,"%s", name);
4484 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4486 init_unistr(&printer->description, desc);
4487 init_unistr(&printer->name, printername);
4488 init_unistr(&printer->comment, comment);
4489 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4491 /* check the required size. */
4492 *needed += spoolss_size_printer_info_1(printer);
4494 if (*needed > offered) {
4495 result = WERR_INSUFFICIENT_BUFFER;
4499 if (!rpcbuf_alloc_size(buffer, *needed)) {
4500 result = WERR_NOMEM;
4504 /* fill the buffer with the structures */
4505 smb_io_printer_info_1("", buffer, printer, 0);
4511 if ( !W_ERROR_IS_OK(result) )
4519 /********************************************************************
4520 enum_all_printers_info_1_network.
4521 *********************************************************************/
4523 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4527 DEBUG(4,("enum_all_printers_info_1_network\n"));
4529 /* If we respond to a enum_printers level 1 on our name with flags
4530 set to PRINTER_ENUM_REMOTE with a list of printers then these
4531 printers incorrectly appear in the APW browse list.
4532 Specifically the printers for the server appear at the workgroup
4533 level where all the other servers in the domain are
4534 listed. Windows responds to this call with a
4535 WERR_CAN_NOT_COMPLETE so we should do the same. */
4537 if (name[0] == '\\' && name[1] == '\\')
4540 if (is_myname_or_ipaddr(s))
4541 return WERR_CAN_NOT_COMPLETE;
4543 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4546 /********************************************************************
4547 * api_spoolss_enumprinters
4549 * called from api_spoolss_enumprinters (see this to understand)
4550 ********************************************************************/
4552 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4556 int n_services=lp_numservices();
4557 PRINTER_INFO_2 *printers=NULL;
4558 PRINTER_INFO_2 current_prt;
4559 WERROR result = WERR_OK;
4563 for (snum=0; snum<n_services; snum++) {
4564 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4565 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4567 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4568 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4569 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4574 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4576 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4583 /* check the required size. */
4584 for (i=0; i<*returned; i++)
4585 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4587 if (*needed > offered) {
4588 result = WERR_INSUFFICIENT_BUFFER;
4592 if (!rpcbuf_alloc_size(buffer, *needed)) {
4593 result = WERR_NOMEM;
4597 /* fill the buffer with the structures */
4598 for (i=0; i<*returned; i++)
4599 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4604 for (i=0; i<*returned; i++)
4605 free_devmode(printers[i].devmode);
4607 SAFE_FREE(printers);
4609 if ( !W_ERROR_IS_OK(result) )
4615 /********************************************************************
4616 * handle enumeration of printers at level 1
4617 ********************************************************************/
4619 static WERROR enumprinters_level1( uint32 flags, fstring name,
4620 RPC_BUFFER *buffer, uint32 offered,
4621 uint32 *needed, uint32 *returned)
4623 /* Not all the flags are equals */
4625 if (flags & PRINTER_ENUM_LOCAL)
4626 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4628 if (flags & PRINTER_ENUM_NAME)
4629 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4631 #if 0 /* JERRY - disabled for now */
4632 if (flags & PRINTER_ENUM_REMOTE)
4633 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4636 if (flags & PRINTER_ENUM_NETWORK)
4637 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4639 return WERR_OK; /* NT4sp5 does that */
4642 /********************************************************************
4643 * handle enumeration of printers at level 2
4644 ********************************************************************/
4646 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4647 RPC_BUFFER *buffer, uint32 offered,
4648 uint32 *needed, uint32 *returned)
4650 char *s = servername;
4652 if (flags & PRINTER_ENUM_LOCAL) {
4653 return enum_all_printers_info_2(buffer, offered, needed, returned);
4656 if (flags & PRINTER_ENUM_NAME) {
4657 if ((servername[0] == '\\') && (servername[1] == '\\'))
4659 if (is_myname_or_ipaddr(s))
4660 return enum_all_printers_info_2(buffer, offered, needed, returned);
4662 return WERR_INVALID_NAME;
4665 if (flags & PRINTER_ENUM_REMOTE)
4666 return WERR_UNKNOWN_LEVEL;
4671 /********************************************************************
4672 * handle enumeration of printers at level 5
4673 ********************************************************************/
4675 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4676 RPC_BUFFER *buffer, uint32 offered,
4677 uint32 *needed, uint32 *returned)
4679 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4683 /********************************************************************
4684 * api_spoolss_enumprinters
4686 * called from api_spoolss_enumprinters (see this to understand)
4687 ********************************************************************/
4689 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4691 uint32 flags = q_u->flags;
4692 UNISTR2 *servername = &q_u->servername;
4693 uint32 level = q_u->level;
4694 RPC_BUFFER *buffer = NULL;
4695 uint32 offered = q_u->offered;
4696 uint32 *needed = &r_u->needed;
4697 uint32 *returned = &r_u->returned;
4701 /* that's an [in out] buffer */
4703 if (!q_u->buffer && (offered!=0)) {
4704 return WERR_INVALID_PARAM;
4707 rpcbuf_move(q_u->buffer, &r_u->buffer);
4708 buffer = r_u->buffer;
4710 DEBUG(4,("_spoolss_enumprinters\n"));
4717 * flags==PRINTER_ENUM_NAME
4718 * if name=="" then enumerates all printers
4719 * if name!="" then enumerate the printer
4720 * flags==PRINTER_ENUM_REMOTE
4721 * name is NULL, enumerate printers
4722 * Level 2: name!="" enumerates printers, name can't be NULL
4723 * Level 3: doesn't exist
4724 * Level 4: does a local registry lookup
4725 * Level 5: same as Level 2
4728 unistr2_to_ascii(name, servername, sizeof(name));
4733 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4735 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4737 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4742 return WERR_UNKNOWN_LEVEL;
4745 /****************************************************************************
4746 ****************************************************************************/
4748 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4750 PRINTER_INFO_0 *printer=NULL;
4751 WERROR result = WERR_OK;
4753 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4756 construct_printer_info_0(print_hnd, printer, snum);
4758 /* check the required size. */
4759 *needed += spoolss_size_printer_info_0(printer);
4761 if (*needed > offered) {
4762 result = WERR_INSUFFICIENT_BUFFER;
4766 if (!rpcbuf_alloc_size(buffer, *needed)) {
4767 result = WERR_NOMEM;
4771 /* fill the buffer with the structures */
4772 smb_io_printer_info_0("", buffer, printer, 0);
4782 /****************************************************************************
4783 ****************************************************************************/
4785 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4787 PRINTER_INFO_1 *printer=NULL;
4788 WERROR result = WERR_OK;
4790 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4793 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4795 /* check the required size. */
4796 *needed += spoolss_size_printer_info_1(printer);
4798 if (*needed > offered) {
4799 result = WERR_INSUFFICIENT_BUFFER;
4803 if (!rpcbuf_alloc_size(buffer, *needed)) {
4804 result = WERR_NOMEM;
4808 /* fill the buffer with the structures */
4809 smb_io_printer_info_1("", buffer, printer, 0);
4818 /****************************************************************************
4819 ****************************************************************************/
4821 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4823 PRINTER_INFO_2 *printer=NULL;
4824 WERROR result = WERR_OK;
4826 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4829 construct_printer_info_2(print_hnd, printer, snum);
4831 /* check the required size. */
4832 *needed += spoolss_size_printer_info_2(printer);
4834 if (*needed > offered) {
4835 result = WERR_INSUFFICIENT_BUFFER;
4839 if (!rpcbuf_alloc_size(buffer, *needed)) {
4840 result = WERR_NOMEM;
4844 /* fill the buffer with the structures */
4845 if (!smb_io_printer_info_2("", buffer, printer, 0))
4846 result = WERR_NOMEM;
4850 free_printer_info_2(printer);
4855 /****************************************************************************
4856 ****************************************************************************/
4858 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4860 PRINTER_INFO_3 *printer=NULL;
4861 WERROR result = WERR_OK;
4863 if (!construct_printer_info_3(print_hnd, &printer, snum))
4866 /* check the required size. */
4867 *needed += spoolss_size_printer_info_3(printer);
4869 if (*needed > offered) {
4870 result = WERR_INSUFFICIENT_BUFFER;
4874 if (!rpcbuf_alloc_size(buffer, *needed)) {
4875 result = WERR_NOMEM;
4879 /* fill the buffer with the structures */
4880 smb_io_printer_info_3("", buffer, printer, 0);
4884 free_printer_info_3(printer);
4889 /****************************************************************************
4890 ****************************************************************************/
4892 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4894 PRINTER_INFO_4 *printer=NULL;
4895 WERROR result = WERR_OK;
4897 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4900 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4905 /* check the required size. */
4906 *needed += spoolss_size_printer_info_4(printer);
4908 if (*needed > offered) {
4909 result = WERR_INSUFFICIENT_BUFFER;
4913 if (!rpcbuf_alloc_size(buffer, *needed)) {
4914 result = WERR_NOMEM;
4918 /* fill the buffer with the structures */
4919 smb_io_printer_info_4("", buffer, printer, 0);
4923 free_printer_info_4(printer);
4928 /****************************************************************************
4929 ****************************************************************************/
4931 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4933 PRINTER_INFO_5 *printer=NULL;
4934 WERROR result = WERR_OK;
4936 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4939 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4940 free_printer_info_5(printer);
4944 /* check the required size. */
4945 *needed += spoolss_size_printer_info_5(printer);
4947 if (*needed > offered) {
4948 result = WERR_INSUFFICIENT_BUFFER;
4952 if (!rpcbuf_alloc_size(buffer, *needed)) {
4953 result = WERR_NOMEM;
4957 /* fill the buffer with the structures */
4958 smb_io_printer_info_5("", buffer, printer, 0);
4962 free_printer_info_5(printer);
4967 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4969 RPC_BUFFER *buffer, uint32 offered,
4972 PRINTER_INFO_6 *printer;
4973 WERROR result = WERR_OK;
4975 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4979 if (!construct_printer_info_6(print_hnd, printer, snum)) {
4980 free_printer_info_6(printer);
4984 /* check the required size. */
4985 *needed += spoolss_size_printer_info_6(printer);
4987 if (*needed > offered) {
4988 result = WERR_INSUFFICIENT_BUFFER;
4992 if (!rpcbuf_alloc_size(buffer, *needed)) {
4993 result = WERR_NOMEM;
4997 /* fill the buffer with the structures */
4998 smb_io_printer_info_6("", buffer, printer, 0);
5002 free_printer_info_6(printer);
5007 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5009 PRINTER_INFO_7 *printer=NULL;
5010 WERROR result = WERR_OK;
5012 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5015 if (!construct_printer_info_7(print_hnd, printer, snum))
5018 /* check the required size. */
5019 *needed += spoolss_size_printer_info_7(printer);
5021 if (*needed > offered) {
5022 result = WERR_INSUFFICIENT_BUFFER;
5026 if (!rpcbuf_alloc_size(buffer, *needed)) {
5027 result = WERR_NOMEM;
5032 /* fill the buffer with the structures */
5033 smb_io_printer_info_7("", buffer, printer, 0);
5037 free_printer_info_7(printer);
5042 /****************************************************************************
5043 ****************************************************************************/
5045 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5047 POLICY_HND *handle = &q_u->handle;
5048 uint32 level = q_u->level;
5049 RPC_BUFFER *buffer = NULL;
5050 uint32 offered = q_u->offered;
5051 uint32 *needed = &r_u->needed;
5052 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5056 /* that's an [in out] buffer */
5058 if (!q_u->buffer && (offered!=0)) {
5059 return WERR_INVALID_PARAM;
5062 rpcbuf_move(q_u->buffer, &r_u->buffer);
5063 buffer = r_u->buffer;
5067 if (!get_printer_snum(p, handle, &snum, NULL))
5072 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5074 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5076 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5078 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5080 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5082 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5084 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5086 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5088 return WERR_UNKNOWN_LEVEL;
5091 /********************************************************************
5092 * fill a DRIVER_INFO_1 struct
5093 ********************************************************************/
5095 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5097 init_unistr( &info->name, driver.info_3->name);
5100 /********************************************************************
5101 * construct_printer_driver_info_1
5102 ********************************************************************/
5104 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5106 NT_PRINTER_INFO_LEVEL *printer = NULL;
5107 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5109 ZERO_STRUCT(driver);
5111 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5112 return WERR_INVALID_PRINTER_NAME;
5114 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5115 free_a_printer(&printer, 2);
5116 return WERR_UNKNOWN_PRINTER_DRIVER;
5119 fill_printer_driver_info_1(info, driver, servername, architecture);
5121 free_a_printer(&printer,2);
5126 /********************************************************************
5127 * construct_printer_driver_info_2
5128 * fill a printer_info_2 struct
5129 ********************************************************************/
5131 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5133 TALLOC_CTX *ctx = talloc_tos();
5136 info->version=driver.info_3->cversion;
5138 init_unistr( &info->name, driver.info_3->name );
5139 init_unistr( &info->architecture, driver.info_3->environment );
5142 if (strlen(driver.info_3->driverpath)) {
5143 temp = talloc_asprintf(ctx,
5146 driver.info_3->driverpath);
5147 init_unistr( &info->driverpath, temp );
5149 init_unistr( &info->driverpath, "" );
5153 if (strlen(driver.info_3->datafile)) {
5154 temp = talloc_asprintf(ctx,
5157 driver.info_3->datafile);
5158 init_unistr( &info->datafile, temp );
5160 init_unistr( &info->datafile, "" );
5163 if (strlen(driver.info_3->configfile)) {
5164 temp = talloc_asprintf(ctx,
5167 driver.info_3->configfile);
5168 init_unistr( &info->configfile, temp );
5170 init_unistr( &info->configfile, "" );
5173 /********************************************************************
5174 * construct_printer_driver_info_2
5175 * fill a printer_info_2 struct
5176 ********************************************************************/
5178 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5180 NT_PRINTER_INFO_LEVEL *printer = NULL;
5181 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5183 ZERO_STRUCT(printer);
5184 ZERO_STRUCT(driver);
5186 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5187 return WERR_INVALID_PRINTER_NAME;
5189 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5190 free_a_printer(&printer, 2);
5191 return WERR_UNKNOWN_PRINTER_DRIVER;
5194 fill_printer_driver_info_2(info, driver, servername);
5196 free_a_printer(&printer,2);
5201 /********************************************************************
5202 * copy a strings array and convert to UNICODE
5204 * convert an array of ascii string to a UNICODE string
5205 ********************************************************************/
5207 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5213 TALLOC_CTX *ctx = talloc_tos();
5215 DEBUG(6,("init_unistr_array\n"));
5219 if ( !char_array ) {
5224 v = ""; /* hack to handle null lists */
5227 /* hack to allow this to be used in places other than when generating
5228 the list of dependent files */
5232 line = talloc_asprintf(ctx,
5237 line = talloc_strdup(ctx, v);
5241 SAFE_FREE(*uni_array);
5244 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5246 /* add one extra unit16 for the second terminating NULL */
5248 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5249 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5256 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5261 /* special case for ""; we need to add both NULL's here */
5263 (*uni_array)[j++]=0x0000;
5264 (*uni_array)[j]=0x0000;
5267 DEBUGADD(6,("last one:done\n"));
5269 /* return size of array in uint16's */
5274 /********************************************************************
5275 * construct_printer_info_3
5276 * fill a printer_info_3 struct
5277 ********************************************************************/
5279 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5282 TALLOC_CTX *ctx = talloc_tos();
5286 info->version=driver.info_3->cversion;
5288 init_unistr( &info->name, driver.info_3->name );
5289 init_unistr( &info->architecture, driver.info_3->environment );
5291 if (strlen(driver.info_3->driverpath)) {
5292 temp = talloc_asprintf(ctx,
5295 driver.info_3->driverpath);
5296 init_unistr( &info->driverpath, temp );
5298 init_unistr( &info->driverpath, "" );
5301 if (strlen(driver.info_3->datafile)) {
5302 temp = talloc_asprintf(ctx,
5305 driver.info_3->datafile);
5306 init_unistr( &info->datafile, temp );
5308 init_unistr( &info->datafile, "" );
5311 if (strlen(driver.info_3->configfile)) {
5312 temp = talloc_asprintf(ctx,
5315 driver.info_3->configfile);
5316 init_unistr( &info->configfile, temp );
5318 init_unistr( &info->configfile, "" );
5321 if (strlen(driver.info_3->helpfile)) {
5322 temp = talloc_asprintf(ctx,
5325 driver.info_3->helpfile);
5326 init_unistr( &info->helpfile, temp );
5328 init_unistr( &info->helpfile, "" );
5331 init_unistr( &info->monitorname, driver.info_3->monitorname );
5332 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5334 info->dependentfiles=NULL;
5335 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5338 /********************************************************************
5339 * construct_printer_info_3
5340 * fill a printer_info_3 struct
5341 ********************************************************************/
5343 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5345 NT_PRINTER_INFO_LEVEL *printer = NULL;
5346 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5348 ZERO_STRUCT(driver);
5350 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5351 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5352 if (!W_ERROR_IS_OK(status))
5353 return WERR_INVALID_PRINTER_NAME;
5355 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5356 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5361 * I put this code in during testing. Helpful when commenting out the
5362 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5363 * as win2k always queries the driver using an infor level of 6.
5364 * I've left it in (but ifdef'd out) because I'll probably
5365 * use it in experimentation again in the future. --jerry 22/01/2002
5368 if (!W_ERROR_IS_OK(status)) {
5370 * Is this a W2k client ?
5373 /* Yes - try again with a WinNT driver. */
5375 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5376 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5380 if (!W_ERROR_IS_OK(status)) {
5381 free_a_printer(&printer,2);
5382 return WERR_UNKNOWN_PRINTER_DRIVER;
5390 fill_printer_driver_info_3(info, driver, servername);
5392 free_a_printer(&printer,2);
5397 /********************************************************************
5398 * construct_printer_info_6
5399 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5400 ********************************************************************/
5402 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5406 TALLOC_CTX *ctx = talloc_tos();
5409 memset(&nullstr, '\0', sizeof(fstring));
5411 info->version=driver.info_3->cversion;
5413 init_unistr( &info->name, driver.info_3->name );
5414 init_unistr( &info->architecture, driver.info_3->environment );
5416 if (strlen(driver.info_3->driverpath)) {
5417 temp = talloc_asprintf(ctx,
5420 driver.info_3->driverpath);
5421 init_unistr( &info->driverpath, temp );
5423 init_unistr( &info->driverpath, "" );
5426 if (strlen(driver.info_3->datafile)) {
5427 temp = talloc_asprintf(ctx,
5430 driver.info_3->datafile);
5431 init_unistr( &info->datafile, temp );
5433 init_unistr( &info->datafile, "" );
5436 if (strlen(driver.info_3->configfile)) {
5437 temp = talloc_asprintf(ctx,
5440 driver.info_3->configfile);
5441 init_unistr( &info->configfile, temp );
5443 init_unistr( &info->configfile, "" );
5446 if (strlen(driver.info_3->helpfile)) {
5447 temp = talloc_asprintf(ctx,
5450 driver.info_3->helpfile);
5451 init_unistr( &info->helpfile, temp );
5453 init_unistr( &info->helpfile, "" );
5456 init_unistr( &info->monitorname, driver.info_3->monitorname );
5457 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5459 info->dependentfiles = NULL;
5460 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5462 info->previousdrivernames=NULL;
5463 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5465 info->driver_date=0;
5468 info->driver_version_low=0;
5469 info->driver_version_high=0;
5471 init_unistr( &info->mfgname, "");
5472 init_unistr( &info->oem_url, "");
5473 init_unistr( &info->hardware_id, "");
5474 init_unistr( &info->provider, "");
5477 /********************************************************************
5478 * construct_printer_info_6
5479 * fill a printer_info_6 struct
5480 ********************************************************************/
5482 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5483 fstring servername, fstring architecture, uint32 version)
5485 NT_PRINTER_INFO_LEVEL *printer = NULL;
5486 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5489 ZERO_STRUCT(driver);
5491 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5493 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5495 if (!W_ERROR_IS_OK(status))
5496 return WERR_INVALID_PRINTER_NAME;
5498 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5500 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5502 if (!W_ERROR_IS_OK(status))
5505 * Is this a W2k client ?
5509 free_a_printer(&printer,2);
5510 return WERR_UNKNOWN_PRINTER_DRIVER;
5513 /* Yes - try again with a WinNT driver. */
5515 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5516 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5517 if (!W_ERROR_IS_OK(status)) {
5518 free_a_printer(&printer,2);
5519 return WERR_UNKNOWN_PRINTER_DRIVER;
5523 fill_printer_driver_info_6(info, driver, servername);
5525 free_a_printer(&printer,2);
5526 free_a_printer_driver(driver, 3);
5531 /****************************************************************************
5532 ****************************************************************************/
5534 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5536 SAFE_FREE(info->dependentfiles);
5539 /****************************************************************************
5540 ****************************************************************************/
5542 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5544 SAFE_FREE(info->dependentfiles);
5547 /****************************************************************************
5548 ****************************************************************************/
5550 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5552 DRIVER_INFO_1 *info=NULL;
5555 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5558 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5559 if (!W_ERROR_IS_OK(result))
5562 /* check the required size. */
5563 *needed += spoolss_size_printer_driver_info_1(info);
5565 if (*needed > offered) {
5566 result = WERR_INSUFFICIENT_BUFFER;
5570 if (!rpcbuf_alloc_size(buffer, *needed)) {
5571 result = WERR_NOMEM;
5575 /* fill the buffer with the structures */
5576 smb_io_printer_driver_info_1("", buffer, info, 0);
5585 /****************************************************************************
5586 ****************************************************************************/
5588 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5590 DRIVER_INFO_2 *info=NULL;
5593 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5596 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5597 if (!W_ERROR_IS_OK(result))
5600 /* check the required size. */
5601 *needed += spoolss_size_printer_driver_info_2(info);
5603 if (*needed > offered) {
5604 result = WERR_INSUFFICIENT_BUFFER;
5608 if (!rpcbuf_alloc_size(buffer, *needed)) {
5609 result = WERR_NOMEM;
5613 /* fill the buffer with the structures */
5614 smb_io_printer_driver_info_2("", buffer, info, 0);
5623 /****************************************************************************
5624 ****************************************************************************/
5626 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5633 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5634 if (!W_ERROR_IS_OK(result))
5637 /* check the required size. */
5638 *needed += spoolss_size_printer_driver_info_3(&info);
5640 if (*needed > offered) {
5641 result = WERR_INSUFFICIENT_BUFFER;
5645 if (!rpcbuf_alloc_size(buffer, *needed)) {
5646 result = WERR_NOMEM;
5650 /* fill the buffer with the structures */
5651 smb_io_printer_driver_info_3("", buffer, &info, 0);
5654 free_printer_driver_info_3(&info);
5659 /****************************************************************************
5660 ****************************************************************************/
5662 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5669 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5670 if (!W_ERROR_IS_OK(result))
5673 /* check the required size. */
5674 *needed += spoolss_size_printer_driver_info_6(&info);
5676 if (*needed > offered) {
5677 result = WERR_INSUFFICIENT_BUFFER;
5681 if (!rpcbuf_alloc_size(buffer, *needed)) {
5682 result = WERR_NOMEM;
5686 /* fill the buffer with the structures */
5687 smb_io_printer_driver_info_6("", buffer, &info, 0);
5690 free_printer_driver_info_6(&info);
5695 /****************************************************************************
5696 ****************************************************************************/
5698 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5700 POLICY_HND *handle = &q_u->handle;
5701 UNISTR2 *uni_arch = &q_u->architecture;
5702 uint32 level = q_u->level;
5703 uint32 clientmajorversion = q_u->clientmajorversion;
5704 RPC_BUFFER *buffer = NULL;
5705 uint32 offered = q_u->offered;
5706 uint32 *needed = &r_u->needed;
5707 uint32 *servermajorversion = &r_u->servermajorversion;
5708 uint32 *serverminorversion = &r_u->serverminorversion;
5709 Printer_entry *printer;
5712 fstring architecture;
5715 /* that's an [in out] buffer */
5717 if (!q_u->buffer && (offered!=0)) {
5718 return WERR_INVALID_PARAM;
5721 rpcbuf_move(q_u->buffer, &r_u->buffer);
5722 buffer = r_u->buffer;
5724 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5726 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5727 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5728 return WERR_INVALID_PRINTER_NAME;
5732 *servermajorversion = 0;
5733 *serverminorversion = 0;
5735 fstrcpy(servername, get_server_name( printer ));
5736 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5738 if (!get_printer_snum(p, handle, &snum, NULL))
5743 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5745 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5747 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5749 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5752 /* apparently this call is the equivalent of
5753 EnumPrinterDataEx() for the DsDriver key */
5758 return WERR_UNKNOWN_LEVEL;
5761 /****************************************************************************
5762 ****************************************************************************/
5764 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5766 POLICY_HND *handle = &q_u->handle;
5768 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5771 DEBUG(3,("Error in startpageprinter printer handle\n"));
5775 Printer->page_started=True;
5779 /****************************************************************************
5780 ****************************************************************************/
5782 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5784 POLICY_HND *handle = &q_u->handle;
5787 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5790 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5794 if (!get_printer_snum(p, handle, &snum, NULL))
5797 Printer->page_started=False;
5798 print_job_endpage(snum, Printer->jobid);
5803 /********************************************************************
5804 * api_spoolss_getprinter
5805 * called from the spoolss dispatcher
5807 ********************************************************************/
5809 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5811 POLICY_HND *handle = &q_u->handle;
5812 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5813 uint32 *jobid = &r_u->jobid;
5814 TALLOC_CTX *ctx = p->mem_ctx;
5815 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5817 char *jobname = NULL;
5819 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5822 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5827 * a nice thing with NT is it doesn't listen to what you tell it.
5828 * when asked to send _only_ RAW datas, it tries to send datas
5831 * So I add checks like in NT Server ...
5834 if (info_1->p_datatype != 0) {
5835 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5836 if (strcmp(datatype, "RAW") != 0) {
5838 return WERR_INVALID_DATATYPE;
5842 /* get the share number of the printer */
5843 if (!get_printer_snum(p, handle, &snum, NULL)) {
5847 jobname = unistr2_to_ascii_talloc(ctx, &info_1->docname);
5849 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5851 /* An error occured in print_job_start() so return an appropriate
5854 if (Printer->jobid == -1) {
5855 return map_werror_from_unix(errno);
5858 Printer->document_started=True;
5859 (*jobid) = Printer->jobid;
5864 /********************************************************************
5865 * api_spoolss_getprinter
5866 * called from the spoolss dispatcher
5868 ********************************************************************/
5870 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5872 POLICY_HND *handle = &q_u->handle;
5874 return _spoolss_enddocprinter_internal(p, handle);
5877 /****************************************************************************
5878 ****************************************************************************/
5880 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5882 POLICY_HND *handle = &q_u->handle;
5883 uint32 buffer_size = q_u->buffer_size;
5884 uint8 *buffer = q_u->buffer;
5885 uint32 *buffer_written = &q_u->buffer_size2;
5887 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5890 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5891 r_u->buffer_written = q_u->buffer_size2;
5895 if (!get_printer_snum(p, handle, &snum, NULL))
5898 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5899 (SMB_OFF_T)-1, (size_t)buffer_size);
5900 if (*buffer_written == (uint32)-1) {
5901 r_u->buffer_written = 0;
5902 if (errno == ENOSPC)
5903 return WERR_NO_SPOOL_SPACE;
5905 return WERR_ACCESS_DENIED;
5908 r_u->buffer_written = q_u->buffer_size2;
5913 /********************************************************************
5914 * api_spoolss_getprinter
5915 * called from the spoolss dispatcher
5917 ********************************************************************/
5919 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5923 WERROR errcode = WERR_BADFUNC;
5924 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5927 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5931 if (!get_printer_snum(p, handle, &snum, NULL))
5935 case PRINTER_CONTROL_PAUSE:
5936 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5940 case PRINTER_CONTROL_RESUME:
5941 case PRINTER_CONTROL_UNPAUSE:
5942 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5946 case PRINTER_CONTROL_PURGE:
5947 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5952 return WERR_UNKNOWN_LEVEL;
5958 /********************************************************************
5959 * api_spoolss_abortprinter
5960 * From MSDN: "Deletes printer's spool file if printer is configured
5962 ********************************************************************/
5964 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5966 POLICY_HND *handle = &q_u->handle;
5967 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5969 WERROR errcode = WERR_OK;
5972 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5976 if (!get_printer_snum(p, handle, &snum, NULL))
5979 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5984 /********************************************************************
5985 * called by spoolss_api_setprinter
5986 * when updating a printer description
5987 ********************************************************************/
5989 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5990 const SPOOL_PRINTER_INFO_LEVEL *info,
5991 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5993 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5997 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5999 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6000 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6001 OUR_HANDLE(handle)));
6003 result = WERR_BADFID;
6008 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6009 result = WERR_INVALID_PARAM;
6013 /* Check the user has permissions to change the security
6014 descriptor. By experimentation with two NT machines, the user
6015 requires Full Access to the printer to change security
6018 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6019 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6020 result = WERR_ACCESS_DENIED;
6024 /* NT seems to like setting the security descriptor even though
6025 nothing may have actually changed. */
6027 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6029 if (DEBUGLEVEL >= 10) {
6033 the_acl = old_secdesc_ctr->sd->dacl;
6034 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6035 PRINTERNAME(snum), the_acl->num_aces));
6037 for (i = 0; i < the_acl->num_aces; i++) {
6040 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6042 DEBUG(10, ("%s 0x%08x\n", sid_str,
6043 the_acl->aces[i].access_mask));
6046 the_acl = secdesc_ctr->sd->dacl;
6049 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6050 PRINTERNAME(snum), the_acl->num_aces));
6052 for (i = 0; i < the_acl->num_aces; i++) {
6055 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6057 DEBUG(10, ("%s 0x%08x\n", sid_str,
6058 the_acl->aces[i].access_mask));
6061 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6065 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6066 if (!new_secdesc_ctr) {
6067 result = WERR_NOMEM;
6071 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6076 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6083 /********************************************************************
6084 Canonicalize printer info from a client
6086 ATTN: It does not matter what we set the servername to hear
6087 since we do the necessary work in get_a_printer() to set it to
6088 the correct value based on what the client sent in the
6089 _spoolss_open_printer_ex().
6090 ********************************************************************/
6092 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6094 fstring printername;
6097 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6098 "portname=%s drivername=%s comment=%s location=%s\n",
6099 info->servername, info->printername, info->sharename,
6100 info->portname, info->drivername, info->comment, info->location));
6102 /* we force some elements to "correct" values */
6103 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6104 fstrcpy(info->sharename, lp_servicename(snum));
6106 /* check to see if we allow printername != sharename */
6108 if ( lp_force_printername(snum) ) {
6109 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6110 global_myname(), info->sharename );
6113 /* make sure printername is in \\server\printername format */
6115 fstrcpy( printername, info->printername );
6117 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6118 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6122 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6123 global_myname(), p );
6126 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6127 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6134 /****************************************************************************
6135 ****************************************************************************/
6137 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6139 char *cmd = lp_addport_cmd();
6140 char *command = NULL;
6143 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6144 bool is_print_op = False;
6147 return WERR_ACCESS_DENIED;
6150 command = talloc_asprintf(ctx,
6151 "%s \"%s\" \"%s\"", cmd, portname, uri );
6157 is_print_op = user_has_privileges( token, &se_printop );
6159 DEBUG(10,("Running [%s]\n", command));
6161 /********* BEGIN SePrintOperatorPrivilege **********/
6166 ret = smbrun(command, &fd);
6171 /********* END SePrintOperatorPrivilege **********/
6173 DEBUGADD(10,("returned [%d]\n", ret));
6175 TALLOC_FREE(command);
6180 return WERR_ACCESS_DENIED;
6186 /****************************************************************************
6187 ****************************************************************************/
6189 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6191 char *cmd = lp_addprinter_cmd();
6193 char *command = NULL;
6197 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6198 bool is_print_op = False;
6199 char *remote_machine = talloc_strdup(ctx, "%m");
6201 if (!remote_machine) {
6204 remote_machine = talloc_sub_basic(ctx,
6205 current_user_info.smb_name,
6206 current_user_info.domain,
6208 if (!remote_machine) {
6212 command = talloc_asprintf(ctx,
6213 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6214 cmd, printer->info_2->printername, printer->info_2->sharename,
6215 printer->info_2->portname, printer->info_2->drivername,
6216 printer->info_2->location, printer->info_2->comment, remote_machine);
6222 is_print_op = user_has_privileges( token, &se_printop );
6224 DEBUG(10,("Running [%s]\n", command));
6226 /********* BEGIN SePrintOperatorPrivilege **********/
6231 if ( (ret = smbrun(command, &fd)) == 0 ) {
6232 /* Tell everyone we updated smb.conf. */
6233 message_send_all(smbd_messaging_context(),
6234 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6240 /********* END SePrintOperatorPrivilege **********/
6242 DEBUGADD(10,("returned [%d]\n", ret));
6244 TALLOC_FREE(command);
6245 TALLOC_FREE(remote_machine);
6253 /* reload our services immediately */
6254 reload_services( False );
6257 /* Get lines and convert them back to dos-codepage */
6258 qlines = fd_lines_load(fd, &numlines, 0);
6259 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6262 /* Set the portname to what the script says the portname should be. */
6263 /* but don't require anything to be return from the script exit a good error code */
6266 /* Set the portname to what the script says the portname should be. */
6267 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6268 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6271 file_lines_free(qlines);
6276 /********************************************************************
6277 * Called by spoolss_api_setprinter
6278 * when updating a printer description.
6279 ********************************************************************/
6281 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6282 const SPOOL_PRINTER_INFO_LEVEL *info,
6283 DEVICEMODE *devmode)
6286 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6287 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6292 DEBUG(8,("update_printer\n"));
6297 result = WERR_BADFID;
6301 if (!get_printer_snum(p, handle, &snum, NULL)) {
6302 result = WERR_BADFID;
6306 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6307 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6308 result = WERR_BADFID;
6312 DEBUGADD(8,("Converting info_2 struct\n"));
6315 * convert_printer_info converts the incoming
6316 * info from the client and overwrites the info
6317 * just read from the tdb in the pointer 'printer'.
6320 if (!convert_printer_info(info, printer, level)) {
6321 result = WERR_NOMEM;
6326 /* we have a valid devmode
6327 convert it and link it*/
6329 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6330 if (!convert_devicemode(printer->info_2->printername, devmode,
6331 &printer->info_2->devmode)) {
6332 result = WERR_NOMEM;
6337 /* Do sanity check on the requested changes for Samba */
6339 if (!check_printer_ok(printer->info_2, snum)) {
6340 result = WERR_INVALID_PARAM;
6344 /* FIXME!!! If the driver has changed we really should verify that
6345 it is installed before doing much else --jerry */
6347 /* Check calling user has permission to update printer description */
6349 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6350 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6351 result = WERR_ACCESS_DENIED;
6355 /* Call addprinter hook */
6356 /* Check changes to see if this is really needed */
6358 if ( *lp_addprinter_cmd()
6359 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6360 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6361 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6362 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6364 /* add_printer_hook() will call reload_services() */
6366 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
6367 result = WERR_ACCESS_DENIED;
6373 * When a *new* driver is bound to a printer, the drivername is used to
6374 * lookup previously saved driver initialization info, which is then
6375 * bound to the printer, simulating what happens in the Windows arch.
6377 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6379 if (!set_driver_init(printer, 2))
6381 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6382 printer->info_2->drivername));
6385 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6386 printer->info_2->drivername));
6388 notify_printer_driver(snum, printer->info_2->drivername);
6392 * flag which changes actually occured. This is a small subset of
6393 * all the possible changes. We also have to update things in the
6397 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6398 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6399 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6400 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6402 notify_printer_comment(snum, printer->info_2->comment);
6405 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6406 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6407 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6408 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6410 notify_printer_sharename(snum, printer->info_2->sharename);
6413 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6416 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6419 pname = printer->info_2->printername;
6422 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6423 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6424 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6426 notify_printer_printername( snum, pname );
6429 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6430 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6431 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6432 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6434 notify_printer_port(snum, printer->info_2->portname);
6437 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6438 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6439 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6440 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6442 notify_printer_location(snum, printer->info_2->location);
6445 /* here we need to update some more DsSpooler keys */
6446 /* uNCName, serverName, shortServerName */
6448 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6449 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6450 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6451 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6452 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6454 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6455 global_myname(), printer->info_2->sharename );
6456 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6457 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6458 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6460 /* Update printer info */
6461 result = mod_a_printer(printer, 2);
6464 free_a_printer(&printer, 2);
6465 free_a_printer(&old_printer, 2);
6471 /****************************************************************************
6472 ****************************************************************************/
6473 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6474 const SPOOL_PRINTER_INFO_LEVEL *info)
6477 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6479 Printer_entry *Printer;
6481 if ( lp_security() != SEC_ADS ) {
6482 return WERR_UNKNOWN_LEVEL;
6485 Printer = find_printer_index_by_hnd(p, handle);
6487 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6492 if (!get_printer_snum(p, handle, &snum, NULL))
6495 nt_printer_publish(Printer, snum, info7->action);
6499 return WERR_UNKNOWN_LEVEL;
6502 /****************************************************************************
6503 ****************************************************************************/
6505 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6507 POLICY_HND *handle = &q_u->handle;
6508 uint32 level = q_u->level;
6509 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6510 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6511 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6512 uint32 command = q_u->command;
6515 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6518 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6522 /* check the level */
6525 return control_printer(handle, command, p);
6527 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6528 if (!W_ERROR_IS_OK(result))
6531 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6534 return update_printer_sec(handle, level, info, p,
6537 return publish_or_unpublish_printer(p, handle, info);
6539 return WERR_UNKNOWN_LEVEL;
6543 /****************************************************************************
6544 ****************************************************************************/
6546 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6548 POLICY_HND *handle = &q_u->handle;
6549 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6552 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6556 if (Printer->notify.client_connected==True) {
6559 if ( Printer->printer_type == SPLHND_SERVER)
6561 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6562 !get_printer_snum(p, handle, &snum, NULL) )
6565 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6568 Printer->notify.flags=0;
6569 Printer->notify.options=0;
6570 Printer->notify.localmachine[0]='\0';
6571 Printer->notify.printerlocal=0;
6572 if (Printer->notify.option)
6573 free_spool_notify_option(&Printer->notify.option);
6574 Printer->notify.client_connected=False;
6579 /****************************************************************************
6580 ****************************************************************************/
6582 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6584 /* that's an [in out] buffer */
6586 if (!q_u->buffer && (q_u->offered!=0)) {
6587 return WERR_INVALID_PARAM;
6590 rpcbuf_move(q_u->buffer, &r_u->buffer);
6593 return WERR_INVALID_PARAM; /* this is what a NT server
6594 returns for AddJob. AddJob
6595 must fail on non-local
6599 /****************************************************************************
6600 ****************************************************************************/
6602 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6603 int position, int snum,
6604 const NT_PRINTER_INFO_LEVEL *ntprinter)
6608 t=gmtime(&queue->time);
6610 job_info->jobid=queue->job;
6611 init_unistr(&job_info->printername, lp_servicename(snum));
6612 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6613 init_unistr(&job_info->username, queue->fs_user);
6614 init_unistr(&job_info->document, queue->fs_file);
6615 init_unistr(&job_info->datatype, "RAW");
6616 init_unistr(&job_info->text_status, "");
6617 job_info->status=nt_printj_status(queue->status);
6618 job_info->priority=queue->priority;
6619 job_info->position=position;
6620 job_info->totalpages=queue->page_count;
6621 job_info->pagesprinted=0;
6623 make_systemtime(&job_info->submitted, t);
6626 /****************************************************************************
6627 ****************************************************************************/
6629 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6630 int position, int snum,
6631 const NT_PRINTER_INFO_LEVEL *ntprinter,
6632 DEVICEMODE *devmode)
6636 t=gmtime(&queue->time);
6638 job_info->jobid=queue->job;
6640 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6642 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6643 init_unistr(&job_info->username, queue->fs_user);
6644 init_unistr(&job_info->document, queue->fs_file);
6645 init_unistr(&job_info->notifyname, queue->fs_user);
6646 init_unistr(&job_info->datatype, "RAW");
6647 init_unistr(&job_info->printprocessor, "winprint");
6648 init_unistr(&job_info->parameters, "");
6649 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6650 init_unistr(&job_info->text_status, "");
6652 /* and here the security descriptor */
6654 job_info->status=nt_printj_status(queue->status);
6655 job_info->priority=queue->priority;
6656 job_info->position=position;
6657 job_info->starttime=0;
6658 job_info->untiltime=0;
6659 job_info->totalpages=queue->page_count;
6660 job_info->size=queue->size;
6661 make_systemtime(&(job_info->submitted), t);
6662 job_info->timeelapsed=0;
6663 job_info->pagesprinted=0;
6665 job_info->devmode = devmode;
6670 /****************************************************************************
6671 Enumjobs at level 1.
6672 ****************************************************************************/
6674 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6675 const NT_PRINTER_INFO_LEVEL *ntprinter,
6676 RPC_BUFFER *buffer, uint32 offered,
6677 uint32 *needed, uint32 *returned)
6681 WERROR result = WERR_OK;
6683 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6689 for (i=0; i<*returned; i++)
6690 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6692 /* check the required size. */
6693 for (i=0; i<*returned; i++)
6694 (*needed) += spoolss_size_job_info_1(&info[i]);
6696 if (*needed > offered) {
6697 result = WERR_INSUFFICIENT_BUFFER;
6701 if (!rpcbuf_alloc_size(buffer, *needed)) {
6702 result = WERR_NOMEM;
6706 /* fill the buffer with the structures */
6707 for (i=0; i<*returned; i++)
6708 smb_io_job_info_1("", buffer, &info[i], 0);
6714 if ( !W_ERROR_IS_OK(result) )
6720 /****************************************************************************
6721 Enumjobs at level 2.
6722 ****************************************************************************/
6724 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6725 const NT_PRINTER_INFO_LEVEL *ntprinter,
6726 RPC_BUFFER *buffer, uint32 offered,
6727 uint32 *needed, uint32 *returned)
6729 JOB_INFO_2 *info = NULL;
6731 WERROR result = WERR_OK;
6732 DEVICEMODE *devmode = NULL;
6734 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6739 /* this should not be a failure condition if the devmode is NULL */
6741 devmode = construct_dev_mode(lp_const_servicename(snum));
6743 for (i=0; i<*returned; i++)
6744 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6746 /* check the required size. */
6747 for (i=0; i<*returned; i++)
6748 (*needed) += spoolss_size_job_info_2(&info[i]);
6750 if (*needed > offered) {
6751 result = WERR_INSUFFICIENT_BUFFER;
6755 if (!rpcbuf_alloc_size(buffer, *needed)) {
6756 result = WERR_NOMEM;
6760 /* fill the buffer with the structures */
6761 for (i=0; i<*returned; i++)
6762 smb_io_job_info_2("", buffer, &info[i], 0);
6765 free_devmode(devmode);
6768 if ( !W_ERROR_IS_OK(result) )
6775 /****************************************************************************
6777 ****************************************************************************/
6779 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6781 POLICY_HND *handle = &q_u->handle;
6782 uint32 level = q_u->level;
6783 RPC_BUFFER *buffer = NULL;
6784 uint32 offered = q_u->offered;
6785 uint32 *needed = &r_u->needed;
6786 uint32 *returned = &r_u->returned;
6788 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6790 print_status_struct prt_status;
6791 print_queue_struct *queue=NULL;
6793 /* that's an [in out] buffer */
6795 if (!q_u->buffer && (offered!=0)) {
6796 return WERR_INVALID_PARAM;
6799 rpcbuf_move(q_u->buffer, &r_u->buffer);
6800 buffer = r_u->buffer;
6802 DEBUG(4,("_spoolss_enumjobs\n"));
6807 /* lookup the printer snum and tdb entry */
6809 if (!get_printer_snum(p, handle, &snum, NULL))
6812 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6813 if ( !W_ERROR_IS_OK(wret) )
6816 *returned = print_queue_status(snum, &queue, &prt_status);
6817 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6819 if (*returned == 0) {
6821 free_a_printer(&ntprinter, 2);
6827 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6830 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6834 wret = WERR_UNKNOWN_LEVEL;
6839 free_a_printer( &ntprinter, 2 );
6843 /****************************************************************************
6844 ****************************************************************************/
6846 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6851 /****************************************************************************
6852 ****************************************************************************/
6854 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6856 POLICY_HND *handle = &q_u->handle;
6857 uint32 jobid = q_u->jobid;
6858 uint32 command = q_u->command;
6861 WERROR errcode = WERR_BADFUNC;
6863 if (!get_printer_snum(p, handle, &snum, NULL)) {
6867 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6868 return WERR_INVALID_PRINTER_NAME;
6872 case JOB_CONTROL_CANCEL:
6873 case JOB_CONTROL_DELETE:
6874 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6878 case JOB_CONTROL_PAUSE:
6879 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6883 case JOB_CONTROL_RESTART:
6884 case JOB_CONTROL_RESUME:
6885 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6890 return WERR_UNKNOWN_LEVEL;
6896 /****************************************************************************
6897 Enumerates all printer drivers at level 1.
6898 ****************************************************************************/
6900 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6905 fstring *list = NULL;
6906 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6907 DRIVER_INFO_1 *driver_info_1=NULL;
6908 WERROR result = WERR_OK;
6912 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6914 ndrivers=get_ntdrivers(&list, architecture, version);
6915 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6917 if(ndrivers == -1) {
6918 SAFE_FREE(driver_info_1);
6923 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6924 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6930 for (i=0; i<ndrivers; i++) {
6932 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6933 ZERO_STRUCT(driver);
6934 status = get_a_printer_driver(&driver, 3, list[i],
6935 architecture, version);
6936 if (!W_ERROR_IS_OK(status)) {
6938 SAFE_FREE(driver_info_1);
6941 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6942 free_a_printer_driver(driver, 3);
6945 *returned+=ndrivers;
6949 /* check the required size. */
6950 for (i=0; i<*returned; i++) {
6951 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6952 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6955 if (*needed > offered) {
6956 result = WERR_INSUFFICIENT_BUFFER;
6960 if (!rpcbuf_alloc_size(buffer, *needed)) {
6961 result = WERR_NOMEM;
6965 /* fill the buffer with the driver structures */
6966 for (i=0; i<*returned; i++) {
6967 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6968 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6972 SAFE_FREE(driver_info_1);
6974 if ( !W_ERROR_IS_OK(result) )
6980 /****************************************************************************
6981 Enumerates all printer drivers at level 2.
6982 ****************************************************************************/
6984 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6989 fstring *list = NULL;
6990 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6991 DRIVER_INFO_2 *driver_info_2=NULL;
6992 WERROR result = WERR_OK;
6996 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6998 ndrivers=get_ntdrivers(&list, architecture, version);
6999 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7001 if(ndrivers == -1) {
7002 SAFE_FREE(driver_info_2);
7007 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7008 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7014 for (i=0; i<ndrivers; i++) {
7017 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7018 ZERO_STRUCT(driver);
7019 status = get_a_printer_driver(&driver, 3, list[i],
7020 architecture, version);
7021 if (!W_ERROR_IS_OK(status)) {
7023 SAFE_FREE(driver_info_2);
7026 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7027 free_a_printer_driver(driver, 3);
7030 *returned+=ndrivers;
7034 /* check the required size. */
7035 for (i=0; i<*returned; i++) {
7036 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7037 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7040 if (*needed > offered) {
7041 result = WERR_INSUFFICIENT_BUFFER;
7045 if (!rpcbuf_alloc_size(buffer, *needed)) {
7046 result = WERR_NOMEM;
7050 /* fill the buffer with the form structures */
7051 for (i=0; i<*returned; i++) {
7052 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7053 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7057 SAFE_FREE(driver_info_2);
7059 if ( !W_ERROR_IS_OK(result) )
7065 /****************************************************************************
7066 Enumerates all printer drivers at level 3.
7067 ****************************************************************************/
7069 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7074 fstring *list = NULL;
7075 DRIVER_INFO_3 *driver_info_3=NULL;
7076 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7077 WERROR result = WERR_OK;
7081 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7083 ndrivers=get_ntdrivers(&list, architecture, version);
7084 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7086 if(ndrivers == -1) {
7087 SAFE_FREE(driver_info_3);
7092 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7093 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7099 for (i=0; i<ndrivers; i++) {
7102 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7103 ZERO_STRUCT(driver);
7104 status = get_a_printer_driver(&driver, 3, list[i],
7105 architecture, version);
7106 if (!W_ERROR_IS_OK(status)) {
7108 SAFE_FREE(driver_info_3);
7111 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7112 free_a_printer_driver(driver, 3);
7115 *returned+=ndrivers;
7119 /* check the required size. */
7120 for (i=0; i<*returned; i++) {
7121 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7122 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7125 if (*needed > offered) {
7126 result = WERR_INSUFFICIENT_BUFFER;
7130 if (!rpcbuf_alloc_size(buffer, *needed)) {
7131 result = WERR_NOMEM;
7135 /* fill the buffer with the driver structures */
7136 for (i=0; i<*returned; i++) {
7137 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7138 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7142 for (i=0; i<*returned; i++) {
7143 SAFE_FREE(driver_info_3[i].dependentfiles);
7146 SAFE_FREE(driver_info_3);
7148 if ( !W_ERROR_IS_OK(result) )
7154 /****************************************************************************
7155 Enumerates all printer drivers.
7156 ****************************************************************************/
7158 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7160 uint32 level = q_u->level;
7161 RPC_BUFFER *buffer = NULL;
7162 uint32 offered = q_u->offered;
7163 uint32 *needed = &r_u->needed;
7164 uint32 *returned = &r_u->returned;
7167 fstring architecture;
7169 /* that's an [in out] buffer */
7171 if (!q_u->buffer && (offered!=0)) {
7172 return WERR_INVALID_PARAM;
7175 rpcbuf_move(q_u->buffer, &r_u->buffer);
7176 buffer = r_u->buffer;
7178 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7183 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7184 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7186 if ( !is_myname_or_ipaddr( servername ) )
7187 return WERR_UNKNOWN_PRINTER_DRIVER;
7191 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7193 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7195 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7197 return WERR_UNKNOWN_LEVEL;
7201 /****************************************************************************
7202 ****************************************************************************/
7204 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7206 form->flag=list->flag;
7207 init_unistr(&form->name, list->name);
7208 form->width=list->width;
7209 form->length=list->length;
7210 form->left=list->left;
7211 form->top=list->top;
7212 form->right=list->right;
7213 form->bottom=list->bottom;
7216 /****************************************************************************
7217 ****************************************************************************/
7219 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7221 uint32 level = q_u->level;
7222 RPC_BUFFER *buffer = NULL;
7223 uint32 offered = q_u->offered;
7224 uint32 *needed = &r_u->needed;
7225 uint32 *numofforms = &r_u->numofforms;
7226 uint32 numbuiltinforms;
7228 nt_forms_struct *list=NULL;
7229 nt_forms_struct *builtinlist=NULL;
7234 /* that's an [in out] buffer */
7236 if (!q_u->buffer && (offered!=0) ) {
7237 return WERR_INVALID_PARAM;
7240 rpcbuf_move(q_u->buffer, &r_u->buffer);
7241 buffer = r_u->buffer;
7243 DEBUG(4,("_spoolss_enumforms\n"));
7244 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7245 DEBUGADD(5,("Info level [%d]\n", level));
7247 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7248 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7249 *numofforms = get_ntforms(&list);
7250 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7251 *numofforms += numbuiltinforms;
7253 if (*numofforms == 0) {
7254 SAFE_FREE(builtinlist);
7256 return WERR_NO_MORE_ITEMS;
7261 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7262 SAFE_FREE(builtinlist);
7268 /* construct the list of form structures */
7269 for (i=0; i<numbuiltinforms; i++) {
7270 DEBUGADD(6,("Filling form number [%d]\n",i));
7271 fill_form_1(&forms_1[i], &builtinlist[i]);
7274 SAFE_FREE(builtinlist);
7276 for (; i<*numofforms; i++) {
7277 DEBUGADD(6,("Filling form number [%d]\n",i));
7278 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7283 /* check the required size. */
7284 for (i=0; i<numbuiltinforms; i++) {
7285 DEBUGADD(6,("adding form [%d]'s size\n",i));
7286 buffer_size += spoolss_size_form_1(&forms_1[i]);
7288 for (; i<*numofforms; i++) {
7289 DEBUGADD(6,("adding form [%d]'s size\n",i));
7290 buffer_size += spoolss_size_form_1(&forms_1[i]);
7293 *needed=buffer_size;
7295 if (*needed > offered) {
7298 return WERR_INSUFFICIENT_BUFFER;
7301 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7307 /* fill the buffer with the form structures */
7308 for (i=0; i<numbuiltinforms; i++) {
7309 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7310 smb_io_form_1("", buffer, &forms_1[i], 0);
7312 for (; i<*numofforms; i++) {
7313 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7314 smb_io_form_1("", buffer, &forms_1[i], 0);
7323 SAFE_FREE(builtinlist);
7324 return WERR_UNKNOWN_LEVEL;
7328 /****************************************************************************
7329 ****************************************************************************/
7331 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7333 uint32 level = q_u->level;
7334 UNISTR2 *uni_formname = &q_u->formname;
7335 RPC_BUFFER *buffer = NULL;
7336 uint32 offered = q_u->offered;
7337 uint32 *needed = &r_u->needed;
7339 nt_forms_struct *list=NULL;
7340 nt_forms_struct builtin_form;
7345 int numofforms=0, i=0;
7347 /* that's an [in out] buffer */
7349 if (!q_u->buffer && (offered!=0)) {
7350 return WERR_INVALID_PARAM;
7353 rpcbuf_move(q_u->buffer, &r_u->buffer);
7354 buffer = r_u->buffer;
7356 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7358 DEBUG(4,("_spoolss_getform\n"));
7359 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7360 DEBUGADD(5,("Info level [%d]\n", level));
7362 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7363 if (!foundBuiltin) {
7364 numofforms = get_ntforms(&list);
7365 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7367 if (numofforms == 0)
7374 fill_form_1(&form_1, &builtin_form);
7377 /* Check if the requested name is in the list of form structures */
7378 for (i=0; i<numofforms; i++) {
7380 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7382 if (strequal(form_name, list[i].name)) {
7383 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7384 fill_form_1(&form_1, &list[i]);
7390 if (i == numofforms) {
7394 /* check the required size. */
7396 *needed=spoolss_size_form_1(&form_1);
7398 if (*needed > offered)
7399 return WERR_INSUFFICIENT_BUFFER;
7401 if (!rpcbuf_alloc_size(buffer, buffer_size))
7404 /* fill the buffer with the form structures */
7405 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7406 smb_io_form_1("", buffer, &form_1, 0);
7412 return WERR_UNKNOWN_LEVEL;
7416 /****************************************************************************
7417 ****************************************************************************/
7419 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7421 init_unistr(&port->port_name, name);
7424 /****************************************************************************
7425 TODO: This probably needs distinguish between TCP/IP and Local ports
7427 ****************************************************************************/
7429 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7431 init_unistr(&port->port_name, name);
7432 init_unistr(&port->monitor_name, "Local Monitor");
7433 init_unistr(&port->description, SPL_LOCAL_PORT );
7434 port->port_type=PORT_TYPE_WRITE;
7439 /****************************************************************************
7440 wrapper around the enumer ports command
7441 ****************************************************************************/
7443 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7445 char *cmd = lp_enumports_cmd();
7446 char **qlines = NULL;
7447 char *command = NULL;
7455 /* if no hook then just fill in the default port */
7458 if (!(qlines = SMB_MALLOC_ARRAY( char*, 2 ))) {
7461 if (!(qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME ))) {
7469 /* we have a valid enumport command */
7471 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7476 DEBUG(10,("Running [%s]\n", command));
7477 ret = smbrun(command, &fd);
7478 DEBUG(10,("Returned [%d]\n", ret));
7479 TALLOC_FREE(command);
7484 return WERR_ACCESS_DENIED;
7488 qlines = fd_lines_load(fd, &numlines, 0);
7489 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7499 /****************************************************************************
7501 ****************************************************************************/
7503 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7505 PORT_INFO_1 *ports=NULL;
7507 WERROR result = WERR_OK;
7508 char **qlines = NULL;
7511 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7512 if (!W_ERROR_IS_OK(result)) {
7513 file_lines_free(qlines);
7518 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7519 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7520 dos_errstr(WERR_NOMEM)));
7521 file_lines_free(qlines);
7525 for (i=0; i<numlines; i++) {
7526 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7527 fill_port_1(&ports[i], qlines[i]);
7530 file_lines_free(qlines);
7532 *returned = numlines;
7534 /* check the required size. */
7535 for (i=0; i<*returned; i++) {
7536 DEBUGADD(6,("adding port [%d]'s size\n", i));
7537 *needed += spoolss_size_port_info_1(&ports[i]);
7540 if (*needed > offered) {
7541 result = WERR_INSUFFICIENT_BUFFER;
7545 if (!rpcbuf_alloc_size(buffer, *needed)) {
7546 result = WERR_NOMEM;
7550 /* fill the buffer with the ports structures */
7551 for (i=0; i<*returned; i++) {
7552 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7553 smb_io_port_1("", buffer, &ports[i], 0);
7559 if ( !W_ERROR_IS_OK(result) )
7565 /****************************************************************************
7567 ****************************************************************************/
7569 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7571 PORT_INFO_2 *ports=NULL;
7573 WERROR result = WERR_OK;
7574 char **qlines = NULL;
7577 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7578 if ( !W_ERROR_IS_OK(result)) {
7579 file_lines_free(qlines);
7584 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7585 file_lines_free(qlines);
7589 for (i=0; i<numlines; i++) {
7590 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7591 fill_port_2(&(ports[i]), qlines[i]);
7595 file_lines_free(qlines);
7597 *returned = numlines;
7599 /* check the required size. */
7600 for (i=0; i<*returned; i++) {
7601 DEBUGADD(6,("adding port [%d]'s size\n", i));
7602 *needed += spoolss_size_port_info_2(&ports[i]);
7605 if (*needed > offered) {
7606 result = WERR_INSUFFICIENT_BUFFER;
7610 if (!rpcbuf_alloc_size(buffer, *needed)) {
7611 result = WERR_NOMEM;
7615 /* fill the buffer with the ports structures */
7616 for (i=0; i<*returned; i++) {
7617 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7618 smb_io_port_2("", buffer, &ports[i], 0);
7624 if ( !W_ERROR_IS_OK(result) )
7630 /****************************************************************************
7632 ****************************************************************************/
7634 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7636 uint32 level = q_u->level;
7637 RPC_BUFFER *buffer = NULL;
7638 uint32 offered = q_u->offered;
7639 uint32 *needed = &r_u->needed;
7640 uint32 *returned = &r_u->returned;
7642 /* that's an [in out] buffer */
7644 if (!q_u->buffer && (offered!=0)) {
7645 return WERR_INVALID_PARAM;
7648 rpcbuf_move(q_u->buffer, &r_u->buffer);
7649 buffer = r_u->buffer;
7651 DEBUG(4,("_spoolss_enumports\n"));
7658 return enumports_level_1(buffer, offered, needed, returned);
7660 return enumports_level_2(buffer, offered, needed, returned);
7662 return WERR_UNKNOWN_LEVEL;
7666 /****************************************************************************
7667 ****************************************************************************/
7669 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7670 const SPOOL_PRINTER_INFO_LEVEL *info,
7671 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7672 uint32 user_switch, const SPOOL_USER_CTR *user,
7675 NT_PRINTER_INFO_LEVEL *printer = NULL;
7678 WERROR err = WERR_OK;
7680 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7681 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7685 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7686 if (!convert_printer_info(info, printer, 2)) {
7687 free_a_printer(&printer, 2);
7691 /* check to see if the printer already exists */
7693 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7694 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7695 printer->info_2->sharename));
7696 free_a_printer(&printer, 2);
7697 return WERR_PRINTER_ALREADY_EXISTS;
7700 /* FIXME!!! smbd should check to see if the driver is installed before
7701 trying to add a printer like this --jerry */
7703 if (*lp_addprinter_cmd() ) {
7704 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
7705 free_a_printer(&printer,2);
7706 return WERR_ACCESS_DENIED;
7709 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7710 "smb.conf parameter \"addprinter command\" is defined. This"
7711 "parameter must exist for this call to succeed\n",
7712 printer->info_2->sharename ));
7715 /* use our primary netbios name since get_a_printer() will convert
7716 it to what the client expects on a case by case basis */
7718 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7719 printer->info_2->sharename);
7722 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7723 free_a_printer(&printer,2);
7724 return WERR_ACCESS_DENIED;
7727 /* you must be a printer admin to add a new printer */
7728 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7729 free_a_printer(&printer,2);
7730 return WERR_ACCESS_DENIED;
7734 * Do sanity check on the requested changes for Samba.
7737 if (!check_printer_ok(printer->info_2, snum)) {
7738 free_a_printer(&printer,2);
7739 return WERR_INVALID_PARAM;
7743 * When a printer is created, the drivername bound to the printer is used
7744 * to lookup previously saved driver initialization info, which is then
7745 * bound to the new printer, simulating what happens in the Windows arch.
7750 set_driver_init(printer, 2);
7754 /* A valid devmode was included, convert and link it
7756 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7758 if (!convert_devicemode(printer->info_2->printername, devmode,
7759 &printer->info_2->devmode))
7763 /* write the ASCII on disk */
7764 err = mod_a_printer(printer, 2);
7765 if (!W_ERROR_IS_OK(err)) {
7766 free_a_printer(&printer,2);
7770 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7771 /* Handle open failed - remove addition. */
7772 del_a_printer(printer->info_2->sharename);
7773 free_a_printer(&printer,2);
7774 return WERR_ACCESS_DENIED;
7777 update_c_setprinter(False);
7778 free_a_printer(&printer,2);
7783 /****************************************************************************
7784 ****************************************************************************/
7786 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7788 UNISTR2 *uni_srv_name = q_u->server_name;
7789 uint32 level = q_u->level;
7790 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7791 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7792 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7793 uint32 user_switch = q_u->user_switch;
7794 SPOOL_USER_CTR *user = &q_u->user_ctr;
7795 POLICY_HND *handle = &r_u->handle;
7799 /* we don't handle yet */
7800 /* but I know what to do ... */
7801 return WERR_UNKNOWN_LEVEL;
7803 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7805 user_switch, user, handle);
7807 return WERR_UNKNOWN_LEVEL;
7811 /****************************************************************************
7812 ****************************************************************************/
7814 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7816 uint32 level = q_u->level;
7817 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7818 WERROR err = WERR_OK;
7819 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7820 fstring driver_name;
7823 ZERO_STRUCT(driver);
7825 if (!convert_printer_driver_info(info, &driver, level)) {
7830 DEBUG(5,("Cleaning driver's information\n"));
7831 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7832 if (!W_ERROR_IS_OK(err))
7835 DEBUG(5,("Moving driver to final destination\n"));
7836 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7840 if (add_a_printer_driver(driver, level)!=0) {
7841 err = WERR_ACCESS_DENIED;
7846 * I think this is where he DrvUpgradePrinter() hook would be
7847 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7848 * server. Right now, we just need to send ourselves a message
7849 * to update each printer bound to this driver. --jerry
7852 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7853 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7858 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7859 * decide if the driver init data should be deleted. The rules are:
7860 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7861 * 2) delete init data only if there is no 2k/Xp driver
7862 * 3) always delete init data
7863 * The generalized rule is always use init data from the highest order driver.
7864 * It is necessary to follow the driver install by an initialization step to
7865 * finish off this process.
7868 version = driver.info_3->cversion;
7869 else if (level == 6)
7870 version = driver.info_6->version;
7875 * 9x printer driver - never delete init data
7878 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7883 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7884 * there is no 2k/Xp driver init data for this driver name.
7888 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7890 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7892 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7894 if (!del_driver_init(driver_name))
7895 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7898 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7900 free_a_printer_driver(driver1,3);
7901 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7908 * 2k or Xp printer driver - always delete init data
7911 if (!del_driver_init(driver_name))
7912 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7916 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7922 free_a_printer_driver(driver, level);
7926 /********************************************************************
7927 * spoolss_addprinterdriverex
7928 ********************************************************************/
7930 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7932 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7933 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7936 * we only support the semantics of AddPrinterDriver()
7937 * i.e. only copy files that are newer than existing ones
7940 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7941 return WERR_ACCESS_DENIED;
7943 ZERO_STRUCT(q_u_local);
7944 ZERO_STRUCT(r_u_local);
7946 /* just pass the information off to _spoolss_addprinterdriver() */
7947 q_u_local.server_name_ptr = q_u->server_name_ptr;
7948 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7949 q_u_local.level = q_u->level;
7950 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7952 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7955 /****************************************************************************
7956 ****************************************************************************/
7958 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7960 init_unistr(&info->name, name);
7963 /****************************************************************************
7964 ****************************************************************************/
7966 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7969 char *long_archi = NULL;
7970 char *servername = NULL;
7971 char *pservername = NULL;
7972 const char *short_archi;
7973 DRIVER_DIRECTORY_1 *info=NULL;
7974 WERROR result = WERR_OK;
7975 TALLOC_CTX *ctx = talloc_tos();
7977 servername = unistr2_to_ascii_talloc(ctx, name);
7981 long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
7986 /* check for beginning double '\'s and that the server
7989 pservername = servername;
7990 if ( *pservername == '\\' && strlen(servername)>2 ) {
7994 if ( !is_myname_or_ipaddr( pservername ) )
7995 return WERR_INVALID_PARAM;
7997 if (!(short_archi = get_short_archi(long_archi)))
7998 return WERR_INVALID_ENVIRONMENT;
8000 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8003 path = talloc_asprintf(ctx,
8004 "\\\\%s\\print$\\%s", pservername, short_archi);
8006 result = WERR_NOMEM;
8010 DEBUG(4,("printer driver directory: [%s]\n", path));
8012 fill_driverdir_1(info, path);
8014 *needed += spoolss_size_driverdir_info_1(info);
8016 if (*needed > offered) {
8017 result = WERR_INSUFFICIENT_BUFFER;
8021 if (!rpcbuf_alloc_size(buffer, *needed)) {
8022 result = WERR_NOMEM;
8026 smb_io_driverdir_1("", buffer, info, 0);
8034 /****************************************************************************
8035 ****************************************************************************/
8037 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8039 UNISTR2 *name = &q_u->name;
8040 UNISTR2 *uni_environment = &q_u->environment;
8041 uint32 level = q_u->level;
8042 RPC_BUFFER *buffer = NULL;
8043 uint32 offered = q_u->offered;
8044 uint32 *needed = &r_u->needed;
8046 /* that's an [in out] buffer */
8048 if (!q_u->buffer && (offered!=0)) {
8049 return WERR_INVALID_PARAM;
8052 rpcbuf_move(q_u->buffer, &r_u->buffer);
8053 buffer = r_u->buffer;
8055 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8061 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8063 return WERR_UNKNOWN_LEVEL;
8067 /****************************************************************************
8068 ****************************************************************************/
8070 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8072 POLICY_HND *handle = &q_u->handle;
8073 uint32 idx = q_u->index;
8074 uint32 in_value_len = q_u->valuesize;
8075 uint32 in_data_len = q_u->datasize;
8076 uint32 *out_max_value_len = &r_u->valuesize;
8077 uint16 **out_value = &r_u->value;
8078 uint32 *out_value_len = &r_u->realvaluesize;
8079 uint32 *out_type = &r_u->type;
8080 uint32 *out_max_data_len = &r_u->datasize;
8081 uint8 **data_out = &r_u->data;
8082 uint32 *out_data_len = &r_u->realdatasize;
8084 NT_PRINTER_INFO_LEVEL *printer = NULL;
8086 uint32 biggest_valuesize;
8087 uint32 biggest_datasize;
8089 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8092 REGISTRY_VALUE *val = NULL;
8093 NT_PRINTER_DATA *p_data;
8094 int i, key_index, num_values;
8099 *out_max_data_len = 0;
8103 DEBUG(5,("spoolss_enumprinterdata\n"));
8106 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8110 if (!get_printer_snum(p,handle, &snum, NULL))
8113 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8114 if (!W_ERROR_IS_OK(result))
8117 p_data = printer->info_2->data;
8118 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8123 * The NT machine wants to know the biggest size of value and data
8125 * cf: MSDN EnumPrinterData remark section
8128 if ( !in_value_len && !in_data_len && (key_index != -1) )
8130 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8132 biggest_valuesize = 0;
8133 biggest_datasize = 0;
8135 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8137 for ( i=0; i<num_values; i++ )
8139 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8141 name_length = strlen(val->valuename);
8142 if ( strlen(val->valuename) > biggest_valuesize )
8143 biggest_valuesize = name_length;
8145 if ( val->size > biggest_datasize )
8146 biggest_datasize = val->size;
8148 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8152 /* the value is an UNICODE string but real_value_size is the length
8153 in bytes including the trailing 0 */
8155 *out_value_len = 2 * (1+biggest_valuesize);
8156 *out_data_len = biggest_datasize;
8158 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8164 * the value len is wrong in NT sp3
8165 * that's the number of bytes not the number of unicode chars
8168 if ( key_index != -1 )
8169 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8174 /* out_value should default to "" or else NT4 has
8175 problems unmarshalling the response */
8177 *out_max_value_len=(in_value_len/sizeof(uint16));
8180 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8182 result = WERR_NOMEM;
8185 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8191 /* the data is counted in bytes */
8193 *out_max_data_len = in_data_len;
8194 *out_data_len = in_data_len;
8196 /* only allocate when given a non-zero data_len */
8198 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8200 result = WERR_NOMEM;
8204 result = WERR_NO_MORE_ITEMS;
8210 * - counted in bytes in the request
8211 * - counted in UNICODE chars in the max reply
8212 * - counted in bytes in the real size
8214 * take a pause *before* coding not *during* coding
8218 *out_max_value_len=(in_value_len/sizeof(uint16));
8220 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8222 result = WERR_NOMEM;
8226 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8234 *out_type = regval_type( val );
8236 /* data - counted in bytes */
8238 *out_max_data_len = in_data_len;
8239 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8241 result = WERR_NOMEM;
8244 data_len = regval_size(val);
8245 if ( *data_out && data_len )
8246 memcpy( *data_out, regval_data_p(val), data_len );
8247 *out_data_len = data_len;
8251 free_a_printer(&printer, 2);
8255 /****************************************************************************
8256 ****************************************************************************/
8258 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8260 POLICY_HND *handle = &q_u->handle;
8261 UNISTR2 *value = &q_u->value;
8262 uint32 type = q_u->type;
8263 uint8 *data = q_u->data;
8264 uint32 real_len = q_u->real_len;
8266 NT_PRINTER_INFO_LEVEL *printer = NULL;
8268 WERROR status = WERR_OK;
8269 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8272 DEBUG(5,("spoolss_setprinterdata\n"));
8275 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8279 if ( Printer->printer_type == SPLHND_SERVER ) {
8280 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8281 return WERR_INVALID_PARAM;
8284 if (!get_printer_snum(p,handle, &snum, NULL))
8288 * Access check : NT returns "access denied" if you make a
8289 * SetPrinterData call without the necessary privildge.
8290 * we were originally returning OK if nothing changed
8291 * which made Win2k issue **a lot** of SetPrinterData
8292 * when connecting to a printer --jerry
8295 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8297 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8298 status = WERR_ACCESS_DENIED;
8302 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8303 if (!W_ERROR_IS_OK(status))
8306 unistr2_to_ascii(valuename, value, sizeof(valuename));
8309 * When client side code sets a magic printer data key, detect it and save
8310 * the current printer data and the magic key's data (its the DEVMODE) for
8311 * future printer/driver initializations.
8313 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8315 /* Set devmode and printer initialization info */
8316 status = save_driver_init( printer, 2, data, real_len );
8318 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8322 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8323 type, data, real_len );
8324 if ( W_ERROR_IS_OK(status) )
8325 status = mod_a_printer(printer, 2);
8329 free_a_printer(&printer, 2);
8334 /****************************************************************************
8335 ****************************************************************************/
8337 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8339 POLICY_HND *handle = &q_u->handle;
8340 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8343 DEBUG(5,("_spoolss_resetprinter\n"));
8346 * All we do is to check to see if the handle and queue is valid.
8347 * This call really doesn't mean anything to us because we only
8348 * support RAW printing. --jerry
8352 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8356 if (!get_printer_snum(p,handle, &snum, NULL))
8360 /* blindly return success */
8365 /****************************************************************************
8366 ****************************************************************************/
8368 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8370 POLICY_HND *handle = &q_u->handle;
8371 UNISTR2 *value = &q_u->valuename;
8373 NT_PRINTER_INFO_LEVEL *printer = NULL;
8375 WERROR status = WERR_OK;
8376 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8377 char *valuename = NULL;
8378 TALLOC_CTX *ctx = p->mem_ctx;
8380 DEBUG(5,("spoolss_deleteprinterdata\n"));
8383 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8387 if (!get_printer_snum(p, handle, &snum, NULL))
8390 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8391 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8392 return WERR_ACCESS_DENIED;
8395 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8396 if (!W_ERROR_IS_OK(status))
8399 valuename = unistr2_to_ascii_talloc(ctx, value);
8401 free_a_printer(&printer, 2);
8405 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8407 if ( W_ERROR_IS_OK(status) )
8408 mod_a_printer( printer, 2 );
8410 free_a_printer(&printer, 2);
8411 TALLOC_FREE(valuename);
8416 /****************************************************************************
8417 ****************************************************************************/
8419 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8421 POLICY_HND *handle = &q_u->handle;
8422 FORM *form = &q_u->form;
8423 nt_forms_struct tmpForm;
8425 WERROR status = WERR_OK;
8426 NT_PRINTER_INFO_LEVEL *printer = NULL;
8429 nt_forms_struct *list=NULL;
8430 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8432 DEBUG(5,("spoolss_addform\n"));
8435 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8440 /* forms can be added on printer of on the print server handle */
8442 if ( Printer->printer_type == SPLHND_PRINTER )
8444 if (!get_printer_snum(p,handle, &snum, NULL))
8447 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8448 if (!W_ERROR_IS_OK(status))
8452 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8453 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8454 status = WERR_ACCESS_DENIED;
8458 /* can't add if builtin */
8460 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8461 status = WERR_ALREADY_EXISTS;
8465 count = get_ntforms(&list);
8467 if(!add_a_form(&list, form, &count)) {
8468 status = WERR_NOMEM;
8472 write_ntforms(&list, count);
8475 * ChangeID must always be set if this is a printer
8478 if ( Printer->printer_type == SPLHND_PRINTER )
8479 status = mod_a_printer(printer, 2);
8483 free_a_printer(&printer, 2);
8489 /****************************************************************************
8490 ****************************************************************************/
8492 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8494 POLICY_HND *handle = &q_u->handle;
8495 UNISTR2 *form_name = &q_u->name;
8496 nt_forms_struct tmpForm;
8498 nt_forms_struct *list=NULL;
8499 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8501 WERROR status = WERR_OK;
8502 NT_PRINTER_INFO_LEVEL *printer = NULL;
8504 DEBUG(5,("spoolss_deleteform\n"));
8507 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8511 /* forms can be deleted on printer of on the print server handle */
8513 if ( Printer->printer_type == SPLHND_PRINTER )
8515 if (!get_printer_snum(p,handle, &snum, NULL))
8518 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8519 if (!W_ERROR_IS_OK(status))
8523 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8524 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8525 status = WERR_ACCESS_DENIED;
8529 /* can't delete if builtin */
8531 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8532 status = WERR_INVALID_PARAM;
8536 count = get_ntforms(&list);
8538 if ( !delete_a_form(&list, form_name, &count, &status ))
8542 * ChangeID must always be set if this is a printer
8545 if ( Printer->printer_type == SPLHND_PRINTER )
8546 status = mod_a_printer(printer, 2);
8550 free_a_printer(&printer, 2);
8556 /****************************************************************************
8557 ****************************************************************************/
8559 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8561 POLICY_HND *handle = &q_u->handle;
8562 FORM *form = &q_u->form;
8563 nt_forms_struct tmpForm;
8565 WERROR status = WERR_OK;
8566 NT_PRINTER_INFO_LEVEL *printer = NULL;
8569 nt_forms_struct *list=NULL;
8570 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8572 DEBUG(5,("spoolss_setform\n"));
8575 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8579 /* forms can be modified on printer of on the print server handle */
8581 if ( Printer->printer_type == SPLHND_PRINTER )
8583 if (!get_printer_snum(p,handle, &snum, NULL))
8586 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8587 if (!W_ERROR_IS_OK(status))
8591 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8592 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8593 status = WERR_ACCESS_DENIED;
8597 /* can't set if builtin */
8598 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8599 status = WERR_INVALID_PARAM;
8603 count = get_ntforms(&list);
8604 update_a_form(&list, form, count);
8605 write_ntforms(&list, count);
8608 * ChangeID must always be set if this is a printer
8611 if ( Printer->printer_type == SPLHND_PRINTER )
8612 status = mod_a_printer(printer, 2);
8617 free_a_printer(&printer, 2);
8623 /****************************************************************************
8624 enumprintprocessors level 1.
8625 ****************************************************************************/
8627 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8629 PRINTPROCESSOR_1 *info_1=NULL;
8630 WERROR result = WERR_OK;
8632 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8637 init_unistr(&info_1->name, "winprint");
8639 *needed += spoolss_size_printprocessor_info_1(info_1);
8641 if (*needed > offered) {
8642 result = WERR_INSUFFICIENT_BUFFER;
8646 if (!rpcbuf_alloc_size(buffer, *needed)) {
8647 result = WERR_NOMEM;
8651 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8656 if ( !W_ERROR_IS_OK(result) )
8662 /****************************************************************************
8663 ****************************************************************************/
8665 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8667 uint32 level = q_u->level;
8668 RPC_BUFFER *buffer = NULL;
8669 uint32 offered = q_u->offered;
8670 uint32 *needed = &r_u->needed;
8671 uint32 *returned = &r_u->returned;
8673 /* that's an [in out] buffer */
8675 if (!q_u->buffer && (offered!=0)) {
8676 return WERR_INVALID_PARAM;
8679 rpcbuf_move(q_u->buffer, &r_u->buffer);
8680 buffer = r_u->buffer;
8682 DEBUG(5,("spoolss_enumprintprocessors\n"));
8685 * Enumerate the print processors ...
8687 * Just reply with "winprint", to keep NT happy
8688 * and I can use my nice printer checker.
8696 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8698 return WERR_UNKNOWN_LEVEL;
8702 /****************************************************************************
8703 enumprintprocdatatypes level 1.
8704 ****************************************************************************/
8706 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8708 PRINTPROCDATATYPE_1 *info_1=NULL;
8709 WERROR result = WERR_OK;
8711 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8716 init_unistr(&info_1->name, "RAW");
8718 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8720 if (*needed > offered) {
8721 result = WERR_INSUFFICIENT_BUFFER;
8725 if (!rpcbuf_alloc_size(buffer, *needed)) {
8726 result = WERR_NOMEM;
8730 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8735 if ( !W_ERROR_IS_OK(result) )
8741 /****************************************************************************
8742 ****************************************************************************/
8744 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8746 uint32 level = q_u->level;
8747 RPC_BUFFER *buffer = NULL;
8748 uint32 offered = q_u->offered;
8749 uint32 *needed = &r_u->needed;
8750 uint32 *returned = &r_u->returned;
8752 /* that's an [in out] buffer */
8754 if (!q_u->buffer && (offered!=0)) {
8755 return WERR_INVALID_PARAM;
8758 rpcbuf_move(q_u->buffer, &r_u->buffer);
8759 buffer = r_u->buffer;
8761 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8768 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8770 return WERR_UNKNOWN_LEVEL;
8774 /****************************************************************************
8775 enumprintmonitors level 1.
8776 ****************************************************************************/
8778 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8780 PRINTMONITOR_1 *info_1;
8781 WERROR result = WERR_OK;
8784 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8789 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8790 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8792 for ( i=0; i<*returned; i++ ) {
8793 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8796 if (*needed > offered) {
8797 result = WERR_INSUFFICIENT_BUFFER;
8801 if (!rpcbuf_alloc_size(buffer, *needed)) {
8802 result = WERR_NOMEM;
8806 for ( i=0; i<*returned; i++ ) {
8807 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8813 if ( !W_ERROR_IS_OK(result) )
8819 /****************************************************************************
8820 enumprintmonitors level 2.
8821 ****************************************************************************/
8823 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8825 PRINTMONITOR_2 *info_2;
8826 WERROR result = WERR_OK;
8829 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8834 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8835 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8836 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8838 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8839 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8840 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8842 for ( i=0; i<*returned; i++ ) {
8843 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8846 if (*needed > offered) {
8847 result = WERR_INSUFFICIENT_BUFFER;
8851 if (!rpcbuf_alloc_size(buffer, *needed)) {
8852 result = WERR_NOMEM;
8856 for ( i=0; i<*returned; i++ ) {
8857 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8863 if ( !W_ERROR_IS_OK(result) )
8869 /****************************************************************************
8870 ****************************************************************************/
8872 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8874 uint32 level = q_u->level;
8875 RPC_BUFFER *buffer = NULL;
8876 uint32 offered = q_u->offered;
8877 uint32 *needed = &r_u->needed;
8878 uint32 *returned = &r_u->returned;
8880 /* that's an [in out] buffer */
8882 if (!q_u->buffer && (offered!=0)) {
8883 return WERR_INVALID_PARAM;
8886 rpcbuf_move(q_u->buffer, &r_u->buffer);
8887 buffer = r_u->buffer;
8889 DEBUG(5,("spoolss_enumprintmonitors\n"));
8892 * Enumerate the print monitors ...
8894 * Just reply with "Local Port", to keep NT happy
8895 * and I can use my nice printer checker.
8903 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8905 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8907 return WERR_UNKNOWN_LEVEL;
8911 /****************************************************************************
8912 ****************************************************************************/
8914 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8915 NT_PRINTER_INFO_LEVEL *ntprinter,
8916 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8921 JOB_INFO_1 *info_1=NULL;
8922 WERROR result = WERR_OK;
8924 info_1=SMB_MALLOC_P(JOB_INFO_1);
8926 if (info_1 == NULL) {
8930 for (i=0; i<count && found==False; i++) {
8931 if ((*queue)[i].job==(int)jobid)
8937 /* NT treats not found as bad param... yet another bad choice */
8938 return WERR_INVALID_PARAM;
8941 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8943 *needed += spoolss_size_job_info_1(info_1);
8945 if (*needed > offered) {
8946 result = WERR_INSUFFICIENT_BUFFER;
8950 if (!rpcbuf_alloc_size(buffer, *needed)) {
8951 result = WERR_NOMEM;
8955 smb_io_job_info_1("", buffer, info_1, 0);
8963 /****************************************************************************
8964 ****************************************************************************/
8966 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8967 NT_PRINTER_INFO_LEVEL *ntprinter,
8968 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8975 DEVICEMODE *devmode = NULL;
8976 NT_DEVICEMODE *nt_devmode = NULL;
8978 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8981 ZERO_STRUCTP(info_2);
8983 for ( i=0; i<count && found==False; i++ )
8985 if ((*queue)[i].job == (int)jobid)
8990 /* NT treats not found as bad param... yet another bad
8992 result = WERR_INVALID_PARAM;
8997 * if the print job does not have a DEVMODE associated with it,
8998 * just use the one for the printer. A NULL devicemode is not
8999 * a failure condition
9002 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9003 devmode = construct_dev_mode(lp_const_servicename(snum));
9005 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9006 ZERO_STRUCTP( devmode );
9007 convert_nt_devicemode( devmode, nt_devmode );
9011 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9013 *needed += spoolss_size_job_info_2(info_2);
9015 if (*needed > offered) {
9016 result = WERR_INSUFFICIENT_BUFFER;
9020 if (!rpcbuf_alloc_size(buffer, *needed)) {
9021 result = WERR_NOMEM;
9025 smb_io_job_info_2("", buffer, info_2, 0);
9030 /* Cleanup allocated memory */
9032 free_job_info_2(info_2); /* Also frees devmode */
9038 /****************************************************************************
9039 ****************************************************************************/
9041 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9043 POLICY_HND *handle = &q_u->handle;
9044 uint32 jobid = q_u->jobid;
9045 uint32 level = q_u->level;
9046 RPC_BUFFER *buffer = NULL;
9047 uint32 offered = q_u->offered;
9048 uint32 *needed = &r_u->needed;
9049 WERROR wstatus = WERR_OK;
9050 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9053 print_queue_struct *queue = NULL;
9054 print_status_struct prt_status;
9056 /* that's an [in out] buffer */
9058 if (!q_u->buffer && (offered!=0)) {
9059 return WERR_INVALID_PARAM;
9062 rpcbuf_move(q_u->buffer, &r_u->buffer);
9063 buffer = r_u->buffer;
9065 DEBUG(5,("spoolss_getjob\n"));
9069 if (!get_printer_snum(p, handle, &snum, NULL))
9072 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9073 if ( !W_ERROR_IS_OK(wstatus) )
9076 count = print_queue_status(snum, &queue, &prt_status);
9078 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9079 count, prt_status.status, prt_status.message));
9083 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9084 buffer, offered, needed);
9087 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9088 buffer, offered, needed);
9091 wstatus = WERR_UNKNOWN_LEVEL;
9096 free_a_printer( &ntprinter, 2 );
9101 /********************************************************************
9102 spoolss_getprinterdataex
9104 From MSDN documentation of GetPrinterDataEx: pass request
9105 to GetPrinterData if key is "PrinterDriverData".
9106 ********************************************************************/
9108 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9110 POLICY_HND *handle = &q_u->handle;
9111 uint32 in_size = q_u->size;
9112 uint32 *type = &r_u->type;
9113 uint32 *out_size = &r_u->size;
9114 uint8 **data = &r_u->data;
9115 uint32 *needed = &r_u->needed;
9116 fstring keyname, valuename;
9118 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9120 NT_PRINTER_INFO_LEVEL *printer = NULL;
9122 WERROR status = WERR_OK;
9124 DEBUG(4,("_spoolss_getprinterdataex\n"));
9126 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9127 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9129 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9130 keyname, valuename));
9132 /* in case of problem, return some default values */
9136 *out_size = in_size;
9139 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9140 status = WERR_BADFID;
9144 /* Is the handle to a printer or to the server? */
9146 if (Printer->printer_type == SPLHND_SERVER) {
9147 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9148 status = WERR_INVALID_PARAM;
9152 if ( !get_printer_snum(p,handle, &snum, NULL) )
9155 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9156 if ( !W_ERROR_IS_OK(status) )
9159 /* check to see if the keyname is valid */
9160 if ( !strlen(keyname) ) {
9161 status = WERR_INVALID_PARAM;
9165 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9166 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9167 free_a_printer( &printer, 2 );
9168 status = WERR_BADFILE;
9172 /* When given a new keyname, we should just create it */
9174 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9176 if (*needed > *out_size)
9177 status = WERR_MORE_DATA;
9180 if ( !W_ERROR_IS_OK(status) )
9182 DEBUG(5, ("error: allocating %d\n", *out_size));
9184 /* reply this param doesn't exist */
9188 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9189 status = WERR_NOMEM;
9198 free_a_printer( &printer, 2 );
9203 /********************************************************************
9204 * spoolss_setprinterdataex
9205 ********************************************************************/
9207 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9209 POLICY_HND *handle = &q_u->handle;
9210 uint32 type = q_u->type;
9211 uint8 *data = q_u->data;
9212 uint32 real_len = q_u->real_len;
9214 NT_PRINTER_INFO_LEVEL *printer = NULL;
9216 WERROR status = WERR_OK;
9217 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9222 DEBUG(4,("_spoolss_setprinterdataex\n"));
9224 /* From MSDN documentation of SetPrinterDataEx: pass request to
9225 SetPrinterData if key is "PrinterDriverData" */
9228 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9232 if ( Printer->printer_type == SPLHND_SERVER ) {
9233 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9234 return WERR_INVALID_PARAM;
9237 if ( !get_printer_snum(p,handle, &snum, NULL) )
9241 * Access check : NT returns "access denied" if you make a
9242 * SetPrinterData call without the necessary privildge.
9243 * we were originally returning OK if nothing changed
9244 * which made Win2k issue **a lot** of SetPrinterData
9245 * when connecting to a printer --jerry
9248 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9250 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9251 return WERR_ACCESS_DENIED;
9254 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9255 if (!W_ERROR_IS_OK(status))
9258 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9259 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9261 /* check for OID in valuename */
9263 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9269 /* save the registry data */
9271 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9273 if ( W_ERROR_IS_OK(status) )
9275 /* save the OID if one was specified */
9277 fstrcat( keyname, "\\" );
9278 fstrcat( keyname, SPOOL_OID_KEY );
9281 * I'm not checking the status here on purpose. Don't know
9282 * if this is right, but I'm returning the status from the
9283 * previous set_printer_dataex() call. I have no idea if
9284 * this is right. --jerry
9287 set_printer_dataex( printer, keyname, valuename,
9288 REG_SZ, (uint8 *)oid_string,
9289 strlen(oid_string)+1 );
9292 status = mod_a_printer(printer, 2);
9295 free_a_printer(&printer, 2);
9301 /********************************************************************
9302 * spoolss_deleteprinterdataex
9303 ********************************************************************/
9305 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9307 POLICY_HND *handle = &q_u->handle;
9308 UNISTR2 *value = &q_u->valuename;
9309 UNISTR2 *key = &q_u->keyname;
9311 NT_PRINTER_INFO_LEVEL *printer = NULL;
9313 WERROR status = WERR_OK;
9314 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9315 char *valuename = NULL;
9316 char *keyname = NULL;
9317 TALLOC_CTX *ctx = p->mem_ctx;
9319 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9322 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9326 if (!get_printer_snum(p, handle, &snum, NULL))
9329 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9330 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9331 return WERR_ACCESS_DENIED;
9334 valuename = unistr2_to_ascii_talloc(ctx, value);
9335 keyname = unistr2_to_ascii_talloc(ctx, key);
9336 if (!valuename || !keyname) {
9340 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9341 if (!W_ERROR_IS_OK(status))
9344 status = delete_printer_dataex( printer, keyname, valuename );
9346 if ( W_ERROR_IS_OK(status) )
9347 mod_a_printer( printer, 2 );
9349 free_a_printer(&printer, 2);
9354 /********************************************************************
9355 * spoolss_enumprinterkey
9356 ********************************************************************/
9359 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9362 fstring *keynames = NULL;
9363 uint16 *enumkeys = NULL;
9366 POLICY_HND *handle = &q_u->handle;
9367 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9368 NT_PRINTER_DATA *data;
9369 NT_PRINTER_INFO_LEVEL *printer = NULL;
9371 WERROR status = WERR_BADFILE;
9374 DEBUG(4,("_spoolss_enumprinterkey\n"));
9377 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9381 if ( !get_printer_snum(p,handle, &snum, NULL) )
9384 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9385 if (!W_ERROR_IS_OK(status))
9388 /* get the list of subkey names */
9390 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9391 data = printer->info_2->data;
9393 num_keys = get_printer_subkeys( data, key, &keynames );
9395 if ( num_keys == -1 ) {
9396 status = WERR_BADFILE;
9400 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9402 r_u->needed = printerkey_len*2;
9404 if ( q_u->size < r_u->needed ) {
9405 status = WERR_MORE_DATA;
9409 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9410 status = WERR_NOMEM;
9416 if ( q_u->size < r_u->needed )
9417 status = WERR_MORE_DATA;
9420 free_a_printer( &printer, 2 );
9421 SAFE_FREE( keynames );
9426 /********************************************************************
9427 * spoolss_deleteprinterkey
9428 ********************************************************************/
9430 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9432 POLICY_HND *handle = &q_u->handle;
9433 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9435 NT_PRINTER_INFO_LEVEL *printer = NULL;
9439 DEBUG(5,("spoolss_deleteprinterkey\n"));
9442 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9446 /* if keyname == NULL, return error */
9448 if ( !q_u->keyname.buffer )
9449 return WERR_INVALID_PARAM;
9451 if (!get_printer_snum(p, handle, &snum, NULL))
9454 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9455 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9456 return WERR_ACCESS_DENIED;
9459 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9460 if (!W_ERROR_IS_OK(status))
9463 /* delete the key and all subneys */
9465 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9467 status = delete_all_printer_data( printer->info_2, key );
9469 if ( W_ERROR_IS_OK(status) )
9470 status = mod_a_printer(printer, 2);
9472 free_a_printer( &printer, 2 );
9478 /********************************************************************
9479 * spoolss_enumprinterdataex
9480 ********************************************************************/
9482 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9484 POLICY_HND *handle = &q_u->handle;
9485 uint32 in_size = q_u->size;
9488 NT_PRINTER_INFO_LEVEL *printer = NULL;
9489 PRINTER_ENUM_VALUES *enum_values = NULL;
9490 NT_PRINTER_DATA *p_data;
9492 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9497 REGISTRY_VALUE *val;
9502 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9505 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9510 * first check for a keyname of NULL or "". Win2k seems to send
9511 * this a lot and we should send back WERR_INVALID_PARAM
9512 * no need to spend time looking up the printer in this case.
9516 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9517 if ( !strlen(key) ) {
9518 result = WERR_INVALID_PARAM;
9522 /* get the printer off of disk */
9524 if (!get_printer_snum(p,handle, &snum, NULL))
9527 ZERO_STRUCT(printer);
9528 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9529 if (!W_ERROR_IS_OK(result))
9532 /* now look for a match on the key name */
9534 p_data = printer->info_2->data;
9536 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9537 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9539 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9540 result = WERR_INVALID_PARAM;
9547 /* allocate the memory for the array of pointers -- if necessary */
9549 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9552 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9554 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9555 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9556 result = WERR_NOMEM;
9560 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9564 * loop through all params and build the array to pass
9565 * back to the client
9568 for ( i=0; i<num_entries; i++ )
9570 /* lookup the registry value */
9572 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9573 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9577 value_name = regval_name( val );
9578 init_unistr( &enum_values[i].valuename, value_name );
9579 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9580 enum_values[i].type = regval_type( val );
9582 data_len = regval_size( val );
9584 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9586 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9588 result = WERR_NOMEM;
9592 enum_values[i].data_len = data_len;
9594 /* keep track of the size of the array in bytes */
9596 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9599 /* housekeeping information in the reply */
9601 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9602 * the hand marshalled container size is a multiple
9603 * of 4 bytes for RPC alignment.
9607 needed += 4-(needed % 4);
9610 r_u->needed = needed;
9611 r_u->returned = num_entries;
9613 if (needed > in_size) {
9614 result = WERR_MORE_DATA;
9618 /* copy data into the reply */
9620 r_u->ctr.size = r_u->needed;
9622 r_u->ctr.size_of_array = r_u->returned;
9623 r_u->ctr.values = enum_values;
9629 free_a_printer(&printer, 2);
9634 /****************************************************************************
9635 ****************************************************************************/
9637 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9639 init_unistr(&info->name, name);
9642 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9643 UNISTR2 *environment,
9648 char *long_archi = NULL;
9649 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9650 WERROR result = WERR_OK;
9651 TALLOC_CTX *ctx = talloc_tos();
9653 long_archi = unistr2_to_ascii_talloc(ctx, environment);
9658 if (!get_short_archi(long_archi))
9659 return WERR_INVALID_ENVIRONMENT;
9661 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9664 fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9666 *needed += spoolss_size_printprocessordirectory_info_1(info);
9668 if (*needed > offered) {
9669 result = WERR_INSUFFICIENT_BUFFER;
9673 if (!rpcbuf_alloc_size(buffer, *needed)) {
9674 result = WERR_INSUFFICIENT_BUFFER;
9678 smb_io_printprocessordirectory_1("", buffer, info, 0);
9686 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9688 uint32 level = q_u->level;
9689 RPC_BUFFER *buffer = NULL;
9690 uint32 offered = q_u->offered;
9691 uint32 *needed = &r_u->needed;
9694 /* that's an [in out] buffer */
9696 if (!q_u->buffer && (offered!=0)) {
9697 return WERR_INVALID_PARAM;
9700 rpcbuf_move(q_u->buffer, &r_u->buffer);
9701 buffer = r_u->buffer;
9703 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9709 result = getprintprocessordirectory_level_1
9710 (&q_u->name, &q_u->environment, buffer, offered, needed);
9713 result = WERR_UNKNOWN_LEVEL;
9719 /*******************************************************************
9720 Streams the monitor UI DLL name in UNICODE
9721 *******************************************************************/
9723 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9724 RPC_BUFFER *out, uint32 *needed )
9726 const char *dllname = "tcpmonui.dll";
9728 *needed = (strlen(dllname)+1) * 2;
9730 if ( rpcbuf_get_size(out) < *needed ) {
9731 return WERR_INSUFFICIENT_BUFFER;
9734 if ( !make_monitorui_buf( out, dllname ) ) {
9741 /*******************************************************************
9742 Create a new TCP/IP port
9743 *******************************************************************/
9745 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9746 RPC_BUFFER *out, uint32 *needed )
9748 NT_PORT_DATA_1 port1;
9749 TALLOC_CTX *ctx = talloc_tos();
9750 char *device_uri = NULL;
9752 ZERO_STRUCT( port1 );
9754 /* convert to our internal port data structure */
9756 if ( !convert_port_data_1( &port1, in ) ) {
9760 /* create the device URI and call the add_port_hook() */
9762 switch ( port1.protocol ) {
9763 case PORT_PROTOCOL_DIRECT:
9764 device_uri = talloc_asprintf(ctx,
9765 "socket://%s:%d/", port1.hostaddr, port1.port );
9768 case PORT_PROTOCOL_LPR:
9769 device_uri = talloc_asprintf(ctx,
9770 "lpr://%s/%s", port1.hostaddr, port1.queue );
9774 return WERR_UNKNOWN_PORT;
9781 return add_port_hook(ctx, token, port1.name, device_uri );
9784 /*******************************************************************
9785 *******************************************************************/
9787 struct xcv_api_table xcvtcp_cmds[] = {
9788 { "MonitorUI", xcvtcp_monitorui },
9789 { "AddPort", xcvtcp_addport},
9793 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9794 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9799 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9801 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9802 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9803 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9806 return WERR_BADFUNC;
9809 /*******************************************************************
9810 *******************************************************************/
9811 #if 0 /* don't support management using the "Local Port" monitor */
9813 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9814 RPC_BUFFER *out, uint32 *needed )
9816 const char *dllname = "localui.dll";
9818 *needed = (strlen(dllname)+1) * 2;
9820 if ( rpcbuf_get_size(out) < *needed ) {
9821 return WERR_INSUFFICIENT_BUFFER;
9824 if ( !make_monitorui_buf( out, dllname )) {
9831 /*******************************************************************
9832 *******************************************************************/
9834 struct xcv_api_table xcvlocal_cmds[] = {
9835 { "MonitorUI", xcvlocal_monitorui },
9839 struct xcv_api_table xcvlocal_cmds[] = {
9846 /*******************************************************************
9847 *******************************************************************/
9849 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9850 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9855 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9857 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9858 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9859 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9861 return WERR_BADFUNC;
9864 /*******************************************************************
9865 *******************************************************************/
9867 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9869 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9873 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9877 /* Has to be a handle to the TCP/IP port monitor */
9879 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9880 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9884 /* requires administrative access to the server */
9886 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9887 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9888 return WERR_ACCESS_DENIED;
9891 /* Get the command name. There's numerous commands supported by the
9892 TCPMON interface. */
9894 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9895 q_u->dataname.uni_str_len*2, 0);
9897 /* Allocate the outgoing buffer */
9899 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9901 switch ( Printer->printer_type ) {
9902 case SPLHND_PORTMON_TCP:
9903 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9904 &q_u->indata, &r_u->outdata, &r_u->needed );
9905 case SPLHND_PORTMON_LOCAL:
9906 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9907 &q_u->indata, &r_u->outdata, &r_u->needed );
9910 return WERR_INVALID_PRINT_MONITOR;