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( rpc_pipe_np_smb_conn(notify_cli_pipe) );
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));
525 /* This call doesn't fill in the location or comment from
526 * a CUPS server for efficiency with large numbers of printers.
530 result = get_a_printer_search( NULL, &printer, 2, sname );
531 if ( !W_ERROR_IS_OK(result) ) {
532 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
533 sname, dos_errstr(result)));
537 /* printername is always returned as \\server\printername */
538 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
539 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
540 printer->info_2->printername));
541 free_a_printer( &printer, 2);
547 if ( strequal(printername, aprinter) ) {
548 free_a_printer( &printer, 2);
553 DEBUGADD(10, ("printername: %s\n", printername));
555 free_a_printer( &printer, 2);
558 free_a_printer( &printer, 2);
561 DEBUGADD(4,("Printer not found\n"));
565 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
567 fstrcpy(Printer->sharename, sname);
572 /****************************************************************************
573 Find first available printer slot. creates a printer handle for you.
574 ****************************************************************************/
576 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
578 Printer_entry *new_printer;
580 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
582 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
585 ZERO_STRUCTP(new_printer);
587 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
588 SAFE_FREE(new_printer);
592 /* Add to the internal list. */
593 DLIST_ADD(printers_list, new_printer);
595 new_printer->notify.option=NULL;
597 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
598 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
599 close_printer_handle(p, hnd);
603 if (!set_printer_hnd_printertype(new_printer, name)) {
604 close_printer_handle(p, hnd);
608 if (!set_printer_hnd_name(new_printer, name)) {
609 close_printer_handle(p, hnd);
613 new_printer->access_granted = access_granted;
615 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
620 /***************************************************************************
621 check to see if the client motify handle is monitoring the notification
622 given by (notify_type, notify_field).
623 **************************************************************************/
625 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
631 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
634 SPOOL_NOTIFY_OPTION *option = p->notify.option;
638 * Flags should always be zero when the change notify
639 * is registered by the client's spooler. A user Win32 app
640 * might use the flags though instead of the NOTIFY_OPTION_INFO
649 return is_monitoring_event_flags(
650 p->notify.flags, notify_type, notify_field);
652 for (i = 0; i < option->count; i++) {
654 /* Check match for notify_type */
656 if (option->ctr.type[i].type != notify_type)
659 /* Check match for field */
661 for (j = 0; j < option->ctr.type[i].count; j++) {
662 if (option->ctr.type[i].fields[j] == notify_field) {
668 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
669 p->servername, p->sharename, notify_type, notify_field));
674 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
676 static void notify_one_value(struct spoolss_notify_msg *msg,
677 SPOOL_NOTIFY_INFO_DATA *data,
680 data->notify_data.value[0] = msg->notify.value[0];
681 data->notify_data.value[1] = 0;
684 static void notify_string(struct spoolss_notify_msg *msg,
685 SPOOL_NOTIFY_INFO_DATA *data,
690 /* The length of the message includes the trailing \0 */
692 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
694 data->notify_data.data.length = msg->len * 2;
695 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
697 if (!data->notify_data.data.string) {
698 data->notify_data.data.length = 0;
702 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
705 static void notify_system_time(struct spoolss_notify_msg *msg,
706 SPOOL_NOTIFY_INFO_DATA *data,
712 if (msg->len != sizeof(time_t)) {
713 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
718 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
719 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
723 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
724 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
729 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
734 data->notify_data.data.length = prs_offset(&ps);
735 if (prs_offset(&ps)) {
736 data->notify_data.data.string = (uint16 *)
737 TALLOC(mem_ctx, prs_offset(&ps));
738 if (!data->notify_data.data.string) {
742 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
744 data->notify_data.data.string = NULL;
750 struct notify2_message_table {
752 void (*fn)(struct spoolss_notify_msg *msg,
753 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
756 static struct notify2_message_table printer_notify_table[] = {
757 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
758 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
759 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
760 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
761 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
762 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
763 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
764 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
765 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
766 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
767 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
768 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
769 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
770 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
771 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
772 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
773 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
774 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
775 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
778 static struct notify2_message_table job_notify_table[] = {
779 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
780 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
781 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
782 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
783 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
784 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
785 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
786 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
787 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
788 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
789 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
790 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
791 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
792 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
793 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
794 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
795 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
796 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
797 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
798 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
799 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
800 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
801 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
802 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
806 /***********************************************************************
807 Allocate talloc context for container object
808 **********************************************************************/
810 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
815 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
820 /***********************************************************************
821 release all allocated memory and zero out structure
822 **********************************************************************/
824 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
830 talloc_destroy(ctr->ctx);
837 /***********************************************************************
838 **********************************************************************/
840 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
848 /***********************************************************************
849 **********************************************************************/
851 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
853 if ( !ctr || !ctr->msg_groups )
856 if ( idx >= ctr->num_groups )
859 return &ctr->msg_groups[idx];
863 /***********************************************************************
864 How many groups of change messages do we have ?
865 **********************************************************************/
867 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
872 return ctr->num_groups;
875 /***********************************************************************
876 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
877 **********************************************************************/
879 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
881 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
882 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
883 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
889 /* loop over all groups looking for a matching printer name */
891 for ( i=0; i<ctr->num_groups; i++ ) {
892 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
896 /* add a new group? */
898 if ( i == ctr->num_groups ) {
901 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
902 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
905 ctr->msg_groups = groups;
907 /* clear the new entry and set the printer name */
909 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
910 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
913 /* add the change messages; 'i' is the correct index now regardless */
915 msg_grp = &ctr->msg_groups[i];
919 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
920 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
923 msg_grp->msgs = msg_list;
925 new_slot = msg_grp->num_msgs-1;
926 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
928 /* need to allocate own copy of data */
931 msg_grp->msgs[new_slot].notify.data = (char *)
932 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
934 return ctr->num_groups;
937 /***********************************************************************
938 Send a change notication message on all handles which have a call
940 **********************************************************************/
942 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
945 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
946 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
947 SPOOLSS_NOTIFY_MSG *messages;
948 int sending_msg_count;
951 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
955 messages = msg_group->msgs;
958 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
962 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
964 /* loop over all printers */
966 for (p = printers_list; p; p = p->next) {
967 SPOOL_NOTIFY_INFO_DATA *data;
972 /* Is there notification on this handle? */
974 if ( !p->notify.client_connected )
977 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
979 /* For this printer? Print servers always receive
982 if ( ( p->printer_type == SPLHND_PRINTER ) &&
983 ( !strequal(msg_group->printername, p->sharename) ) )
986 DEBUG(10,("Our printer\n"));
988 /* allocate the max entries possible */
990 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
997 /* build the array of change notifications */
999 sending_msg_count = 0;
1001 for ( i=0; i<msg_group->num_msgs; i++ ) {
1002 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1004 /* Are we monitoring this event? */
1006 if (!is_monitoring_event(p, msg->type, msg->field))
1009 sending_msg_count++;
1012 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1013 msg->type, msg->field, p->sharename));
1016 * if the is a printer notification handle and not a job notification
1017 * type, then set the id to 0. Other wise just use what was specified
1020 * When registering change notification on a print server handle
1021 * we always need to send back the id (snum) matching the printer
1022 * for which the change took place. For change notify registered
1023 * on a printer handle, this does not matter and the id should be 0.
1028 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1034 /* Convert unix jobid to smb jobid */
1036 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1037 id = sysjob_to_jobid(msg->id);
1040 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1045 construct_info_data( &data[data_len], msg->type, msg->field, id );
1048 case PRINTER_NOTIFY_TYPE:
1049 if ( printer_notify_table[msg->field].fn )
1050 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1053 case JOB_NOTIFY_TYPE:
1054 if ( job_notify_table[msg->field].fn )
1055 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1059 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1066 if ( sending_msg_count ) {
1067 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1068 data_len, data, p->notify.change, 0 );
1073 DEBUG(8,("send_notify2_changes: Exit...\n"));
1077 /***********************************************************************
1078 **********************************************************************/
1080 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1083 uint32 tv_sec, tv_usec;
1086 /* Unpack message */
1088 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1091 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1093 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1096 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1097 &msg->notify.value[0], &msg->notify.value[1]);
1099 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1100 &msg->len, &msg->notify.data);
1102 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1103 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1105 tv->tv_sec = tv_sec;
1106 tv->tv_usec = tv_usec;
1109 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1110 msg->notify.value[1]));
1112 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1117 /********************************************************************
1118 Receive a notify2 message list
1119 ********************************************************************/
1121 static void receive_notify2_message_list(struct messaging_context *msg,
1124 struct server_id server_id,
1127 size_t msg_count, i;
1128 char *buf = (char *)data->data;
1131 SPOOLSS_NOTIFY_MSG notify;
1132 SPOOLSS_NOTIFY_MSG_CTR messages;
1135 if (data->length < 4) {
1136 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1140 msg_count = IVAL(buf, 0);
1143 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1145 if (msg_count == 0) {
1146 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1150 /* initialize the container */
1152 ZERO_STRUCT( messages );
1153 notify_msg_ctr_init( &messages );
1156 * build message groups for each printer identified
1157 * in a change_notify msg. Remember that a PCN message
1158 * includes the handle returned for the srv_spoolss_replyopenprinter()
1159 * call. Therefore messages are grouped according to printer handle.
1162 for ( i=0; i<msg_count; i++ ) {
1163 struct timeval msg_tv;
1165 if (msg_ptr + 4 - buf > data->length) {
1166 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1170 msg_len = IVAL(msg_ptr,0);
1173 if (msg_ptr + msg_len - buf > data->length) {
1174 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1178 /* unpack messages */
1180 ZERO_STRUCT( notify );
1181 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1184 /* add to correct list in container */
1186 notify_msg_ctr_addmsg( &messages, ¬ify );
1188 /* free memory that might have been allocated by notify2_unpack_msg() */
1190 if ( notify.len != 0 )
1191 SAFE_FREE( notify.notify.data );
1194 /* process each group of messages */
1196 num_groups = notify_msg_ctr_numgroups( &messages );
1197 for ( i=0; i<num_groups; i++ )
1198 send_notify2_changes( &messages, i );
1203 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1205 notify_msg_ctr_destroy( &messages );
1210 /********************************************************************
1211 Send a message to ourself about new driver being installed
1212 so we can upgrade the information for each printer bound to this
1214 ********************************************************************/
1216 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1218 int len = strlen(drivername);
1223 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1226 messaging_send_buf(smbd_messaging_context(), procid_self(),
1227 MSG_PRINTER_DRVUPGRADE,
1228 (uint8 *)drivername, len+1);
1233 /**********************************************************************
1234 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1235 over all printers, upgrading ones as necessary
1236 **********************************************************************/
1238 void do_drv_upgrade_printer(struct messaging_context *msg,
1241 struct server_id server_id,
1246 int n_services = lp_numservices();
1249 len = MIN(data->length,sizeof(drivername)-1);
1250 strncpy(drivername, (const char *)data->data, len);
1252 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1254 /* Iterate the printer list */
1256 for (snum=0; snum<n_services; snum++)
1258 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1261 NT_PRINTER_INFO_LEVEL *printer = NULL;
1263 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1264 if (!W_ERROR_IS_OK(result))
1267 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1269 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1271 /* all we care about currently is the change_id */
1273 result = mod_a_printer(printer, 2);
1274 if (!W_ERROR_IS_OK(result)) {
1275 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1276 dos_errstr(result)));
1280 free_a_printer(&printer, 2);
1287 /********************************************************************
1288 Update the cache for all printq's with a registered client
1290 ********************************************************************/
1292 void update_monitored_printq_cache( void )
1294 Printer_entry *printer = printers_list;
1297 /* loop through all printers and update the cache where
1298 client_connected == True */
1301 if ( (printer->printer_type == SPLHND_PRINTER)
1302 && printer->notify.client_connected )
1304 snum = print_queue_snum(printer->sharename);
1305 print_queue_status( snum, NULL, NULL );
1308 printer = printer->next;
1313 /********************************************************************
1314 Send a message to ourself about new driver being installed
1315 so we can upgrade the information for each printer bound to this
1317 ********************************************************************/
1319 static bool srv_spoolss_reset_printerdata(char* drivername)
1321 int len = strlen(drivername);
1326 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1329 messaging_send_buf(smbd_messaging_context(), procid_self(),
1330 MSG_PRINTERDATA_INIT_RESET,
1331 (uint8 *)drivername, len+1);
1336 /**********************************************************************
1337 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1338 over all printers, resetting printer data as neessary
1339 **********************************************************************/
1341 void reset_all_printerdata(struct messaging_context *msg,
1344 struct server_id server_id,
1349 int n_services = lp_numservices();
1352 len = MIN( data->length, sizeof(drivername)-1 );
1353 strncpy( drivername, (const char *)data->data, len );
1355 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1357 /* Iterate the printer list */
1359 for ( snum=0; snum<n_services; snum++ )
1361 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1364 NT_PRINTER_INFO_LEVEL *printer = NULL;
1366 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1367 if ( !W_ERROR_IS_OK(result) )
1371 * if the printer is bound to the driver,
1372 * then reset to the new driver initdata
1375 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1377 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1379 if ( !set_driver_init(printer, 2) ) {
1380 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1381 printer->info_2->printername, printer->info_2->drivername));
1384 result = mod_a_printer( printer, 2 );
1385 if ( !W_ERROR_IS_OK(result) ) {
1386 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1387 get_dos_error_msg(result)));
1391 free_a_printer( &printer, 2 );
1400 /********************************************************************
1401 Copy routines used by convert_to_openprinterex()
1402 *******************************************************************/
1404 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1412 DEBUG (8,("dup_devmode\n"));
1414 /* bulk copy first */
1416 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1420 /* dup the pointer members separately */
1422 len = unistrlen(devmode->devicename.buffer);
1424 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1425 if (!d->devicename.buffer) {
1428 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1433 len = unistrlen(devmode->formname.buffer);
1435 d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
1436 if (!d->formname.buffer) {
1439 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1443 if (devmode->driverextra) {
1444 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1445 devmode->driverextra);
1446 if (!d->dev_private) {
1450 d->dev_private = NULL;
1455 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1457 if (!new_ctr || !ctr)
1460 DEBUG(8,("copy_devmode_ctr\n"));
1462 new_ctr->size = ctr->size;
1463 new_ctr->devmode_ptr = ctr->devmode_ptr;
1465 if(ctr->devmode_ptr)
1466 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1469 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1471 if (!new_def || !def)
1474 DEBUG(8,("copy_printer_defaults\n"));
1476 new_def->datatype_ptr = def->datatype_ptr;
1478 if (def->datatype_ptr)
1479 copy_unistr2(&new_def->datatype, &def->datatype);
1481 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1483 new_def->access_required = def->access_required;
1486 /********************************************************************
1487 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1488 * SPOOL_Q_OPEN_PRINTER_EX structure
1489 ********************************************************************/
1491 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1493 if (!q_u_ex || !q_u)
1496 DEBUG(8,("convert_to_openprinterex\n"));
1498 if ( q_u->printername ) {
1499 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1500 if (q_u_ex->printername == NULL)
1502 copy_unistr2(q_u_ex->printername, q_u->printername);
1505 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1510 /********************************************************************
1511 * spoolss_open_printer
1513 * called from the spoolss dispatcher
1514 ********************************************************************/
1516 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1518 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1519 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1524 ZERO_STRUCT(q_u_ex);
1525 ZERO_STRUCT(r_u_ex);
1527 /* convert the OpenPrinter() call to OpenPrinterEx() */
1529 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1530 if (!W_ERROR_IS_OK(r_u_ex.status))
1531 return r_u_ex.status;
1533 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1535 /* convert back to OpenPrinter() */
1537 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1539 if (W_ERROR_EQUAL(r_u->status, WERR_INVALID_PARAM)) {
1540 /* OpenPrinterEx returns this for a bad
1541 * printer name. We must return WERR_INVALID_PRINTER_NAME
1544 r_u->status = WERR_INVALID_PRINTER_NAME;
1549 /********************************************************************
1550 ********************************************************************/
1552 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1554 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1555 POLICY_HND *handle = &r_u->handle;
1559 Printer_entry *Printer=NULL;
1561 if (!q_u->printername) {
1562 return WERR_INVALID_PARAM;
1565 /* some sanity check because you can open a printer or a print server */
1566 /* aka: \\server\printer or \\server */
1568 unistr2_to_ascii(name, q_u->printername, sizeof(name));
1570 DEBUGADD(3,("checking name: %s\n",name));
1572 if (!open_printer_hnd(p, handle, name, 0)) {
1573 return WERR_INVALID_PARAM;
1576 Printer=find_printer_index_by_hnd(p, handle);
1578 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1579 "handle we created for printer %s\n", name ));
1580 close_printer_handle(p,handle);
1581 return WERR_INVALID_PARAM;
1585 * First case: the user is opening the print server:
1587 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1588 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1590 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1591 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1592 * or if the user is listed in the smb.conf printer admin parameter.
1594 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1595 * client view printer folder, but does not show the MSAPW.
1597 * Note: this test needs code to check access rights here too. Jeremy
1598 * could you look at this?
1600 * Second case: the user is opening a printer:
1601 * NT doesn't let us connect to a printer if the connecting user
1602 * doesn't have print permission.
1604 * Third case: user is opening a Port Monitor
1605 * access checks same as opening a handle to the print server.
1608 switch (Printer->printer_type )
1611 case SPLHND_PORTMON_TCP:
1612 case SPLHND_PORTMON_LOCAL:
1613 /* Printserver handles use global struct... */
1617 /* Map standard access rights to object specific access rights */
1619 se_map_standard(&printer_default->access_required,
1620 &printserver_std_mapping);
1622 /* Deny any object specific bits that don't apply to print
1623 servers (i.e printer and job specific bits) */
1625 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1627 if (printer_default->access_required &
1628 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1629 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1630 close_printer_handle(p, handle);
1631 return WERR_ACCESS_DENIED;
1634 /* Allow admin access */
1636 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1638 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1640 if (!lp_ms_add_printer_wizard()) {
1641 close_printer_handle(p, handle);
1642 return WERR_ACCESS_DENIED;
1645 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1646 and not a printer admin, then fail */
1648 if ((p->pipe_user.ut.uid != 0) &&
1649 !user_has_privileges(p->pipe_user.nt_user_token,
1651 !token_contains_name_in_list(
1652 uidtoname(p->pipe_user.ut.uid), NULL,
1653 p->pipe_user.nt_user_token,
1654 lp_printer_admin(snum))) {
1655 close_printer_handle(p, handle);
1656 return WERR_ACCESS_DENIED;
1659 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1663 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1666 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1667 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1669 /* We fall through to return WERR_OK */
1672 case SPLHND_PRINTER:
1673 /* NT doesn't let us connect to a printer if the connecting user
1674 doesn't have print permission. */
1676 if (!get_printer_snum(p, handle, &snum, NULL)) {
1677 close_printer_handle(p, handle);
1681 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1683 /* map an empty access mask to the minimum access mask */
1684 if (printer_default->access_required == 0x0)
1685 printer_default->access_required = PRINTER_ACCESS_USE;
1688 * If we are not serving the printer driver for this printer,
1689 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1690 * will keep NT clients happy --jerry
1693 if (lp_use_client_driver(snum)
1694 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1696 printer_default->access_required = PRINTER_ACCESS_USE;
1699 /* check smb.conf parameters and the the sec_desc */
1701 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1702 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1703 return WERR_ACCESS_DENIED;
1706 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1707 p->pipe_user.nt_user_token, snum) ||
1708 !print_access_check(&p->pipe_user, snum,
1709 printer_default->access_required)) {
1710 DEBUG(3, ("access DENIED for printer open\n"));
1711 close_printer_handle(p, handle);
1712 return WERR_ACCESS_DENIED;
1715 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1716 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1717 close_printer_handle(p, handle);
1718 return WERR_ACCESS_DENIED;
1721 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1722 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1724 printer_default->access_required = PRINTER_ACCESS_USE;
1726 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1727 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1732 /* sanity check to prevent programmer error */
1736 Printer->access_granted = printer_default->access_required;
1739 * If the client sent a devmode in the OpenPrinter() call, then
1740 * save it here in case we get a job submission on this handle
1743 if ( (Printer->printer_type != SPLHND_SERVER)
1744 && q_u->printer_default.devmode_cont.devmode_ptr )
1746 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1747 &Printer->nt_devmode );
1750 #if 0 /* JERRY -- I'm doubtful this is really effective */
1751 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1752 optimization in Windows 2000 clients --jerry */
1754 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1755 && (RA_WIN2K == get_remote_arch()) )
1757 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1758 sys_usleep( 500000 );
1765 /****************************************************************************
1766 ****************************************************************************/
1768 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1769 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1775 /* allocate memory if needed. Messy because
1776 convert_printer_info is used to update an existing
1777 printer or build a new one */
1779 if ( !printer->info_2 ) {
1780 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1781 if ( !printer->info_2 ) {
1782 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1787 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1788 printer->info_2->setuptime = time(NULL);
1796 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1797 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1803 printer->info_3=NULL;
1804 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1808 printer->info_6=NULL;
1809 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1819 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1820 NT_DEVICEMODE **pp_nt_devmode)
1822 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1825 * Ensure nt_devmode is a valid pointer
1826 * as we will be overwriting it.
1829 if (nt_devmode == NULL) {
1830 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1831 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1835 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1836 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1838 nt_devmode->specversion=devmode->specversion;
1839 nt_devmode->driverversion=devmode->driverversion;
1840 nt_devmode->size=devmode->size;
1841 nt_devmode->fields=devmode->fields;
1842 nt_devmode->orientation=devmode->orientation;
1843 nt_devmode->papersize=devmode->papersize;
1844 nt_devmode->paperlength=devmode->paperlength;
1845 nt_devmode->paperwidth=devmode->paperwidth;
1846 nt_devmode->scale=devmode->scale;
1847 nt_devmode->copies=devmode->copies;
1848 nt_devmode->defaultsource=devmode->defaultsource;
1849 nt_devmode->printquality=devmode->printquality;
1850 nt_devmode->color=devmode->color;
1851 nt_devmode->duplex=devmode->duplex;
1852 nt_devmode->yresolution=devmode->yresolution;
1853 nt_devmode->ttoption=devmode->ttoption;
1854 nt_devmode->collate=devmode->collate;
1856 nt_devmode->logpixels=devmode->logpixels;
1857 nt_devmode->bitsperpel=devmode->bitsperpel;
1858 nt_devmode->pelswidth=devmode->pelswidth;
1859 nt_devmode->pelsheight=devmode->pelsheight;
1860 nt_devmode->displayflags=devmode->displayflags;
1861 nt_devmode->displayfrequency=devmode->displayfrequency;
1862 nt_devmode->icmmethod=devmode->icmmethod;
1863 nt_devmode->icmintent=devmode->icmintent;
1864 nt_devmode->mediatype=devmode->mediatype;
1865 nt_devmode->dithertype=devmode->dithertype;
1866 nt_devmode->reserved1=devmode->reserved1;
1867 nt_devmode->reserved2=devmode->reserved2;
1868 nt_devmode->panningwidth=devmode->panningwidth;
1869 nt_devmode->panningheight=devmode->panningheight;
1872 * Only change private and driverextra if the incoming devmode
1873 * has a new one. JRA.
1876 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1877 SAFE_FREE(nt_devmode->nt_dev_private);
1878 nt_devmode->driverextra=devmode->driverextra;
1879 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1881 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1884 *pp_nt_devmode = nt_devmode;
1889 /********************************************************************
1890 * _spoolss_enddocprinter_internal.
1891 ********************************************************************/
1893 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1895 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1899 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1903 if (!get_printer_snum(p, handle, &snum, NULL))
1906 Printer->document_started=False;
1907 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1908 /* error codes unhandled so far ... */
1913 /********************************************************************
1914 * api_spoolss_closeprinter
1915 ********************************************************************/
1917 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1919 POLICY_HND *handle = &q_u->handle;
1921 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1923 if (Printer && Printer->document_started)
1924 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1926 if (!close_printer_handle(p, handle))
1929 /* clear the returned printer handle. Observed behavior
1930 from Win2k server. Don't think this really matters.
1931 Previous code just copied the value of the closed
1934 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1939 /********************************************************************
1940 * api_spoolss_deleteprinter
1942 ********************************************************************/
1944 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1946 POLICY_HND *handle = &q_u->handle;
1947 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1950 if (Printer && Printer->document_started)
1951 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1953 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1955 result = delete_printer_handle(p, handle);
1957 update_c_setprinter(False);
1962 /*******************************************************************
1963 * static function to lookup the version id corresponding to an
1964 * long architecture string
1965 ******************************************************************/
1967 static int get_version_id (char * arch)
1970 struct table_node archi_table[]= {
1972 {"Windows 4.0", "WIN40", 0 },
1973 {"Windows NT x86", "W32X86", 2 },
1974 {"Windows NT R4000", "W32MIPS", 2 },
1975 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1976 {"Windows NT PowerPC", "W32PPC", 2 },
1977 {"Windows IA64", "IA64", 3 },
1978 {"Windows x64", "x64", 3 },
1982 for (i=0; archi_table[i].long_archi != NULL; i++)
1984 if (strcmp(arch, archi_table[i].long_archi) == 0)
1985 return (archi_table[i].version);
1991 /********************************************************************
1992 * _spoolss_deleteprinterdriver
1993 ********************************************************************/
1995 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1999 NT_PRINTER_DRIVER_INFO_LEVEL info;
2000 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2003 WERROR status_win2k = WERR_ACCESS_DENIED;
2004 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2006 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2007 and not a printer admin, then fail */
2009 if ( (p->pipe_user.ut.uid != 0)
2010 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2011 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2012 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2014 return WERR_ACCESS_DENIED;
2017 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2018 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2020 /* check that we have a valid driver name first */
2022 if ((version=get_version_id(arch)) == -1)
2023 return WERR_INVALID_ENVIRONMENT;
2026 ZERO_STRUCT(info_win2k);
2028 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2030 /* try for Win2k driver if "Windows NT x86" */
2032 if ( version == 2 ) {
2034 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2035 status = WERR_UNKNOWN_PRINTER_DRIVER;
2039 /* otherwise it was a failure */
2041 status = WERR_UNKNOWN_PRINTER_DRIVER;
2047 if (printer_driver_in_use(info.info_3)) {
2048 status = WERR_PRINTER_DRIVER_IN_USE;
2054 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2056 /* if we get to here, we now have 2 driver info structures to remove */
2057 /* remove the Win2k driver first*/
2059 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2060 free_a_printer_driver( info_win2k, 3 );
2062 /* this should not have failed---if it did, report to client */
2063 if ( !W_ERROR_IS_OK(status_win2k) )
2065 status = status_win2k;
2071 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2073 /* if at least one of the deletes succeeded return OK */
2075 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2079 free_a_printer_driver( info, 3 );
2084 /********************************************************************
2085 * spoolss_deleteprinterdriverex
2086 ********************************************************************/
2088 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2092 NT_PRINTER_DRIVER_INFO_LEVEL info;
2093 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2095 uint32 flags = q_u->delete_flags;
2098 WERROR status_win2k = WERR_ACCESS_DENIED;
2099 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2101 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2102 and not a printer admin, then fail */
2104 if ( (p->pipe_user.ut.uid != 0)
2105 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2106 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2107 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2109 return WERR_ACCESS_DENIED;
2112 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2113 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2115 /* check that we have a valid driver name first */
2116 if ((version=get_version_id(arch)) == -1) {
2117 /* this is what NT returns */
2118 return WERR_INVALID_ENVIRONMENT;
2121 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2122 version = q_u->version;
2125 ZERO_STRUCT(info_win2k);
2127 status = get_a_printer_driver(&info, 3, driver, arch, version);
2129 if ( !W_ERROR_IS_OK(status) )
2132 * if the client asked for a specific version,
2133 * or this is something other than Windows NT x86,
2137 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2140 /* try for Win2k driver if "Windows NT x86" */
2143 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2144 status = WERR_UNKNOWN_PRINTER_DRIVER;
2149 if ( printer_driver_in_use(info.info_3) ) {
2150 status = WERR_PRINTER_DRIVER_IN_USE;
2155 * we have a couple of cases to consider.
2156 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2157 * then the delete should fail if **any** files overlap with
2159 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2160 * non-overlapping files
2161 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2162 * is set, the do not delete any files
2163 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2166 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2168 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2170 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2171 /* no idea of the correct error here */
2172 status = WERR_ACCESS_DENIED;
2177 /* also check for W32X86/3 if necessary; maybe we already have? */
2179 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2180 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2183 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2184 /* no idea of the correct error here */
2185 free_a_printer_driver( info_win2k, 3 );
2186 status = WERR_ACCESS_DENIED;
2190 /* if we get to here, we now have 2 driver info structures to remove */
2191 /* remove the Win2k driver first*/
2193 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2194 free_a_printer_driver( info_win2k, 3 );
2196 /* this should not have failed---if it did, report to client */
2198 if ( !W_ERROR_IS_OK(status_win2k) )
2203 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2205 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2208 free_a_printer_driver( info, 3 );
2214 /****************************************************************************
2215 Internal routine for retreiving printerdata
2216 ***************************************************************************/
2218 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2219 const char *key, const char *value, uint32 *type, uint8 **data,
2220 uint32 *needed, uint32 in_size )
2222 REGISTRY_VALUE *val;
2226 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2227 return WERR_BADFILE;
2229 *type = regval_type( val );
2231 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2233 size = regval_size( val );
2235 /* copy the min(in_size, len) */
2238 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2240 /* special case for 0 length values */
2242 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2246 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2255 DEBUG(5,("get_printer_dataex: copy done\n"));
2260 /****************************************************************************
2261 Internal routine for removing printerdata
2262 ***************************************************************************/
2264 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2266 return delete_printer_data( printer->info_2, key, value );
2269 /****************************************************************************
2270 Internal routine for storing printerdata
2271 ***************************************************************************/
2273 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2274 uint32 type, uint8 *data, int real_len )
2276 /* the registry objects enforce uniqueness based on value name */
2278 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2281 /********************************************************************
2282 GetPrinterData on a printer server Handle.
2283 ********************************************************************/
2285 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2289 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2291 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2293 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2295 SIVAL(*data, 0, 0x00);
2300 if (!StrCaseCmp(value, "BeepEnabled")) {
2302 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2304 SIVAL(*data, 0, 0x00);
2309 if (!StrCaseCmp(value, "EventLog")) {
2311 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2313 /* formally was 0x1b */
2314 SIVAL(*data, 0, 0x0);
2319 if (!StrCaseCmp(value, "NetPopup")) {
2321 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2323 SIVAL(*data, 0, 0x00);
2328 if (!StrCaseCmp(value, "MajorVersion")) {
2330 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2333 /* Windows NT 4.0 seems to not allow uploading of drivers
2334 to a server that reports 0x3 as the MajorVersion.
2335 need to investigate more how Win2k gets around this .
2338 if ( RA_WINNT == get_remote_arch() )
2347 if (!StrCaseCmp(value, "MinorVersion")) {
2349 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2357 * uint32 size = 0x114
2359 * uint32 minor = [0|1]
2360 * uint32 build = [2195|2600]
2361 * extra unicode string = e.g. "Service Pack 3"
2363 if (!StrCaseCmp(value, "OSVersion")) {
2367 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2370 SIVAL(*data, 0, *needed); /* size */
2371 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2373 SIVAL(*data, 12, 2195); /* build */
2375 /* leave extra string empty */
2381 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2382 const char *string="C:\\PRINTERS";
2384 *needed = 2*(strlen(string)+1);
2385 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2387 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2389 /* it's done by hand ready to go on the wire */
2390 for (i=0; i<strlen(string); i++) {
2391 (*data)[2*i]=string[i];
2392 (*data)[2*i+1]='\0';
2397 if (!StrCaseCmp(value, "Architecture")) {
2398 const char *string="Windows NT x86";
2400 *needed = 2*(strlen(string)+1);
2401 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2403 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2404 for (i=0; i<strlen(string); i++) {
2405 (*data)[2*i]=string[i];
2406 (*data)[2*i+1]='\0';
2411 if (!StrCaseCmp(value, "DsPresent")) {
2413 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2416 /* only show the publish check box if we are a
2417 memeber of a AD domain */
2419 if ( lp_security() == SEC_ADS )
2420 SIVAL(*data, 0, 0x01);
2422 SIVAL(*data, 0, 0x00);
2428 if (!StrCaseCmp(value, "DNSMachineName")) {
2429 const char *hostname = get_mydnsfullname();
2432 return WERR_BADFILE;
2434 *needed = 2*(strlen(hostname)+1);
2435 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2437 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2438 for (i=0; i<strlen(hostname); i++) {
2439 (*data)[2*i]=hostname[i];
2440 (*data)[2*i+1]='\0';
2446 return WERR_BADFILE;
2449 /********************************************************************
2450 * spoolss_getprinterdata
2451 ********************************************************************/
2453 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2455 POLICY_HND *handle = &q_u->handle;
2456 UNISTR2 *valuename = &q_u->valuename;
2457 uint32 in_size = q_u->size;
2458 uint32 *type = &r_u->type;
2459 uint32 *out_size = &r_u->size;
2460 uint8 **data = &r_u->data;
2461 uint32 *needed = &r_u->needed;
2464 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2465 NT_PRINTER_INFO_LEVEL *printer = NULL;
2469 * Reminder: when it's a string, the length is in BYTES
2470 * even if UNICODE is negociated.
2475 *out_size = in_size;
2477 /* in case of problem, return some default values */
2482 DEBUG(4,("_spoolss_getprinterdata\n"));
2485 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2486 status = WERR_BADFID;
2490 unistr2_to_ascii(value, valuename, sizeof(value));
2492 if ( Printer->printer_type == SPLHND_SERVER )
2493 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2496 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2497 status = WERR_BADFID;
2501 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2502 if ( !W_ERROR_IS_OK(status) )
2505 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2507 if ( strequal(value, "ChangeId") ) {
2509 *needed = sizeof(uint32);
2510 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2511 status = WERR_NOMEM;
2514 SIVAL( *data, 0, printer->info_2->changeid );
2518 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2521 if (*needed > *out_size)
2522 status = WERR_MORE_DATA;
2525 if ( !W_ERROR_IS_OK(status) )
2527 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2529 /* reply this param doesn't exist */
2532 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2534 free_a_printer( &printer, 2 );
2542 /* cleanup & exit */
2545 free_a_printer( &printer, 2 );
2550 /*********************************************************
2551 Connect to the client machine.
2552 **********************************************************/
2554 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2555 struct sockaddr_storage *client_ss, const char *remote_machine)
2558 struct cli_state *the_cli;
2559 struct sockaddr_storage rm_addr;
2561 if ( is_zero_addr(client_ss) ) {
2562 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2563 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2567 if (ismyaddr(&rm_addr)) {
2568 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2572 char addr[INET6_ADDRSTRLEN];
2573 rm_addr = *client_ss;
2574 print_sockaddr(addr, sizeof(addr), &rm_addr);
2575 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2579 /* setup the connection */
2581 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2582 &rm_addr, 0, "IPC$", "IPC",
2586 0, lp_client_signing(), NULL );
2588 if ( !NT_STATUS_IS_OK( ret ) ) {
2589 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2594 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2595 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2596 cli_shutdown(the_cli);
2601 * Ok - we have an anonymous connection to the IPC$ share.
2602 * Now start the NT Domain stuff :-).
2605 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2606 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2607 remote_machine, nt_errstr(ret)));
2608 cli_shutdown(the_cli);
2615 /***************************************************************************
2616 Connect to the client.
2617 ****************************************************************************/
2619 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2620 uint32 localprinter, uint32 type,
2621 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2626 * If it's the first connection, contact the client
2627 * and connect to the IPC$ share anonymously
2629 if (smb_connections==0) {
2630 fstring unix_printer;
2632 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2634 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2637 messaging_register(smbd_messaging_context(), NULL,
2638 MSG_PRINTER_NOTIFY2,
2639 receive_notify2_message_list);
2640 /* Tell the connections db we're now interested in printer
2641 * notify messages. */
2642 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2646 * Tell the specific printing tdb we want messages for this printer
2647 * by registering our PID.
2650 if (!print_notify_register_pid(snum))
2651 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2655 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe,
2662 if (!W_ERROR_IS_OK(result))
2663 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2664 dos_errstr(result)));
2666 return (W_ERROR_IS_OK(result));
2669 /********************************************************************
2671 * ReplyFindFirstPrinterChangeNotifyEx
2673 * before replying OK: status=0 a rpc call is made to the workstation
2674 * asking ReplyOpenPrinter
2676 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2677 * called from api_spoolss_rffpcnex
2678 ********************************************************************/
2680 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2682 POLICY_HND *handle = &q_u->handle;
2683 uint32 flags = q_u->flags;
2684 uint32 options = q_u->options;
2685 UNISTR2 *localmachine = &q_u->localmachine;
2686 uint32 printerlocal = q_u->printerlocal;
2688 SPOOL_NOTIFY_OPTION *option = q_u->option;
2689 struct sockaddr_storage client_ss;
2691 /* store the notify value in the printer struct */
2693 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2696 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2700 Printer->notify.flags=flags;
2701 Printer->notify.options=options;
2702 Printer->notify.printerlocal=printerlocal;
2704 if (Printer->notify.option)
2705 free_spool_notify_option(&Printer->notify.option);
2707 Printer->notify.option=dup_spool_notify_option(option);
2709 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2710 sizeof(Printer->notify.localmachine));
2712 /* Connect to the client machine and send a ReplyOpenPrinter */
2714 if ( Printer->printer_type == SPLHND_SERVER)
2716 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2717 !get_printer_snum(p, handle, &snum, NULL) )
2720 if (!interpret_string_addr(&client_ss,
2721 p->conn->client_address,
2723 return WERR_SERVER_UNAVAILABLE;
2726 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2727 Printer->notify.printerlocal, 1,
2728 &Printer->notify.client_hnd, &client_ss))
2729 return WERR_SERVER_UNAVAILABLE;
2731 Printer->notify.client_connected=True;
2736 /*******************************************************************
2737 * fill a notify_info_data with the servername
2738 ********************************************************************/
2740 void spoolss_notify_server_name(int snum,
2741 SPOOL_NOTIFY_INFO_DATA *data,
2742 print_queue_struct *queue,
2743 NT_PRINTER_INFO_LEVEL *printer,
2744 TALLOC_CTX *mem_ctx)
2746 smb_ucs2_t *temp = NULL;
2749 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2750 if (len == (uint32)-1) {
2754 data->notify_data.data.length = len;
2756 data->notify_data.data.string = (uint16 *)temp;
2758 data->notify_data.data.string = NULL;
2762 /*******************************************************************
2763 * fill a notify_info_data with the printername (not including the servername).
2764 ********************************************************************/
2766 void spoolss_notify_printer_name(int snum,
2767 SPOOL_NOTIFY_INFO_DATA *data,
2768 print_queue_struct *queue,
2769 NT_PRINTER_INFO_LEVEL *printer,
2770 TALLOC_CTX *mem_ctx)
2772 smb_ucs2_t *temp = NULL;
2775 /* the notify name should not contain the \\server\ part */
2776 char *p = strrchr(printer->info_2->printername, '\\');
2779 p = printer->info_2->printername;
2784 len = rpcstr_push_talloc(mem_ctx, &temp, p);
2785 if (len == (uint32)-1) {
2789 data->notify_data.data.length = len;
2791 data->notify_data.data.string = (uint16 *)temp;
2793 data->notify_data.data.string = NULL;
2797 /*******************************************************************
2798 * fill a notify_info_data with the servicename
2799 ********************************************************************/
2801 void spoolss_notify_share_name(int snum,
2802 SPOOL_NOTIFY_INFO_DATA *data,
2803 print_queue_struct *queue,
2804 NT_PRINTER_INFO_LEVEL *printer,
2805 TALLOC_CTX *mem_ctx)
2807 smb_ucs2_t *temp = NULL;
2810 len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2811 if (len == (uint32)-1) {
2815 data->notify_data.data.length = len;
2817 data->notify_data.data.string = (uint16 *)temp;
2819 data->notify_data.data.string = NULL;
2824 /*******************************************************************
2825 * fill a notify_info_data with the port name
2826 ********************************************************************/
2828 void spoolss_notify_port_name(int snum,
2829 SPOOL_NOTIFY_INFO_DATA *data,
2830 print_queue_struct *queue,
2831 NT_PRINTER_INFO_LEVEL *printer,
2832 TALLOC_CTX *mem_ctx)
2834 smb_ucs2_t *temp = NULL;
2837 /* even if it's strange, that's consistant in all the code */
2839 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2840 if (len == (uint32)-1) {
2844 data->notify_data.data.length = len;
2846 data->notify_data.data.string = (uint16 *)temp;
2848 data->notify_data.data.string = NULL;
2852 /*******************************************************************
2853 * fill a notify_info_data with the printername
2854 * but it doesn't exist, have to see what to do
2855 ********************************************************************/
2857 void spoolss_notify_driver_name(int snum,
2858 SPOOL_NOTIFY_INFO_DATA *data,
2859 print_queue_struct *queue,
2860 NT_PRINTER_INFO_LEVEL *printer,
2861 TALLOC_CTX *mem_ctx)
2863 smb_ucs2_t *temp = NULL;
2866 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2867 if (len == (uint32)-1) {
2871 data->notify_data.data.length = len;
2873 data->notify_data.data.string = (uint16 *)temp;
2875 data->notify_data.data.string = NULL;
2879 /*******************************************************************
2880 * fill a notify_info_data with the comment
2881 ********************************************************************/
2883 void spoolss_notify_comment(int snum,
2884 SPOOL_NOTIFY_INFO_DATA *data,
2885 print_queue_struct *queue,
2886 NT_PRINTER_INFO_LEVEL *printer,
2887 TALLOC_CTX *mem_ctx)
2889 smb_ucs2_t *temp = NULL;
2892 if (*printer->info_2->comment == '\0')
2893 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2895 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2897 if (len == (uint32)-1) {
2900 data->notify_data.data.length = len;
2902 data->notify_data.data.string = (uint16 *)temp;
2904 data->notify_data.data.string = NULL;
2908 /*******************************************************************
2909 * fill a notify_info_data with the comment
2910 * location = "Room 1, floor 2, building 3"
2911 ********************************************************************/
2913 void spoolss_notify_location(int snum,
2914 SPOOL_NOTIFY_INFO_DATA *data,
2915 print_queue_struct *queue,
2916 NT_PRINTER_INFO_LEVEL *printer,
2917 TALLOC_CTX *mem_ctx)
2919 smb_ucs2_t *temp = NULL;
2922 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2923 if (len == (uint32)-1) {
2927 data->notify_data.data.length = len;
2929 data->notify_data.data.string = (uint16 *)temp;
2931 data->notify_data.data.string = NULL;
2935 /*******************************************************************
2936 * fill a notify_info_data with the device mode
2937 * jfm:xxxx don't to it for know but that's a real problem !!!
2938 ********************************************************************/
2940 static void spoolss_notify_devmode(int snum,
2941 SPOOL_NOTIFY_INFO_DATA *data,
2942 print_queue_struct *queue,
2943 NT_PRINTER_INFO_LEVEL *printer,
2944 TALLOC_CTX *mem_ctx)
2946 /* for a dummy implementation we have to zero the fields */
2947 data->notify_data.data.length = 0;
2948 data->notify_data.data.string = NULL;
2951 /*******************************************************************
2952 * fill a notify_info_data with the separator file name
2953 ********************************************************************/
2955 void spoolss_notify_sepfile(int snum,
2956 SPOOL_NOTIFY_INFO_DATA *data,
2957 print_queue_struct *queue,
2958 NT_PRINTER_INFO_LEVEL *printer,
2959 TALLOC_CTX *mem_ctx)
2961 smb_ucs2_t *temp = NULL;
2964 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2965 if (len == (uint32)-1) {
2969 data->notify_data.data.length = len;
2971 data->notify_data.data.string = (uint16 *)temp;
2973 data->notify_data.data.string = NULL;
2977 /*******************************************************************
2978 * fill a notify_info_data with the print processor
2979 * jfm:xxxx return always winprint to indicate we don't do anything to it
2980 ********************************************************************/
2982 void spoolss_notify_print_processor(int snum,
2983 SPOOL_NOTIFY_INFO_DATA *data,
2984 print_queue_struct *queue,
2985 NT_PRINTER_INFO_LEVEL *printer,
2986 TALLOC_CTX *mem_ctx)
2988 smb_ucs2_t *temp = NULL;
2991 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
2992 if (len == (uint32)-1) {
2996 data->notify_data.data.length = len;
2998 data->notify_data.data.string = (uint16 *)temp;
3000 data->notify_data.data.string = NULL;
3004 /*******************************************************************
3005 * fill a notify_info_data with the print processor options
3006 * jfm:xxxx send an empty string
3007 ********************************************************************/
3009 void spoolss_notify_parameters(int snum,
3010 SPOOL_NOTIFY_INFO_DATA *data,
3011 print_queue_struct *queue,
3012 NT_PRINTER_INFO_LEVEL *printer,
3013 TALLOC_CTX *mem_ctx)
3015 smb_ucs2_t *temp = NULL;
3018 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3019 if (len == (uint32)-1) {
3023 data->notify_data.data.length = len;
3025 data->notify_data.data.string = (uint16 *)temp;
3027 data->notify_data.data.string = NULL;
3031 /*******************************************************************
3032 * fill a notify_info_data with the data type
3033 * jfm:xxxx always send RAW as data type
3034 ********************************************************************/
3036 void spoolss_notify_datatype(int snum,
3037 SPOOL_NOTIFY_INFO_DATA *data,
3038 print_queue_struct *queue,
3039 NT_PRINTER_INFO_LEVEL *printer,
3040 TALLOC_CTX *mem_ctx)
3042 smb_ucs2_t *temp = NULL;
3045 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3046 if (len == (uint32)-1) {
3050 data->notify_data.data.length = len;
3052 data->notify_data.data.string = (uint16 *)temp;
3054 data->notify_data.data.string = NULL;
3058 /*******************************************************************
3059 * fill a notify_info_data with the security descriptor
3060 * jfm:xxxx send an null pointer to say no security desc
3061 * have to implement security before !
3062 ********************************************************************/
3064 static void spoolss_notify_security_desc(int snum,
3065 SPOOL_NOTIFY_INFO_DATA *data,
3066 print_queue_struct *queue,
3067 NT_PRINTER_INFO_LEVEL *printer,
3068 TALLOC_CTX *mem_ctx)
3070 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3071 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3074 /*******************************************************************
3075 * fill a notify_info_data with the attributes
3076 * jfm:xxxx a samba printer is always shared
3077 ********************************************************************/
3079 void spoolss_notify_attributes(int snum,
3080 SPOOL_NOTIFY_INFO_DATA *data,
3081 print_queue_struct *queue,
3082 NT_PRINTER_INFO_LEVEL *printer,
3083 TALLOC_CTX *mem_ctx)
3085 data->notify_data.value[0] = printer->info_2->attributes;
3086 data->notify_data.value[1] = 0;
3089 /*******************************************************************
3090 * fill a notify_info_data with the priority
3091 ********************************************************************/
3093 static void spoolss_notify_priority(int snum,
3094 SPOOL_NOTIFY_INFO_DATA *data,
3095 print_queue_struct *queue,
3096 NT_PRINTER_INFO_LEVEL *printer,
3097 TALLOC_CTX *mem_ctx)
3099 data->notify_data.value[0] = printer->info_2->priority;
3100 data->notify_data.value[1] = 0;
3103 /*******************************************************************
3104 * fill a notify_info_data with the default priority
3105 ********************************************************************/
3107 static void spoolss_notify_default_priority(int snum,
3108 SPOOL_NOTIFY_INFO_DATA *data,
3109 print_queue_struct *queue,
3110 NT_PRINTER_INFO_LEVEL *printer,
3111 TALLOC_CTX *mem_ctx)
3113 data->notify_data.value[0] = printer->info_2->default_priority;
3114 data->notify_data.value[1] = 0;
3117 /*******************************************************************
3118 * fill a notify_info_data with the start time
3119 ********************************************************************/
3121 static void spoolss_notify_start_time(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3127 data->notify_data.value[0] = printer->info_2->starttime;
3128 data->notify_data.value[1] = 0;
3131 /*******************************************************************
3132 * fill a notify_info_data with the until time
3133 ********************************************************************/
3135 static void spoolss_notify_until_time(int snum,
3136 SPOOL_NOTIFY_INFO_DATA *data,
3137 print_queue_struct *queue,
3138 NT_PRINTER_INFO_LEVEL *printer,
3139 TALLOC_CTX *mem_ctx)
3141 data->notify_data.value[0] = printer->info_2->untiltime;
3142 data->notify_data.value[1] = 0;
3145 /*******************************************************************
3146 * fill a notify_info_data with the status
3147 ********************************************************************/
3149 static void spoolss_notify_status(int snum,
3150 SPOOL_NOTIFY_INFO_DATA *data,
3151 print_queue_struct *queue,
3152 NT_PRINTER_INFO_LEVEL *printer,
3153 TALLOC_CTX *mem_ctx)
3155 print_status_struct status;
3157 print_queue_length(snum, &status);
3158 data->notify_data.value[0]=(uint32) status.status;
3159 data->notify_data.value[1] = 0;
3162 /*******************************************************************
3163 * fill a notify_info_data with the number of jobs queued
3164 ********************************************************************/
3166 void spoolss_notify_cjobs(int snum,
3167 SPOOL_NOTIFY_INFO_DATA *data,
3168 print_queue_struct *queue,
3169 NT_PRINTER_INFO_LEVEL *printer,
3170 TALLOC_CTX *mem_ctx)
3172 data->notify_data.value[0] = print_queue_length(snum, NULL);
3173 data->notify_data.value[1] = 0;
3176 /*******************************************************************
3177 * fill a notify_info_data with the average ppm
3178 ********************************************************************/
3180 static void spoolss_notify_average_ppm(int snum,
3181 SPOOL_NOTIFY_INFO_DATA *data,
3182 print_queue_struct *queue,
3183 NT_PRINTER_INFO_LEVEL *printer,
3184 TALLOC_CTX *mem_ctx)
3186 /* always respond 8 pages per minutes */
3187 /* a little hard ! */
3188 data->notify_data.value[0] = printer->info_2->averageppm;
3189 data->notify_data.value[1] = 0;
3192 /*******************************************************************
3193 * fill a notify_info_data with username
3194 ********************************************************************/
3196 static void spoolss_notify_username(int snum,
3197 SPOOL_NOTIFY_INFO_DATA *data,
3198 print_queue_struct *queue,
3199 NT_PRINTER_INFO_LEVEL *printer,
3200 TALLOC_CTX *mem_ctx)
3202 smb_ucs2_t *temp = NULL;
3205 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3206 if (len == (uint32)-1) {
3210 data->notify_data.data.length = len;
3212 data->notify_data.data.string = (uint16 *)temp;
3214 data->notify_data.data.string = NULL;
3218 /*******************************************************************
3219 * fill a notify_info_data with job status
3220 ********************************************************************/
3222 static void spoolss_notify_job_status(int snum,
3223 SPOOL_NOTIFY_INFO_DATA *data,
3224 print_queue_struct *queue,
3225 NT_PRINTER_INFO_LEVEL *printer,
3226 TALLOC_CTX *mem_ctx)
3228 data->notify_data.value[0]=nt_printj_status(queue->status);
3229 data->notify_data.value[1] = 0;
3232 /*******************************************************************
3233 * fill a notify_info_data with job name
3234 ********************************************************************/
3236 static void spoolss_notify_job_name(int snum,
3237 SPOOL_NOTIFY_INFO_DATA *data,
3238 print_queue_struct *queue,
3239 NT_PRINTER_INFO_LEVEL *printer,
3240 TALLOC_CTX *mem_ctx)
3242 smb_ucs2_t *temp = NULL;
3245 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3246 if (len == (uint32)-1) {
3250 data->notify_data.data.length = len;
3252 data->notify_data.data.string = (uint16 *)temp;
3254 data->notify_data.data.string = NULL;
3258 /*******************************************************************
3259 * fill a notify_info_data with job status
3260 ********************************************************************/
3262 static void spoolss_notify_job_status_string(int snum,
3263 SPOOL_NOTIFY_INFO_DATA *data,
3264 print_queue_struct *queue,
3265 NT_PRINTER_INFO_LEVEL *printer,
3266 TALLOC_CTX *mem_ctx)
3269 * Now we're returning job status codes we just return a "" here. JRA.
3273 smb_ucs2_t *temp = NULL;
3276 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3279 switch (queue->status) {
3284 p = ""; /* NT provides the paused string */
3293 #endif /* NO LONGER NEEDED. */
3295 len = rpcstr_push_talloc(mem_ctx, &temp, p);
3296 if (len == (uint32)-1) {
3300 data->notify_data.data.length = len;
3302 data->notify_data.data.string = (uint16 *)temp;
3304 data->notify_data.data.string = NULL;
3308 /*******************************************************************
3309 * fill a notify_info_data with job time
3310 ********************************************************************/
3312 static void spoolss_notify_job_time(int snum,
3313 SPOOL_NOTIFY_INFO_DATA *data,
3314 print_queue_struct *queue,
3315 NT_PRINTER_INFO_LEVEL *printer,
3316 TALLOC_CTX *mem_ctx)
3318 data->notify_data.value[0]=0x0;
3319 data->notify_data.value[1]=0;
3322 /*******************************************************************
3323 * fill a notify_info_data with job size
3324 ********************************************************************/
3326 static void spoolss_notify_job_size(int snum,
3327 SPOOL_NOTIFY_INFO_DATA *data,
3328 print_queue_struct *queue,
3329 NT_PRINTER_INFO_LEVEL *printer,
3330 TALLOC_CTX *mem_ctx)
3332 data->notify_data.value[0]=queue->size;
3333 data->notify_data.value[1]=0;
3336 /*******************************************************************
3337 * fill a notify_info_data with page info
3338 ********************************************************************/
3339 static void spoolss_notify_total_pages(int snum,
3340 SPOOL_NOTIFY_INFO_DATA *data,
3341 print_queue_struct *queue,
3342 NT_PRINTER_INFO_LEVEL *printer,
3343 TALLOC_CTX *mem_ctx)
3345 data->notify_data.value[0]=queue->page_count;
3346 data->notify_data.value[1]=0;
3349 /*******************************************************************
3350 * fill a notify_info_data with pages printed info.
3351 ********************************************************************/
3352 static void spoolss_notify_pages_printed(int snum,
3353 SPOOL_NOTIFY_INFO_DATA *data,
3354 print_queue_struct *queue,
3355 NT_PRINTER_INFO_LEVEL *printer,
3356 TALLOC_CTX *mem_ctx)
3358 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3359 data->notify_data.value[1]=0;
3362 /*******************************************************************
3363 Fill a notify_info_data with job position.
3364 ********************************************************************/
3366 static void spoolss_notify_job_position(int snum,
3367 SPOOL_NOTIFY_INFO_DATA *data,
3368 print_queue_struct *queue,
3369 NT_PRINTER_INFO_LEVEL *printer,
3370 TALLOC_CTX *mem_ctx)
3372 data->notify_data.value[0]=queue->job;
3373 data->notify_data.value[1]=0;
3376 /*******************************************************************
3377 Fill a notify_info_data with submitted time.
3378 ********************************************************************/
3380 static void spoolss_notify_submitted_time(int snum,
3381 SPOOL_NOTIFY_INFO_DATA *data,
3382 print_queue_struct *queue,
3383 NT_PRINTER_INFO_LEVEL *printer,
3384 TALLOC_CTX *mem_ctx)
3391 t=gmtime(&queue->time);
3393 len = sizeof(SYSTEMTIME);
3395 data->notify_data.data.length = len;
3396 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3398 if (!data->notify_data.data.string) {
3399 data->notify_data.data.length = 0;
3403 make_systemtime(&st, t);
3406 * Systemtime must be linearized as a set of UINT16's.
3407 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3410 p = (char *)data->notify_data.data.string;
3411 SSVAL(p, 0, st.year);
3412 SSVAL(p, 2, st.month);
3413 SSVAL(p, 4, st.dayofweek);
3414 SSVAL(p, 6, st.day);
3415 SSVAL(p, 8, st.hour);
3416 SSVAL(p, 10, st.minute);
3417 SSVAL(p, 12, st.second);
3418 SSVAL(p, 14, st.milliseconds);
3421 struct s_notify_info_data_table
3427 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3428 print_queue_struct *queue,
3429 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3432 /* A table describing the various print notification constants and
3433 whether the notification data is a pointer to a variable sized
3434 buffer, a one value uint32 or a two value uint32. */
3436 static const struct s_notify_info_data_table notify_info_data_table[] =
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3487 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3490 /*******************************************************************
3491 Return the size of info_data structure.
3492 ********************************************************************/
3494 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3498 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3499 if ( (notify_info_data_table[i].type == type)
3500 && (notify_info_data_table[i].field == field) ) {
3501 switch(notify_info_data_table[i].size) {
3502 case NOTIFY_ONE_VALUE:
3503 case NOTIFY_TWO_VALUE:
3508 /* The only pointer notify data I have seen on
3509 the wire is the submitted time and this has
3510 the notify size set to 4. -tpot */
3512 case NOTIFY_POINTER:
3515 case NOTIFY_SECDESC:
3521 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3526 /*******************************************************************
3527 Return the type of notify_info_data.
3528 ********************************************************************/
3530 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3534 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3535 if (notify_info_data_table[i].type == type &&
3536 notify_info_data_table[i].field == field)
3537 return notify_info_data_table[i].size;
3543 /****************************************************************************
3544 ****************************************************************************/
3546 static bool search_notify(uint16 type, uint16 field, int *value)
3550 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3551 if (notify_info_data_table[i].type == type &&
3552 notify_info_data_table[i].field == field &&
3553 notify_info_data_table[i].fn != NULL) {
3562 /****************************************************************************
3563 ****************************************************************************/
3565 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3567 info_data->type = type;
3568 info_data->field = field;
3569 info_data->reserved = 0;
3571 info_data->size = size_of_notify_info_data(type, field);
3572 info_data->enc_type = type_of_notify_info_data(type, field);
3577 /*******************************************************************
3579 * fill a notify_info struct with info asked
3581 ********************************************************************/
3583 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3584 snum, SPOOL_NOTIFY_OPTION_TYPE
3585 *option_type, uint32 id,
3586 TALLOC_CTX *mem_ctx)
3592 SPOOL_NOTIFY_INFO_DATA *current_data;
3593 NT_PRINTER_INFO_LEVEL *printer = NULL;
3594 print_queue_struct *queue=NULL;
3596 type=option_type->type;
3598 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3599 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3600 option_type->count, lp_servicename(snum)));
3602 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3605 for(field_num=0; field_num<option_type->count; field_num++) {
3606 field = option_type->fields[field_num];
3608 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3610 if (!search_notify(type, field, &j) )
3613 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3614 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3615 free_a_printer(&printer, 2);
3619 current_data = &info->data[info->count];
3621 construct_info_data(current_data, type, field, id);
3623 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3624 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3626 notify_info_data_table[j].fn(snum, current_data, queue,
3632 free_a_printer(&printer, 2);
3636 /*******************************************************************
3638 * fill a notify_info struct with info asked
3640 ********************************************************************/
3642 static bool construct_notify_jobs_info(print_queue_struct *queue,
3643 SPOOL_NOTIFY_INFO *info,
3644 NT_PRINTER_INFO_LEVEL *printer,
3645 int snum, SPOOL_NOTIFY_OPTION_TYPE
3646 *option_type, uint32 id,
3647 TALLOC_CTX *mem_ctx)
3653 SPOOL_NOTIFY_INFO_DATA *current_data;
3655 DEBUG(4,("construct_notify_jobs_info\n"));
3657 type = option_type->type;
3659 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3660 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3661 option_type->count));
3663 for(field_num=0; field_num<option_type->count; field_num++) {
3664 field = option_type->fields[field_num];
3666 if (!search_notify(type, field, &j) )
3669 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3670 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3674 current_data=&(info->data[info->count]);
3676 construct_info_data(current_data, type, field, id);
3677 notify_info_data_table[j].fn(snum, current_data, queue,
3686 * JFM: The enumeration is not that simple, it's even non obvious.
3688 * let's take an example: I want to monitor the PRINTER SERVER for
3689 * the printer's name and the number of jobs currently queued.
3690 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3691 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3693 * I have 3 printers on the back of my server.
3695 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3698 * 1 printer 1 name 1
3699 * 2 printer 1 cjob 1
3700 * 3 printer 2 name 2
3701 * 4 printer 2 cjob 2
3702 * 5 printer 3 name 3
3703 * 6 printer 3 name 3
3705 * that's the print server case, the printer case is even worse.
3708 /*******************************************************************
3710 * enumerate all printers on the printserver
3711 * fill a notify_info struct with info asked
3713 ********************************************************************/
3715 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3716 SPOOL_NOTIFY_INFO *info,
3717 TALLOC_CTX *mem_ctx)
3720 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3721 int n_services=lp_numservices();
3723 SPOOL_NOTIFY_OPTION *option;
3724 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3726 DEBUG(4,("printserver_notify_info\n"));
3731 option=Printer->notify.option;
3736 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3737 sending a ffpcn() request first */
3742 for (i=0; i<option->count; i++) {
3743 option_type=&(option->ctr.type[i]);
3745 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3748 for (snum=0; snum<n_services; snum++)
3750 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3751 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3757 * Debugging information, don't delete.
3760 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3761 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3762 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3764 for (i=0; i<info->count; i++) {
3765 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3766 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3767 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3774 /*******************************************************************
3776 * fill a notify_info struct with info asked
3778 ********************************************************************/
3780 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3781 TALLOC_CTX *mem_ctx)
3784 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3787 SPOOL_NOTIFY_OPTION *option;
3788 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3790 print_queue_struct *queue=NULL;
3791 print_status_struct status;
3793 DEBUG(4,("printer_notify_info\n"));
3798 option=Printer->notify.option;
3804 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3805 sending a ffpcn() request first */
3810 get_printer_snum(p, hnd, &snum, NULL);
3812 for (i=0; i<option->count; i++) {
3813 option_type=&option->ctr.type[i];
3815 switch ( option_type->type ) {
3816 case PRINTER_NOTIFY_TYPE:
3817 if(construct_notify_printer_info(Printer, info, snum,
3823 case JOB_NOTIFY_TYPE: {
3824 NT_PRINTER_INFO_LEVEL *printer = NULL;
3826 count = print_queue_status(snum, &queue, &status);
3828 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3831 for (j=0; j<count; j++) {
3832 construct_notify_jobs_info(&queue[j], info,
3839 free_a_printer(&printer, 2);
3849 * Debugging information, don't delete.
3852 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3853 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3854 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3856 for (i=0; i<info->count; i++) {
3857 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3858 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3859 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3865 /********************************************************************
3867 ********************************************************************/
3869 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3871 POLICY_HND *handle = &q_u->handle;
3872 SPOOL_NOTIFY_INFO *info = &r_u->info;
3874 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3875 WERROR result = WERR_BADFID;
3877 /* we always have a NOTIFY_INFO struct */
3881 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3882 OUR_HANDLE(handle)));
3886 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3889 * We are now using the change value, and
3890 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3891 * I don't have a global notification system, I'm sending back all the
3892 * informations even when _NOTHING_ has changed.
3895 /* We need to keep track of the change value to send back in
3896 RRPCN replies otherwise our updates are ignored. */
3898 Printer->notify.fnpcn = True;
3900 if (Printer->notify.client_connected) {
3901 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3902 Printer->notify.change = q_u->change;
3905 /* just ignore the SPOOL_NOTIFY_OPTION */
3907 switch (Printer->printer_type) {
3909 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3912 case SPLHND_PRINTER:
3913 result = printer_notify_info(p, handle, info, p->mem_ctx);
3917 Printer->notify.fnpcn = False;
3923 /********************************************************************
3924 * construct_printer_info_0
3925 * fill a printer_info_0 struct
3926 ********************************************************************/
3928 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3930 char *chaine = NULL;
3932 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3933 counter_printer_0 *session_counter;
3934 uint32 global_counter;
3937 print_status_struct status;
3938 TALLOC_CTX *ctx = talloc_tos();
3940 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3943 init_unistr(&printer->printername, ntprinter->info_2->printername);
3945 chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3947 free_a_printer(&ntprinter,2);
3951 count = print_queue_length(snum, &status);
3953 /* check if we already have a counter for this printer */
3954 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3955 if (session_counter->snum == snum)
3959 init_unistr(&printer->servername, chaine);
3961 /* it's the first time, add it to the list */
3962 if (session_counter==NULL) {
3963 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3964 free_a_printer(&ntprinter, 2);
3967 ZERO_STRUCTP(session_counter);
3968 session_counter->snum=snum;
3969 session_counter->counter=0;
3970 DLIST_ADD(counter_list, session_counter);
3974 session_counter->counter++;
3977 * the global_counter should be stored in a TDB as it's common to all the clients
3978 * and should be zeroed on samba startup
3980 global_counter=session_counter->counter;
3981 printer->cjobs = count;
3982 printer->total_jobs = 0;
3983 printer->total_bytes = 0;
3985 setuptime = (time_t)ntprinter->info_2->setuptime;
3986 t=gmtime(&setuptime);
3988 printer->year = t->tm_year+1900;
3989 printer->month = t->tm_mon+1;
3990 printer->dayofweek = t->tm_wday;
3991 printer->day = t->tm_mday;
3992 printer->hour = t->tm_hour;
3993 printer->minute = t->tm_min;
3994 printer->second = t->tm_sec;
3995 printer->milliseconds = 0;
3997 printer->global_counter = global_counter;
3998 printer->total_pages = 0;
4000 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4001 printer->major_version = 0x0005; /* NT 5 */
4002 printer->build_version = 0x0893; /* build 2195 */
4004 printer->unknown7 = 0x1;
4005 printer->unknown8 = 0x0;
4006 printer->unknown9 = 0x0;
4007 printer->session_counter = session_counter->counter;
4008 printer->unknown11 = 0x0;
4009 printer->printer_errors = 0x0; /* number of print failure */
4010 printer->unknown13 = 0x0;
4011 printer->unknown14 = 0x1;
4012 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4013 printer->unknown16 = 0x0;
4014 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4015 printer->unknown18 = 0x0;
4016 printer->status = nt_printq_status(status.status);
4017 printer->unknown20 = 0x0;
4018 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4019 printer->unknown22 = 0x0;
4020 printer->unknown23 = 0x6; /* 6 ???*/
4021 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4022 printer->unknown25 = 0;
4023 printer->unknown26 = 0;
4024 printer->unknown27 = 0;
4025 printer->unknown28 = 0;
4026 printer->unknown29 = 0;
4028 free_a_printer(&ntprinter,2);
4032 /********************************************************************
4033 * construct_printer_info_1
4034 * fill a printer_info_1 struct
4035 ********************************************************************/
4036 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4038 char *chaine = NULL;
4039 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4040 TALLOC_CTX *ctx = talloc_tos();
4042 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4045 printer->flags=flags;
4047 if (*ntprinter->info_2->comment == '\0') {
4048 init_unistr(&printer->comment, lp_comment(snum));
4049 chaine = talloc_asprintf(ctx,
4050 "%s,%s,%s", ntprinter->info_2->printername,
4051 ntprinter->info_2->drivername, lp_comment(snum));
4054 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4055 chaine = talloc_asprintf(ctx,
4056 "%s,%s,%s", ntprinter->info_2->printername,
4057 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4061 free_a_printer(&ntprinter,2);
4065 init_unistr(&printer->description, chaine);
4066 init_unistr(&printer->name, ntprinter->info_2->printername);
4068 free_a_printer(&ntprinter,2);
4073 /****************************************************************************
4074 Free a DEVMODE struct.
4075 ****************************************************************************/
4077 static void free_dev_mode(DEVICEMODE *dev)
4082 SAFE_FREE(dev->dev_private);
4087 /****************************************************************************
4088 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4089 should be valid upon entry
4090 ****************************************************************************/
4092 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4094 if ( !devmode || !ntdevmode )
4097 init_unistr(&devmode->devicename, ntdevmode->devicename);
4099 init_unistr(&devmode->formname, ntdevmode->formname);
4101 devmode->specversion = ntdevmode->specversion;
4102 devmode->driverversion = ntdevmode->driverversion;
4103 devmode->size = ntdevmode->size;
4104 devmode->driverextra = ntdevmode->driverextra;
4105 devmode->fields = ntdevmode->fields;
4107 devmode->orientation = ntdevmode->orientation;
4108 devmode->papersize = ntdevmode->papersize;
4109 devmode->paperlength = ntdevmode->paperlength;
4110 devmode->paperwidth = ntdevmode->paperwidth;
4111 devmode->scale = ntdevmode->scale;
4112 devmode->copies = ntdevmode->copies;
4113 devmode->defaultsource = ntdevmode->defaultsource;
4114 devmode->printquality = ntdevmode->printquality;
4115 devmode->color = ntdevmode->color;
4116 devmode->duplex = ntdevmode->duplex;
4117 devmode->yresolution = ntdevmode->yresolution;
4118 devmode->ttoption = ntdevmode->ttoption;
4119 devmode->collate = ntdevmode->collate;
4120 devmode->icmmethod = ntdevmode->icmmethod;
4121 devmode->icmintent = ntdevmode->icmintent;
4122 devmode->mediatype = ntdevmode->mediatype;
4123 devmode->dithertype = ntdevmode->dithertype;
4125 if (ntdevmode->nt_dev_private != NULL) {
4126 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4133 /****************************************************************************
4134 Create a DEVMODE struct. Returns malloced memory.
4135 ****************************************************************************/
4137 DEVICEMODE *construct_dev_mode(const char *servicename)
4139 NT_PRINTER_INFO_LEVEL *printer = NULL;
4140 DEVICEMODE *devmode = NULL;
4142 DEBUG(7,("construct_dev_mode\n"));
4144 DEBUGADD(8,("getting printer characteristics\n"));
4146 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4149 if ( !printer->info_2->devmode ) {
4150 DEBUG(5, ("BONG! There was no device mode!\n"));
4154 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4155 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4159 ZERO_STRUCTP(devmode);
4161 DEBUGADD(8,("loading DEVICEMODE\n"));
4163 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4164 free_dev_mode( devmode );
4169 free_a_printer(&printer,2);
4174 /********************************************************************
4175 * construct_printer_info_2
4176 * fill a printer_info_2 struct
4177 ********************************************************************/
4179 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4182 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4184 print_status_struct status;
4186 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4189 count = print_queue_length(snum, &status);
4191 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4192 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4193 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4194 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4195 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4197 if (*ntprinter->info_2->comment == '\0')
4198 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4200 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4202 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4203 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4204 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4205 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4206 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4208 printer->attributes = ntprinter->info_2->attributes;
4210 printer->priority = ntprinter->info_2->priority; /* priority */
4211 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4212 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4213 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4214 printer->status = nt_printq_status(status.status); /* status */
4215 printer->cjobs = count; /* jobs */
4216 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4218 if ( !(printer->devmode = construct_dev_mode(
4219 lp_const_servicename(snum))) )
4220 DEBUG(8, ("Returning NULL Devicemode!\n"));
4222 printer->secdesc = NULL;
4224 if ( ntprinter->info_2->secdesc_buf
4225 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4227 /* don't use talloc_steal() here unless you do a deep steal of all
4228 the SEC_DESC members */
4230 printer->secdesc = dup_sec_desc( talloc_tos(),
4231 ntprinter->info_2->secdesc_buf->sd );
4234 free_a_printer(&ntprinter, 2);
4239 /********************************************************************
4240 * construct_printer_info_3
4241 * fill a printer_info_3 struct
4242 ********************************************************************/
4244 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4246 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4247 PRINTER_INFO_3 *printer = NULL;
4249 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4253 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4254 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4255 free_a_printer(&ntprinter, 2);
4259 ZERO_STRUCTP(printer);
4261 /* These are the components of the SD we are returning. */
4263 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4264 /* don't use talloc_steal() here unless you do a deep steal of all
4265 the SEC_DESC members */
4267 printer->secdesc = dup_sec_desc( talloc_tos(),
4268 ntprinter->info_2->secdesc_buf->sd );
4271 free_a_printer(&ntprinter, 2);
4273 *pp_printer = printer;
4277 /********************************************************************
4278 * construct_printer_info_4
4279 * fill a printer_info_4 struct
4280 ********************************************************************/
4282 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4284 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4286 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4289 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4290 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4291 printer->attributes = ntprinter->info_2->attributes;
4293 free_a_printer(&ntprinter, 2);
4297 /********************************************************************
4298 * construct_printer_info_5
4299 * fill a printer_info_5 struct
4300 ********************************************************************/
4302 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4304 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4306 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4309 init_unistr(&printer->printername, ntprinter->info_2->printername);
4310 init_unistr(&printer->portname, ntprinter->info_2->portname);
4311 printer->attributes = ntprinter->info_2->attributes;
4313 /* these two are not used by NT+ according to MSDN */
4315 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4316 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4318 free_a_printer(&ntprinter, 2);
4323 /********************************************************************
4324 * construct_printer_info_6
4325 * fill a printer_info_6 struct
4326 ********************************************************************/
4328 static bool construct_printer_info_6(Printer_entry *print_hnd,
4329 PRINTER_INFO_6 *printer,
4332 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4334 print_status_struct status;
4336 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4337 lp_const_servicename(snum))))
4340 count = print_queue_length(snum, &status);
4342 printer->status = nt_printq_status(status.status);
4344 free_a_printer(&ntprinter, 2);
4349 /********************************************************************
4350 * construct_printer_info_7
4351 * fill a printer_info_7 struct
4352 ********************************************************************/
4354 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4356 char *guid_str = NULL;
4359 if (is_printer_published(print_hnd, snum, &guid)) {
4360 asprintf(&guid_str, "{%s}",
4361 smb_uuid_string(talloc_tos(), guid));
4362 strupper_m(guid_str);
4363 init_unistr(&printer->guid, guid_str);
4364 printer->action = SPOOL_DS_PUBLISH;
4366 init_unistr(&printer->guid, "");
4367 printer->action = SPOOL_DS_UNPUBLISH;
4373 /********************************************************************
4374 Spoolss_enumprinters.
4375 ********************************************************************/
4377 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4381 int n_services=lp_numservices();
4382 PRINTER_INFO_1 *printers=NULL;
4383 PRINTER_INFO_1 current_prt;
4384 WERROR result = WERR_OK;
4386 DEBUG(4,("enum_all_printers_info_1\n"));
4388 for (snum=0; snum<n_services; snum++) {
4389 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4390 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4392 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4393 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4394 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4398 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4400 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4406 /* check the required size. */
4407 for (i=0; i<*returned; i++)
4408 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4410 if (*needed > offered) {
4411 result = WERR_INSUFFICIENT_BUFFER;
4415 if (!rpcbuf_alloc_size(buffer, *needed)) {
4416 result = WERR_NOMEM;
4420 /* fill the buffer with the structures */
4421 for (i=0; i<*returned; i++)
4422 smb_io_printer_info_1("", buffer, &printers[i], 0);
4427 SAFE_FREE(printers);
4429 if ( !W_ERROR_IS_OK(result) )
4435 /********************************************************************
4436 enum_all_printers_info_1_local.
4437 *********************************************************************/
4439 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4441 DEBUG(4,("enum_all_printers_info_1_local\n"));
4443 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4446 /********************************************************************
4447 enum_all_printers_info_1_name.
4448 *********************************************************************/
4450 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4454 DEBUG(4,("enum_all_printers_info_1_name\n"));
4456 if ((name[0] == '\\') && (name[1] == '\\'))
4459 if (is_myname_or_ipaddr(s)) {
4460 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4463 return WERR_INVALID_NAME;
4466 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4467 /********************************************************************
4468 enum_all_printers_info_1_remote.
4469 *********************************************************************/
4471 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4473 PRINTER_INFO_1 *printer;
4474 fstring printername;
4477 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4478 WERROR result = WERR_OK;
4480 /* JFM: currently it's more a place holder than anything else.
4481 * In the spooler world there is a notion of server registration.
4482 * the print servers are registered on the PDC (in the same domain)
4484 * We should have a TDB here. The registration is done thru an
4485 * undocumented RPC call.
4488 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4493 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4494 slprintf(desc, sizeof(desc)-1,"%s", name);
4495 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4497 init_unistr(&printer->description, desc);
4498 init_unistr(&printer->name, printername);
4499 init_unistr(&printer->comment, comment);
4500 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4502 /* check the required size. */
4503 *needed += spoolss_size_printer_info_1(printer);
4505 if (*needed > offered) {
4506 result = WERR_INSUFFICIENT_BUFFER;
4510 if (!rpcbuf_alloc_size(buffer, *needed)) {
4511 result = WERR_NOMEM;
4515 /* fill the buffer with the structures */
4516 smb_io_printer_info_1("", buffer, printer, 0);
4522 if ( !W_ERROR_IS_OK(result) )
4530 /********************************************************************
4531 enum_all_printers_info_1_network.
4532 *********************************************************************/
4534 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4538 DEBUG(4,("enum_all_printers_info_1_network\n"));
4540 /* If we respond to a enum_printers level 1 on our name with flags
4541 set to PRINTER_ENUM_REMOTE with a list of printers then these
4542 printers incorrectly appear in the APW browse list.
4543 Specifically the printers for the server appear at the workgroup
4544 level where all the other servers in the domain are
4545 listed. Windows responds to this call with a
4546 WERR_CAN_NOT_COMPLETE so we should do the same. */
4548 if (name[0] == '\\' && name[1] == '\\')
4551 if (is_myname_or_ipaddr(s))
4552 return WERR_CAN_NOT_COMPLETE;
4554 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4557 /********************************************************************
4558 * api_spoolss_enumprinters
4560 * called from api_spoolss_enumprinters (see this to understand)
4561 ********************************************************************/
4563 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4567 int n_services=lp_numservices();
4568 PRINTER_INFO_2 *printers=NULL;
4569 PRINTER_INFO_2 current_prt;
4570 WERROR result = WERR_OK;
4574 for (snum=0; snum<n_services; snum++) {
4575 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4576 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4578 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4579 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4580 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4585 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4587 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4594 /* check the required size. */
4595 for (i=0; i<*returned; i++)
4596 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4598 if (*needed > offered) {
4599 result = WERR_INSUFFICIENT_BUFFER;
4603 if (!rpcbuf_alloc_size(buffer, *needed)) {
4604 result = WERR_NOMEM;
4608 /* fill the buffer with the structures */
4609 for (i=0; i<*returned; i++)
4610 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4615 for (i=0; i<*returned; i++)
4616 free_devmode(printers[i].devmode);
4618 SAFE_FREE(printers);
4620 if ( !W_ERROR_IS_OK(result) )
4626 /********************************************************************
4627 * handle enumeration of printers at level 1
4628 ********************************************************************/
4630 static WERROR enumprinters_level1( uint32 flags, fstring name,
4631 RPC_BUFFER *buffer, uint32 offered,
4632 uint32 *needed, uint32 *returned)
4634 /* Not all the flags are equals */
4636 if (flags & PRINTER_ENUM_LOCAL)
4637 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4639 if (flags & PRINTER_ENUM_NAME)
4640 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4642 #if 0 /* JERRY - disabled for now */
4643 if (flags & PRINTER_ENUM_REMOTE)
4644 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4647 if (flags & PRINTER_ENUM_NETWORK)
4648 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4650 return WERR_OK; /* NT4sp5 does that */
4653 /********************************************************************
4654 * handle enumeration of printers at level 2
4655 ********************************************************************/
4657 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4658 RPC_BUFFER *buffer, uint32 offered,
4659 uint32 *needed, uint32 *returned)
4661 char *s = servername;
4663 if (flags & PRINTER_ENUM_LOCAL) {
4664 return enum_all_printers_info_2(buffer, offered, needed, returned);
4667 if (flags & PRINTER_ENUM_NAME) {
4668 if ((servername[0] == '\\') && (servername[1] == '\\'))
4670 if (is_myname_or_ipaddr(s))
4671 return enum_all_printers_info_2(buffer, offered, needed, returned);
4673 return WERR_INVALID_NAME;
4676 if (flags & PRINTER_ENUM_REMOTE)
4677 return WERR_UNKNOWN_LEVEL;
4682 /********************************************************************
4683 * handle enumeration of printers at level 5
4684 ********************************************************************/
4686 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4687 RPC_BUFFER *buffer, uint32 offered,
4688 uint32 *needed, uint32 *returned)
4690 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4694 /********************************************************************
4695 * api_spoolss_enumprinters
4697 * called from api_spoolss_enumprinters (see this to understand)
4698 ********************************************************************/
4700 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4702 uint32 flags = q_u->flags;
4703 UNISTR2 *servername = &q_u->servername;
4704 uint32 level = q_u->level;
4705 RPC_BUFFER *buffer = NULL;
4706 uint32 offered = q_u->offered;
4707 uint32 *needed = &r_u->needed;
4708 uint32 *returned = &r_u->returned;
4712 /* that's an [in out] buffer */
4714 if (!q_u->buffer && (offered!=0)) {
4715 return WERR_INVALID_PARAM;
4718 rpcbuf_move(q_u->buffer, &r_u->buffer);
4719 buffer = r_u->buffer;
4721 DEBUG(4,("_spoolss_enumprinters\n"));
4728 * flags==PRINTER_ENUM_NAME
4729 * if name=="" then enumerates all printers
4730 * if name!="" then enumerate the printer
4731 * flags==PRINTER_ENUM_REMOTE
4732 * name is NULL, enumerate printers
4733 * Level 2: name!="" enumerates printers, name can't be NULL
4734 * Level 3: doesn't exist
4735 * Level 4: does a local registry lookup
4736 * Level 5: same as Level 2
4739 unistr2_to_ascii(name, servername, sizeof(name));
4744 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4746 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4748 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4753 return WERR_UNKNOWN_LEVEL;
4756 /****************************************************************************
4757 ****************************************************************************/
4759 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4761 PRINTER_INFO_0 *printer=NULL;
4762 WERROR result = WERR_OK;
4764 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4767 construct_printer_info_0(print_hnd, printer, snum);
4769 /* check the required size. */
4770 *needed += spoolss_size_printer_info_0(printer);
4772 if (*needed > offered) {
4773 result = WERR_INSUFFICIENT_BUFFER;
4777 if (!rpcbuf_alloc_size(buffer, *needed)) {
4778 result = WERR_NOMEM;
4782 /* fill the buffer with the structures */
4783 smb_io_printer_info_0("", buffer, printer, 0);
4793 /****************************************************************************
4794 ****************************************************************************/
4796 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4798 PRINTER_INFO_1 *printer=NULL;
4799 WERROR result = WERR_OK;
4801 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4804 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4806 /* check the required size. */
4807 *needed += spoolss_size_printer_info_1(printer);
4809 if (*needed > offered) {
4810 result = WERR_INSUFFICIENT_BUFFER;
4814 if (!rpcbuf_alloc_size(buffer, *needed)) {
4815 result = WERR_NOMEM;
4819 /* fill the buffer with the structures */
4820 smb_io_printer_info_1("", buffer, printer, 0);
4829 /****************************************************************************
4830 ****************************************************************************/
4832 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4834 PRINTER_INFO_2 *printer=NULL;
4835 WERROR result = WERR_OK;
4837 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4840 construct_printer_info_2(print_hnd, printer, snum);
4842 /* check the required size. */
4843 *needed += spoolss_size_printer_info_2(printer);
4845 if (*needed > offered) {
4846 result = WERR_INSUFFICIENT_BUFFER;
4850 if (!rpcbuf_alloc_size(buffer, *needed)) {
4851 result = WERR_NOMEM;
4855 /* fill the buffer with the structures */
4856 if (!smb_io_printer_info_2("", buffer, printer, 0))
4857 result = WERR_NOMEM;
4861 free_printer_info_2(printer);
4866 /****************************************************************************
4867 ****************************************************************************/
4869 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4871 PRINTER_INFO_3 *printer=NULL;
4872 WERROR result = WERR_OK;
4874 if (!construct_printer_info_3(print_hnd, &printer, snum))
4877 /* check the required size. */
4878 *needed += spoolss_size_printer_info_3(printer);
4880 if (*needed > offered) {
4881 result = WERR_INSUFFICIENT_BUFFER;
4885 if (!rpcbuf_alloc_size(buffer, *needed)) {
4886 result = WERR_NOMEM;
4890 /* fill the buffer with the structures */
4891 smb_io_printer_info_3("", buffer, printer, 0);
4895 free_printer_info_3(printer);
4900 /****************************************************************************
4901 ****************************************************************************/
4903 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4905 PRINTER_INFO_4 *printer=NULL;
4906 WERROR result = WERR_OK;
4908 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4911 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4916 /* check the required size. */
4917 *needed += spoolss_size_printer_info_4(printer);
4919 if (*needed > offered) {
4920 result = WERR_INSUFFICIENT_BUFFER;
4924 if (!rpcbuf_alloc_size(buffer, *needed)) {
4925 result = WERR_NOMEM;
4929 /* fill the buffer with the structures */
4930 smb_io_printer_info_4("", buffer, printer, 0);
4934 free_printer_info_4(printer);
4939 /****************************************************************************
4940 ****************************************************************************/
4942 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4944 PRINTER_INFO_5 *printer=NULL;
4945 WERROR result = WERR_OK;
4947 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4950 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4951 free_printer_info_5(printer);
4955 /* check the required size. */
4956 *needed += spoolss_size_printer_info_5(printer);
4958 if (*needed > offered) {
4959 result = WERR_INSUFFICIENT_BUFFER;
4963 if (!rpcbuf_alloc_size(buffer, *needed)) {
4964 result = WERR_NOMEM;
4968 /* fill the buffer with the structures */
4969 smb_io_printer_info_5("", buffer, printer, 0);
4973 free_printer_info_5(printer);
4978 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4980 RPC_BUFFER *buffer, uint32 offered,
4983 PRINTER_INFO_6 *printer;
4984 WERROR result = WERR_OK;
4986 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4990 if (!construct_printer_info_6(print_hnd, printer, snum)) {
4991 free_printer_info_6(printer);
4995 /* check the required size. */
4996 *needed += spoolss_size_printer_info_6(printer);
4998 if (*needed > offered) {
4999 result = WERR_INSUFFICIENT_BUFFER;
5003 if (!rpcbuf_alloc_size(buffer, *needed)) {
5004 result = WERR_NOMEM;
5008 /* fill the buffer with the structures */
5009 smb_io_printer_info_6("", buffer, printer, 0);
5013 free_printer_info_6(printer);
5018 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5020 PRINTER_INFO_7 *printer=NULL;
5021 WERROR result = WERR_OK;
5023 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5026 if (!construct_printer_info_7(print_hnd, printer, snum))
5029 /* check the required size. */
5030 *needed += spoolss_size_printer_info_7(printer);
5032 if (*needed > offered) {
5033 result = WERR_INSUFFICIENT_BUFFER;
5037 if (!rpcbuf_alloc_size(buffer, *needed)) {
5038 result = WERR_NOMEM;
5043 /* fill the buffer with the structures */
5044 smb_io_printer_info_7("", buffer, printer, 0);
5048 free_printer_info_7(printer);
5053 /****************************************************************************
5054 ****************************************************************************/
5056 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5058 POLICY_HND *handle = &q_u->handle;
5059 uint32 level = q_u->level;
5060 RPC_BUFFER *buffer = NULL;
5061 uint32 offered = q_u->offered;
5062 uint32 *needed = &r_u->needed;
5063 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5067 /* that's an [in out] buffer */
5069 if (!q_u->buffer && (offered!=0)) {
5070 return WERR_INVALID_PARAM;
5073 rpcbuf_move(q_u->buffer, &r_u->buffer);
5074 buffer = r_u->buffer;
5078 if (!get_printer_snum(p, handle, &snum, NULL))
5083 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5085 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5087 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5089 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5091 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5093 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5095 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5097 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5099 return WERR_UNKNOWN_LEVEL;
5102 /********************************************************************
5103 * fill a DRIVER_INFO_1 struct
5104 ********************************************************************/
5106 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5108 init_unistr( &info->name, driver.info_3->name);
5111 /********************************************************************
5112 * construct_printer_driver_info_1
5113 ********************************************************************/
5115 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5117 NT_PRINTER_INFO_LEVEL *printer = NULL;
5118 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5120 ZERO_STRUCT(driver);
5122 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5123 return WERR_INVALID_PRINTER_NAME;
5125 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5126 free_a_printer(&printer, 2);
5127 return WERR_UNKNOWN_PRINTER_DRIVER;
5130 fill_printer_driver_info_1(info, driver, servername, architecture);
5132 free_a_printer(&printer,2);
5137 /********************************************************************
5138 * construct_printer_driver_info_2
5139 * fill a printer_info_2 struct
5140 ********************************************************************/
5142 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5144 TALLOC_CTX *ctx = talloc_tos();
5147 info->version=driver.info_3->cversion;
5149 init_unistr( &info->name, driver.info_3->name );
5150 init_unistr( &info->architecture, driver.info_3->environment );
5153 if (strlen(driver.info_3->driverpath)) {
5154 temp = talloc_asprintf(ctx,
5157 driver.info_3->driverpath);
5158 init_unistr( &info->driverpath, temp );
5160 init_unistr( &info->driverpath, "" );
5164 if (strlen(driver.info_3->datafile)) {
5165 temp = talloc_asprintf(ctx,
5168 driver.info_3->datafile);
5169 init_unistr( &info->datafile, temp );
5171 init_unistr( &info->datafile, "" );
5174 if (strlen(driver.info_3->configfile)) {
5175 temp = talloc_asprintf(ctx,
5178 driver.info_3->configfile);
5179 init_unistr( &info->configfile, temp );
5181 init_unistr( &info->configfile, "" );
5184 /********************************************************************
5185 * construct_printer_driver_info_2
5186 * fill a printer_info_2 struct
5187 ********************************************************************/
5189 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5191 NT_PRINTER_INFO_LEVEL *printer = NULL;
5192 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5194 ZERO_STRUCT(printer);
5195 ZERO_STRUCT(driver);
5197 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5198 return WERR_INVALID_PRINTER_NAME;
5200 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5201 free_a_printer(&printer, 2);
5202 return WERR_UNKNOWN_PRINTER_DRIVER;
5205 fill_printer_driver_info_2(info, driver, servername);
5207 free_a_printer(&printer,2);
5212 /********************************************************************
5213 * copy a strings array and convert to UNICODE
5215 * convert an array of ascii string to a UNICODE string
5216 ********************************************************************/
5218 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5224 TALLOC_CTX *ctx = talloc_tos();
5226 DEBUG(6,("init_unistr_array\n"));
5230 if ( !char_array ) {
5235 v = ""; /* hack to handle null lists */
5238 /* hack to allow this to be used in places other than when generating
5239 the list of dependent files */
5243 line = talloc_asprintf(ctx,
5248 line = talloc_strdup(ctx, v);
5252 SAFE_FREE(*uni_array);
5255 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5257 /* add one extra unit16 for the second terminating NULL */
5259 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5260 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5267 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5272 /* special case for ""; we need to add both NULL's here */
5274 (*uni_array)[j++]=0x0000;
5275 (*uni_array)[j]=0x0000;
5278 DEBUGADD(6,("last one:done\n"));
5280 /* return size of array in uint16's */
5285 /********************************************************************
5286 * construct_printer_info_3
5287 * fill a printer_info_3 struct
5288 ********************************************************************/
5290 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5293 TALLOC_CTX *ctx = talloc_tos();
5297 info->version=driver.info_3->cversion;
5299 init_unistr( &info->name, driver.info_3->name );
5300 init_unistr( &info->architecture, driver.info_3->environment );
5302 if (strlen(driver.info_3->driverpath)) {
5303 temp = talloc_asprintf(ctx,
5306 driver.info_3->driverpath);
5307 init_unistr( &info->driverpath, temp );
5309 init_unistr( &info->driverpath, "" );
5312 if (strlen(driver.info_3->datafile)) {
5313 temp = talloc_asprintf(ctx,
5316 driver.info_3->datafile);
5317 init_unistr( &info->datafile, temp );
5319 init_unistr( &info->datafile, "" );
5322 if (strlen(driver.info_3->configfile)) {
5323 temp = talloc_asprintf(ctx,
5326 driver.info_3->configfile);
5327 init_unistr( &info->configfile, temp );
5329 init_unistr( &info->configfile, "" );
5332 if (strlen(driver.info_3->helpfile)) {
5333 temp = talloc_asprintf(ctx,
5336 driver.info_3->helpfile);
5337 init_unistr( &info->helpfile, temp );
5339 init_unistr( &info->helpfile, "" );
5342 init_unistr( &info->monitorname, driver.info_3->monitorname );
5343 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5345 info->dependentfiles=NULL;
5346 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5349 /********************************************************************
5350 * construct_printer_info_3
5351 * fill a printer_info_3 struct
5352 ********************************************************************/
5354 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5356 NT_PRINTER_INFO_LEVEL *printer = NULL;
5357 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5359 ZERO_STRUCT(driver);
5361 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5362 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5363 if (!W_ERROR_IS_OK(status))
5364 return WERR_INVALID_PRINTER_NAME;
5366 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5367 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5372 * I put this code in during testing. Helpful when commenting out the
5373 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5374 * as win2k always queries the driver using an infor level of 6.
5375 * I've left it in (but ifdef'd out) because I'll probably
5376 * use it in experimentation again in the future. --jerry 22/01/2002
5379 if (!W_ERROR_IS_OK(status)) {
5381 * Is this a W2k client ?
5384 /* Yes - try again with a WinNT driver. */
5386 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5387 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5391 if (!W_ERROR_IS_OK(status)) {
5392 free_a_printer(&printer,2);
5393 return WERR_UNKNOWN_PRINTER_DRIVER;
5401 fill_printer_driver_info_3(info, driver, servername);
5403 free_a_printer(&printer,2);
5408 /********************************************************************
5409 * construct_printer_info_6
5410 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5411 ********************************************************************/
5413 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5417 TALLOC_CTX *ctx = talloc_tos();
5420 memset(&nullstr, '\0', sizeof(fstring));
5422 info->version=driver.info_3->cversion;
5424 init_unistr( &info->name, driver.info_3->name );
5425 init_unistr( &info->architecture, driver.info_3->environment );
5427 if (strlen(driver.info_3->driverpath)) {
5428 temp = talloc_asprintf(ctx,
5431 driver.info_3->driverpath);
5432 init_unistr( &info->driverpath, temp );
5434 init_unistr( &info->driverpath, "" );
5437 if (strlen(driver.info_3->datafile)) {
5438 temp = talloc_asprintf(ctx,
5441 driver.info_3->datafile);
5442 init_unistr( &info->datafile, temp );
5444 init_unistr( &info->datafile, "" );
5447 if (strlen(driver.info_3->configfile)) {
5448 temp = talloc_asprintf(ctx,
5451 driver.info_3->configfile);
5452 init_unistr( &info->configfile, temp );
5454 init_unistr( &info->configfile, "" );
5457 if (strlen(driver.info_3->helpfile)) {
5458 temp = talloc_asprintf(ctx,
5461 driver.info_3->helpfile);
5462 init_unistr( &info->helpfile, temp );
5464 init_unistr( &info->helpfile, "" );
5467 init_unistr( &info->monitorname, driver.info_3->monitorname );
5468 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5470 info->dependentfiles = NULL;
5471 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5473 info->previousdrivernames=NULL;
5474 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5476 info->driver_date=0;
5479 info->driver_version_low=0;
5480 info->driver_version_high=0;
5482 init_unistr( &info->mfgname, "");
5483 init_unistr( &info->oem_url, "");
5484 init_unistr( &info->hardware_id, "");
5485 init_unistr( &info->provider, "");
5488 /********************************************************************
5489 * construct_printer_info_6
5490 * fill a printer_info_6 struct
5491 ********************************************************************/
5493 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5494 fstring servername, fstring architecture, uint32 version)
5496 NT_PRINTER_INFO_LEVEL *printer = NULL;
5497 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5500 ZERO_STRUCT(driver);
5502 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5504 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5506 if (!W_ERROR_IS_OK(status))
5507 return WERR_INVALID_PRINTER_NAME;
5509 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5511 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5513 if (!W_ERROR_IS_OK(status))
5516 * Is this a W2k client ?
5520 free_a_printer(&printer,2);
5521 return WERR_UNKNOWN_PRINTER_DRIVER;
5524 /* Yes - try again with a WinNT driver. */
5526 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5527 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5528 if (!W_ERROR_IS_OK(status)) {
5529 free_a_printer(&printer,2);
5530 return WERR_UNKNOWN_PRINTER_DRIVER;
5534 fill_printer_driver_info_6(info, driver, servername);
5536 free_a_printer(&printer,2);
5537 free_a_printer_driver(driver, 3);
5542 /****************************************************************************
5543 ****************************************************************************/
5545 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5547 SAFE_FREE(info->dependentfiles);
5550 /****************************************************************************
5551 ****************************************************************************/
5553 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5555 SAFE_FREE(info->dependentfiles);
5558 /****************************************************************************
5559 ****************************************************************************/
5561 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5563 DRIVER_INFO_1 *info=NULL;
5566 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5569 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5570 if (!W_ERROR_IS_OK(result))
5573 /* check the required size. */
5574 *needed += spoolss_size_printer_driver_info_1(info);
5576 if (*needed > offered) {
5577 result = WERR_INSUFFICIENT_BUFFER;
5581 if (!rpcbuf_alloc_size(buffer, *needed)) {
5582 result = WERR_NOMEM;
5586 /* fill the buffer with the structures */
5587 smb_io_printer_driver_info_1("", buffer, info, 0);
5596 /****************************************************************************
5597 ****************************************************************************/
5599 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5601 DRIVER_INFO_2 *info=NULL;
5604 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5607 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5608 if (!W_ERROR_IS_OK(result))
5611 /* check the required size. */
5612 *needed += spoolss_size_printer_driver_info_2(info);
5614 if (*needed > offered) {
5615 result = WERR_INSUFFICIENT_BUFFER;
5619 if (!rpcbuf_alloc_size(buffer, *needed)) {
5620 result = WERR_NOMEM;
5624 /* fill the buffer with the structures */
5625 smb_io_printer_driver_info_2("", buffer, info, 0);
5634 /****************************************************************************
5635 ****************************************************************************/
5637 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5644 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5645 if (!W_ERROR_IS_OK(result))
5648 /* check the required size. */
5649 *needed += spoolss_size_printer_driver_info_3(&info);
5651 if (*needed > offered) {
5652 result = WERR_INSUFFICIENT_BUFFER;
5656 if (!rpcbuf_alloc_size(buffer, *needed)) {
5657 result = WERR_NOMEM;
5661 /* fill the buffer with the structures */
5662 smb_io_printer_driver_info_3("", buffer, &info, 0);
5665 free_printer_driver_info_3(&info);
5670 /****************************************************************************
5671 ****************************************************************************/
5673 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5680 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5681 if (!W_ERROR_IS_OK(result))
5684 /* check the required size. */
5685 *needed += spoolss_size_printer_driver_info_6(&info);
5687 if (*needed > offered) {
5688 result = WERR_INSUFFICIENT_BUFFER;
5692 if (!rpcbuf_alloc_size(buffer, *needed)) {
5693 result = WERR_NOMEM;
5697 /* fill the buffer with the structures */
5698 smb_io_printer_driver_info_6("", buffer, &info, 0);
5701 free_printer_driver_info_6(&info);
5706 /****************************************************************************
5707 ****************************************************************************/
5709 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5711 POLICY_HND *handle = &q_u->handle;
5712 UNISTR2 *uni_arch = &q_u->architecture;
5713 uint32 level = q_u->level;
5714 uint32 clientmajorversion = q_u->clientmajorversion;
5715 RPC_BUFFER *buffer = NULL;
5716 uint32 offered = q_u->offered;
5717 uint32 *needed = &r_u->needed;
5718 uint32 *servermajorversion = &r_u->servermajorversion;
5719 uint32 *serverminorversion = &r_u->serverminorversion;
5720 Printer_entry *printer;
5723 fstring architecture;
5726 /* that's an [in out] buffer */
5728 if (!q_u->buffer && (offered!=0)) {
5729 return WERR_INVALID_PARAM;
5732 rpcbuf_move(q_u->buffer, &r_u->buffer);
5733 buffer = r_u->buffer;
5735 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5737 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5738 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5739 return WERR_INVALID_PRINTER_NAME;
5743 *servermajorversion = 0;
5744 *serverminorversion = 0;
5746 fstrcpy(servername, get_server_name( printer ));
5747 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5749 if (!get_printer_snum(p, handle, &snum, NULL))
5754 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5756 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5758 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5760 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5763 /* apparently this call is the equivalent of
5764 EnumPrinterDataEx() for the DsDriver key */
5769 return WERR_UNKNOWN_LEVEL;
5772 /****************************************************************************
5773 ****************************************************************************/
5775 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5777 POLICY_HND *handle = &q_u->handle;
5779 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5782 DEBUG(3,("Error in startpageprinter printer handle\n"));
5786 Printer->page_started=True;
5790 /****************************************************************************
5791 ****************************************************************************/
5793 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5795 POLICY_HND *handle = &q_u->handle;
5798 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5801 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5805 if (!get_printer_snum(p, handle, &snum, NULL))
5808 Printer->page_started=False;
5809 print_job_endpage(snum, Printer->jobid);
5814 /********************************************************************
5815 * api_spoolss_getprinter
5816 * called from the spoolss dispatcher
5818 ********************************************************************/
5820 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5822 POLICY_HND *handle = &q_u->handle;
5823 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5824 uint32 *jobid = &r_u->jobid;
5825 TALLOC_CTX *ctx = p->mem_ctx;
5826 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5828 char *jobname = NULL;
5830 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5833 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5838 * a nice thing with NT is it doesn't listen to what you tell it.
5839 * when asked to send _only_ RAW datas, it tries to send datas
5842 * So I add checks like in NT Server ...
5845 if (info_1->p_datatype != 0) {
5846 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5847 if (strcmp(datatype, "RAW") != 0) {
5849 return WERR_INVALID_DATATYPE;
5853 /* get the share number of the printer */
5854 if (!get_printer_snum(p, handle, &snum, NULL)) {
5858 jobname = unistr2_to_ascii_talloc(ctx, &info_1->docname);
5860 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5862 /* An error occured in print_job_start() so return an appropriate
5865 if (Printer->jobid == -1) {
5866 return map_werror_from_unix(errno);
5869 Printer->document_started=True;
5870 (*jobid) = Printer->jobid;
5875 /********************************************************************
5876 * api_spoolss_getprinter
5877 * called from the spoolss dispatcher
5879 ********************************************************************/
5881 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5883 POLICY_HND *handle = &q_u->handle;
5885 return _spoolss_enddocprinter_internal(p, handle);
5888 /****************************************************************************
5889 ****************************************************************************/
5891 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5893 POLICY_HND *handle = &q_u->handle;
5894 uint32 buffer_size = q_u->buffer_size;
5895 uint8 *buffer = q_u->buffer;
5896 uint32 *buffer_written = &q_u->buffer_size2;
5898 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5901 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5902 r_u->buffer_written = q_u->buffer_size2;
5906 if (!get_printer_snum(p, handle, &snum, NULL))
5909 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5910 (SMB_OFF_T)-1, (size_t)buffer_size);
5911 if (*buffer_written == (uint32)-1) {
5912 r_u->buffer_written = 0;
5913 if (errno == ENOSPC)
5914 return WERR_NO_SPOOL_SPACE;
5916 return WERR_ACCESS_DENIED;
5919 r_u->buffer_written = q_u->buffer_size2;
5924 /********************************************************************
5925 * api_spoolss_getprinter
5926 * called from the spoolss dispatcher
5928 ********************************************************************/
5930 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5934 WERROR errcode = WERR_BADFUNC;
5935 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5938 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5942 if (!get_printer_snum(p, handle, &snum, NULL))
5946 case PRINTER_CONTROL_PAUSE:
5947 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5951 case PRINTER_CONTROL_RESUME:
5952 case PRINTER_CONTROL_UNPAUSE:
5953 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5957 case PRINTER_CONTROL_PURGE:
5958 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5963 return WERR_UNKNOWN_LEVEL;
5969 /********************************************************************
5970 * api_spoolss_abortprinter
5971 * From MSDN: "Deletes printer's spool file if printer is configured
5973 ********************************************************************/
5975 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5977 POLICY_HND *handle = &q_u->handle;
5978 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5980 WERROR errcode = WERR_OK;
5983 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5987 if (!get_printer_snum(p, handle, &snum, NULL))
5990 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5995 /********************************************************************
5996 * called by spoolss_api_setprinter
5997 * when updating a printer description
5998 ********************************************************************/
6000 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6001 const SPOOL_PRINTER_INFO_LEVEL *info,
6002 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6004 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6008 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6010 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6011 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6012 OUR_HANDLE(handle)));
6014 result = WERR_BADFID;
6019 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6020 result = WERR_INVALID_PARAM;
6024 /* Check the user has permissions to change the security
6025 descriptor. By experimentation with two NT machines, the user
6026 requires Full Access to the printer to change security
6029 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6030 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6031 result = WERR_ACCESS_DENIED;
6035 /* NT seems to like setting the security descriptor even though
6036 nothing may have actually changed. */
6038 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6039 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6040 result = WERR_BADFID;
6044 if (DEBUGLEVEL >= 10) {
6048 the_acl = old_secdesc_ctr->sd->dacl;
6049 DEBUG(10, ("old_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++) {
6053 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6054 &the_acl->aces[i].trustee),
6055 the_acl->aces[i].access_mask));
6058 the_acl = secdesc_ctr->sd->dacl;
6061 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6062 PRINTERNAME(snum), the_acl->num_aces));
6064 for (i = 0; i < the_acl->num_aces; i++) {
6065 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6066 &the_acl->aces[i].trustee),
6067 the_acl->aces[i].access_mask));
6070 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6074 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6075 if (!new_secdesc_ctr) {
6076 result = WERR_NOMEM;
6080 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6085 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6092 /********************************************************************
6093 Canonicalize printer info from a client
6095 ATTN: It does not matter what we set the servername to hear
6096 since we do the necessary work in get_a_printer() to set it to
6097 the correct value based on what the client sent in the
6098 _spoolss_open_printer_ex().
6099 ********************************************************************/
6101 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6103 fstring printername;
6106 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6107 "portname=%s drivername=%s comment=%s location=%s\n",
6108 info->servername, info->printername, info->sharename,
6109 info->portname, info->drivername, info->comment, info->location));
6111 /* we force some elements to "correct" values */
6112 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6113 fstrcpy(info->sharename, lp_servicename(snum));
6115 /* check to see if we allow printername != sharename */
6117 if ( lp_force_printername(snum) ) {
6118 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6119 global_myname(), info->sharename );
6122 /* make sure printername is in \\server\printername format */
6124 fstrcpy( printername, info->printername );
6126 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6127 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6131 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6132 global_myname(), p );
6135 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6136 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6143 /****************************************************************************
6144 ****************************************************************************/
6146 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6148 char *cmd = lp_addport_cmd();
6149 char *command = NULL;
6152 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6153 bool is_print_op = False;
6156 return WERR_ACCESS_DENIED;
6159 command = talloc_asprintf(ctx,
6160 "%s \"%s\" \"%s\"", cmd, portname, uri );
6166 is_print_op = user_has_privileges( token, &se_printop );
6168 DEBUG(10,("Running [%s]\n", command));
6170 /********* BEGIN SePrintOperatorPrivilege **********/
6175 ret = smbrun(command, &fd);
6180 /********* END SePrintOperatorPrivilege **********/
6182 DEBUGADD(10,("returned [%d]\n", ret));
6184 TALLOC_FREE(command);
6189 return WERR_ACCESS_DENIED;
6195 /****************************************************************************
6196 ****************************************************************************/
6198 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6200 char *cmd = lp_addprinter_cmd();
6202 char *command = NULL;
6206 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6207 bool is_print_op = False;
6208 char *remote_machine = talloc_strdup(ctx, "%m");
6210 if (!remote_machine) {
6213 remote_machine = talloc_sub_basic(ctx,
6214 current_user_info.smb_name,
6215 current_user_info.domain,
6217 if (!remote_machine) {
6221 command = talloc_asprintf(ctx,
6222 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6223 cmd, printer->info_2->printername, printer->info_2->sharename,
6224 printer->info_2->portname, printer->info_2->drivername,
6225 printer->info_2->location, printer->info_2->comment, remote_machine);
6231 is_print_op = user_has_privileges( token, &se_printop );
6233 DEBUG(10,("Running [%s]\n", command));
6235 /********* BEGIN SePrintOperatorPrivilege **********/
6240 if ( (ret = smbrun(command, &fd)) == 0 ) {
6241 /* Tell everyone we updated smb.conf. */
6242 message_send_all(smbd_messaging_context(),
6243 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6249 /********* END SePrintOperatorPrivilege **********/
6251 DEBUGADD(10,("returned [%d]\n", ret));
6253 TALLOC_FREE(command);
6254 TALLOC_FREE(remote_machine);
6262 /* reload our services immediately */
6263 reload_services( False );
6266 /* Get lines and convert them back to dos-codepage */
6267 qlines = fd_lines_load(fd, &numlines, 0);
6268 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6271 /* Set the portname to what the script says the portname should be. */
6272 /* but don't require anything to be return from the script exit a good error code */
6275 /* Set the portname to what the script says the portname should be. */
6276 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6277 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6280 file_lines_free(qlines);
6285 /********************************************************************
6286 * Called by spoolss_api_setprinter
6287 * when updating a printer description.
6288 ********************************************************************/
6290 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6291 const SPOOL_PRINTER_INFO_LEVEL *info,
6292 DEVICEMODE *devmode)
6295 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6296 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6301 DEBUG(8,("update_printer\n"));
6306 result = WERR_BADFID;
6310 if (!get_printer_snum(p, handle, &snum, NULL)) {
6311 result = WERR_BADFID;
6315 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6316 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6317 result = WERR_BADFID;
6321 DEBUGADD(8,("Converting info_2 struct\n"));
6324 * convert_printer_info converts the incoming
6325 * info from the client and overwrites the info
6326 * just read from the tdb in the pointer 'printer'.
6329 if (!convert_printer_info(info, printer, level)) {
6330 result = WERR_NOMEM;
6335 /* we have a valid devmode
6336 convert it and link it*/
6338 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6339 if (!convert_devicemode(printer->info_2->printername, devmode,
6340 &printer->info_2->devmode)) {
6341 result = WERR_NOMEM;
6346 /* Do sanity check on the requested changes for Samba */
6348 if (!check_printer_ok(printer->info_2, snum)) {
6349 result = WERR_INVALID_PARAM;
6353 /* FIXME!!! If the driver has changed we really should verify that
6354 it is installed before doing much else --jerry */
6356 /* Check calling user has permission to update printer description */
6358 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6359 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6360 result = WERR_ACCESS_DENIED;
6364 /* Call addprinter hook */
6365 /* Check changes to see if this is really needed */
6367 if ( *lp_addprinter_cmd()
6368 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6369 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6370 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6371 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6373 /* add_printer_hook() will call reload_services() */
6375 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
6376 result = WERR_ACCESS_DENIED;
6382 * When a *new* driver is bound to a printer, the drivername is used to
6383 * lookup previously saved driver initialization info, which is then
6384 * bound to the printer, simulating what happens in the Windows arch.
6386 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6388 if (!set_driver_init(printer, 2))
6390 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6391 printer->info_2->drivername));
6394 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6395 printer->info_2->drivername));
6397 notify_printer_driver(snum, printer->info_2->drivername);
6401 * flag which changes actually occured. This is a small subset of
6402 * all the possible changes. We also have to update things in the
6406 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6407 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6408 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6409 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6411 notify_printer_comment(snum, printer->info_2->comment);
6414 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6415 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6416 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6417 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6419 notify_printer_sharename(snum, printer->info_2->sharename);
6422 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6425 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6428 pname = printer->info_2->printername;
6431 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6432 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6433 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6435 notify_printer_printername( snum, pname );
6438 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6439 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6440 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6441 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6443 notify_printer_port(snum, printer->info_2->portname);
6446 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6447 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6448 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6449 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6451 notify_printer_location(snum, printer->info_2->location);
6454 /* here we need to update some more DsSpooler keys */
6455 /* uNCName, serverName, shortServerName */
6457 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6458 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6459 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6460 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6461 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6463 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6464 global_myname(), printer->info_2->sharename );
6465 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6466 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6467 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6469 /* Update printer info */
6470 result = mod_a_printer(printer, 2);
6473 free_a_printer(&printer, 2);
6474 free_a_printer(&old_printer, 2);
6480 /****************************************************************************
6481 ****************************************************************************/
6482 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6483 const SPOOL_PRINTER_INFO_LEVEL *info)
6486 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6488 Printer_entry *Printer;
6490 if ( lp_security() != SEC_ADS ) {
6491 return WERR_UNKNOWN_LEVEL;
6494 Printer = find_printer_index_by_hnd(p, handle);
6496 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6501 if (!get_printer_snum(p, handle, &snum, NULL))
6504 nt_printer_publish(Printer, snum, info7->action);
6508 return WERR_UNKNOWN_LEVEL;
6511 /****************************************************************************
6512 ****************************************************************************/
6514 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6516 POLICY_HND *handle = &q_u->handle;
6517 uint32 level = q_u->level;
6518 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6519 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6520 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6521 uint32 command = q_u->command;
6524 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6527 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6531 /* check the level */
6534 return control_printer(handle, command, p);
6536 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6537 if (!W_ERROR_IS_OK(result))
6540 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6543 return update_printer_sec(handle, level, info, p,
6546 return publish_or_unpublish_printer(p, handle, info);
6548 return WERR_UNKNOWN_LEVEL;
6552 /****************************************************************************
6553 ****************************************************************************/
6555 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6557 POLICY_HND *handle = &q_u->handle;
6558 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6561 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6565 if (Printer->notify.client_connected==True) {
6568 if ( Printer->printer_type == SPLHND_SERVER)
6570 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6571 !get_printer_snum(p, handle, &snum, NULL) )
6574 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6577 Printer->notify.flags=0;
6578 Printer->notify.options=0;
6579 Printer->notify.localmachine[0]='\0';
6580 Printer->notify.printerlocal=0;
6581 if (Printer->notify.option)
6582 free_spool_notify_option(&Printer->notify.option);
6583 Printer->notify.client_connected=False;
6588 /****************************************************************************
6589 ****************************************************************************/
6591 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6593 /* that's an [in out] buffer */
6595 if (!q_u->buffer && (q_u->offered!=0)) {
6596 return WERR_INVALID_PARAM;
6599 rpcbuf_move(q_u->buffer, &r_u->buffer);
6602 return WERR_INVALID_PARAM; /* this is what a NT server
6603 returns for AddJob. AddJob
6604 must fail on non-local
6608 /****************************************************************************
6609 ****************************************************************************/
6611 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6612 int position, int snum,
6613 const NT_PRINTER_INFO_LEVEL *ntprinter)
6617 t=gmtime(&queue->time);
6619 job_info->jobid=queue->job;
6620 init_unistr(&job_info->printername, lp_servicename(snum));
6621 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6622 init_unistr(&job_info->username, queue->fs_user);
6623 init_unistr(&job_info->document, queue->fs_file);
6624 init_unistr(&job_info->datatype, "RAW");
6625 init_unistr(&job_info->text_status, "");
6626 job_info->status=nt_printj_status(queue->status);
6627 job_info->priority=queue->priority;
6628 job_info->position=position;
6629 job_info->totalpages=queue->page_count;
6630 job_info->pagesprinted=0;
6632 make_systemtime(&job_info->submitted, t);
6635 /****************************************************************************
6636 ****************************************************************************/
6638 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6639 int position, int snum,
6640 const NT_PRINTER_INFO_LEVEL *ntprinter,
6641 DEVICEMODE *devmode)
6645 t=gmtime(&queue->time);
6647 job_info->jobid=queue->job;
6649 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6651 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6652 init_unistr(&job_info->username, queue->fs_user);
6653 init_unistr(&job_info->document, queue->fs_file);
6654 init_unistr(&job_info->notifyname, queue->fs_user);
6655 init_unistr(&job_info->datatype, "RAW");
6656 init_unistr(&job_info->printprocessor, "winprint");
6657 init_unistr(&job_info->parameters, "");
6658 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6659 init_unistr(&job_info->text_status, "");
6661 /* and here the security descriptor */
6663 job_info->status=nt_printj_status(queue->status);
6664 job_info->priority=queue->priority;
6665 job_info->position=position;
6666 job_info->starttime=0;
6667 job_info->untiltime=0;
6668 job_info->totalpages=queue->page_count;
6669 job_info->size=queue->size;
6670 make_systemtime(&(job_info->submitted), t);
6671 job_info->timeelapsed=0;
6672 job_info->pagesprinted=0;
6674 job_info->devmode = devmode;
6679 /****************************************************************************
6680 Enumjobs at level 1.
6681 ****************************************************************************/
6683 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6684 const NT_PRINTER_INFO_LEVEL *ntprinter,
6685 RPC_BUFFER *buffer, uint32 offered,
6686 uint32 *needed, uint32 *returned)
6690 WERROR result = WERR_OK;
6692 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6698 for (i=0; i<*returned; i++)
6699 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6701 /* check the required size. */
6702 for (i=0; i<*returned; i++)
6703 (*needed) += spoolss_size_job_info_1(&info[i]);
6705 if (*needed > offered) {
6706 result = WERR_INSUFFICIENT_BUFFER;
6710 if (!rpcbuf_alloc_size(buffer, *needed)) {
6711 result = WERR_NOMEM;
6715 /* fill the buffer with the structures */
6716 for (i=0; i<*returned; i++)
6717 smb_io_job_info_1("", buffer, &info[i], 0);
6723 if ( !W_ERROR_IS_OK(result) )
6729 /****************************************************************************
6730 Enumjobs at level 2.
6731 ****************************************************************************/
6733 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6734 const NT_PRINTER_INFO_LEVEL *ntprinter,
6735 RPC_BUFFER *buffer, uint32 offered,
6736 uint32 *needed, uint32 *returned)
6738 JOB_INFO_2 *info = NULL;
6740 WERROR result = WERR_OK;
6741 DEVICEMODE *devmode = NULL;
6743 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6748 /* this should not be a failure condition if the devmode is NULL */
6750 devmode = construct_dev_mode(lp_const_servicename(snum));
6752 for (i=0; i<*returned; i++)
6753 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6755 /* check the required size. */
6756 for (i=0; i<*returned; i++)
6757 (*needed) += spoolss_size_job_info_2(&info[i]);
6759 if (*needed > offered) {
6760 result = WERR_INSUFFICIENT_BUFFER;
6764 if (!rpcbuf_alloc_size(buffer, *needed)) {
6765 result = WERR_NOMEM;
6769 /* fill the buffer with the structures */
6770 for (i=0; i<*returned; i++)
6771 smb_io_job_info_2("", buffer, &info[i], 0);
6774 free_devmode(devmode);
6777 if ( !W_ERROR_IS_OK(result) )
6784 /****************************************************************************
6786 ****************************************************************************/
6788 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6790 POLICY_HND *handle = &q_u->handle;
6791 uint32 level = q_u->level;
6792 RPC_BUFFER *buffer = NULL;
6793 uint32 offered = q_u->offered;
6794 uint32 *needed = &r_u->needed;
6795 uint32 *returned = &r_u->returned;
6797 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6799 print_status_struct prt_status;
6800 print_queue_struct *queue=NULL;
6802 /* that's an [in out] buffer */
6804 if (!q_u->buffer && (offered!=0)) {
6805 return WERR_INVALID_PARAM;
6808 rpcbuf_move(q_u->buffer, &r_u->buffer);
6809 buffer = r_u->buffer;
6811 DEBUG(4,("_spoolss_enumjobs\n"));
6816 /* lookup the printer snum and tdb entry */
6818 if (!get_printer_snum(p, handle, &snum, NULL))
6821 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6822 if ( !W_ERROR_IS_OK(wret) )
6825 *returned = print_queue_status(snum, &queue, &prt_status);
6826 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6828 if (*returned == 0) {
6830 free_a_printer(&ntprinter, 2);
6836 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6839 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6843 wret = WERR_UNKNOWN_LEVEL;
6848 free_a_printer( &ntprinter, 2 );
6852 /****************************************************************************
6853 ****************************************************************************/
6855 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6860 /****************************************************************************
6861 ****************************************************************************/
6863 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6865 POLICY_HND *handle = &q_u->handle;
6866 uint32 jobid = q_u->jobid;
6867 uint32 command = q_u->command;
6870 WERROR errcode = WERR_BADFUNC;
6872 if (!get_printer_snum(p, handle, &snum, NULL)) {
6876 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6877 return WERR_INVALID_PRINTER_NAME;
6881 case JOB_CONTROL_CANCEL:
6882 case JOB_CONTROL_DELETE:
6883 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6887 case JOB_CONTROL_PAUSE:
6888 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6892 case JOB_CONTROL_RESTART:
6893 case JOB_CONTROL_RESUME:
6894 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6899 return WERR_UNKNOWN_LEVEL;
6905 /****************************************************************************
6906 Enumerates all printer drivers at level 1.
6907 ****************************************************************************/
6909 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6914 fstring *list = NULL;
6915 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6916 DRIVER_INFO_1 *driver_info_1=NULL;
6917 WERROR result = WERR_OK;
6921 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6923 ndrivers=get_ntdrivers(&list, architecture, version);
6924 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6926 if(ndrivers == -1) {
6927 SAFE_FREE(driver_info_1);
6932 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6933 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6939 for (i=0; i<ndrivers; i++) {
6941 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6942 ZERO_STRUCT(driver);
6943 status = get_a_printer_driver(&driver, 3, list[i],
6944 architecture, version);
6945 if (!W_ERROR_IS_OK(status)) {
6947 SAFE_FREE(driver_info_1);
6950 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6951 free_a_printer_driver(driver, 3);
6954 *returned+=ndrivers;
6958 /* check the required size. */
6959 for (i=0; i<*returned; i++) {
6960 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6961 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6964 if (*needed > offered) {
6965 result = WERR_INSUFFICIENT_BUFFER;
6969 if (!rpcbuf_alloc_size(buffer, *needed)) {
6970 result = WERR_NOMEM;
6974 /* fill the buffer with the driver structures */
6975 for (i=0; i<*returned; i++) {
6976 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6977 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6981 SAFE_FREE(driver_info_1);
6983 if ( !W_ERROR_IS_OK(result) )
6989 /****************************************************************************
6990 Enumerates all printer drivers at level 2.
6991 ****************************************************************************/
6993 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6998 fstring *list = NULL;
6999 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7000 DRIVER_INFO_2 *driver_info_2=NULL;
7001 WERROR result = WERR_OK;
7005 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7007 ndrivers=get_ntdrivers(&list, architecture, version);
7008 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7010 if(ndrivers == -1) {
7011 SAFE_FREE(driver_info_2);
7016 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7017 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7023 for (i=0; i<ndrivers; i++) {
7026 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7027 ZERO_STRUCT(driver);
7028 status = get_a_printer_driver(&driver, 3, list[i],
7029 architecture, version);
7030 if (!W_ERROR_IS_OK(status)) {
7032 SAFE_FREE(driver_info_2);
7035 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7036 free_a_printer_driver(driver, 3);
7039 *returned+=ndrivers;
7043 /* check the required size. */
7044 for (i=0; i<*returned; i++) {
7045 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7046 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7049 if (*needed > offered) {
7050 result = WERR_INSUFFICIENT_BUFFER;
7054 if (!rpcbuf_alloc_size(buffer, *needed)) {
7055 result = WERR_NOMEM;
7059 /* fill the buffer with the form structures */
7060 for (i=0; i<*returned; i++) {
7061 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7062 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7066 SAFE_FREE(driver_info_2);
7068 if ( !W_ERROR_IS_OK(result) )
7074 /****************************************************************************
7075 Enumerates all printer drivers at level 3.
7076 ****************************************************************************/
7078 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7083 fstring *list = NULL;
7084 DRIVER_INFO_3 *driver_info_3=NULL;
7085 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7086 WERROR result = WERR_OK;
7090 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7092 ndrivers=get_ntdrivers(&list, architecture, version);
7093 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7095 if(ndrivers == -1) {
7096 SAFE_FREE(driver_info_3);
7101 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7102 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7108 for (i=0; i<ndrivers; i++) {
7111 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7112 ZERO_STRUCT(driver);
7113 status = get_a_printer_driver(&driver, 3, list[i],
7114 architecture, version);
7115 if (!W_ERROR_IS_OK(status)) {
7117 SAFE_FREE(driver_info_3);
7120 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7121 free_a_printer_driver(driver, 3);
7124 *returned+=ndrivers;
7128 /* check the required size. */
7129 for (i=0; i<*returned; i++) {
7130 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7131 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7134 if (*needed > offered) {
7135 result = WERR_INSUFFICIENT_BUFFER;
7139 if (!rpcbuf_alloc_size(buffer, *needed)) {
7140 result = WERR_NOMEM;
7144 /* fill the buffer with the driver structures */
7145 for (i=0; i<*returned; i++) {
7146 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7147 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7151 for (i=0; i<*returned; i++) {
7152 SAFE_FREE(driver_info_3[i].dependentfiles);
7155 SAFE_FREE(driver_info_3);
7157 if ( !W_ERROR_IS_OK(result) )
7163 /****************************************************************************
7164 Enumerates all printer drivers.
7165 ****************************************************************************/
7167 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7169 uint32 level = q_u->level;
7170 RPC_BUFFER *buffer = NULL;
7171 uint32 offered = q_u->offered;
7172 uint32 *needed = &r_u->needed;
7173 uint32 *returned = &r_u->returned;
7176 fstring architecture;
7178 /* that's an [in out] buffer */
7180 if (!q_u->buffer && (offered!=0)) {
7181 return WERR_INVALID_PARAM;
7184 rpcbuf_move(q_u->buffer, &r_u->buffer);
7185 buffer = r_u->buffer;
7187 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7192 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7193 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7195 if ( !is_myname_or_ipaddr( servername ) )
7196 return WERR_UNKNOWN_PRINTER_DRIVER;
7200 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7202 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7204 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7206 return WERR_UNKNOWN_LEVEL;
7210 /****************************************************************************
7211 ****************************************************************************/
7213 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7215 form->flag=list->flag;
7216 init_unistr(&form->name, list->name);
7217 form->width=list->width;
7218 form->length=list->length;
7219 form->left=list->left;
7220 form->top=list->top;
7221 form->right=list->right;
7222 form->bottom=list->bottom;
7225 /****************************************************************************
7226 ****************************************************************************/
7228 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7230 uint32 level = q_u->level;
7231 RPC_BUFFER *buffer = NULL;
7232 uint32 offered = q_u->offered;
7233 uint32 *needed = &r_u->needed;
7234 uint32 *numofforms = &r_u->numofforms;
7235 uint32 numbuiltinforms;
7237 nt_forms_struct *list=NULL;
7238 nt_forms_struct *builtinlist=NULL;
7243 /* that's an [in out] buffer */
7245 if (!q_u->buffer && (offered!=0) ) {
7246 return WERR_INVALID_PARAM;
7249 rpcbuf_move(q_u->buffer, &r_u->buffer);
7250 buffer = r_u->buffer;
7252 DEBUG(4,("_spoolss_enumforms\n"));
7253 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7254 DEBUGADD(5,("Info level [%d]\n", level));
7256 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7257 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7258 *numofforms = get_ntforms(&list);
7259 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7260 *numofforms += numbuiltinforms;
7262 if (*numofforms == 0) {
7263 SAFE_FREE(builtinlist);
7265 return WERR_NO_MORE_ITEMS;
7270 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7271 SAFE_FREE(builtinlist);
7277 /* construct the list of form structures */
7278 for (i=0; i<numbuiltinforms; i++) {
7279 DEBUGADD(6,("Filling form number [%d]\n",i));
7280 fill_form_1(&forms_1[i], &builtinlist[i]);
7283 SAFE_FREE(builtinlist);
7285 for (; i<*numofforms; i++) {
7286 DEBUGADD(6,("Filling form number [%d]\n",i));
7287 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7292 /* check the required size. */
7293 for (i=0; i<numbuiltinforms; i++) {
7294 DEBUGADD(6,("adding form [%d]'s size\n",i));
7295 buffer_size += spoolss_size_form_1(&forms_1[i]);
7297 for (; i<*numofforms; i++) {
7298 DEBUGADD(6,("adding form [%d]'s size\n",i));
7299 buffer_size += spoolss_size_form_1(&forms_1[i]);
7302 *needed=buffer_size;
7304 if (*needed > offered) {
7307 return WERR_INSUFFICIENT_BUFFER;
7310 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7316 /* fill the buffer with the form structures */
7317 for (i=0; i<numbuiltinforms; i++) {
7318 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7319 smb_io_form_1("", buffer, &forms_1[i], 0);
7321 for (; i<*numofforms; i++) {
7322 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7323 smb_io_form_1("", buffer, &forms_1[i], 0);
7332 SAFE_FREE(builtinlist);
7333 return WERR_UNKNOWN_LEVEL;
7337 /****************************************************************************
7338 ****************************************************************************/
7340 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7342 uint32 level = q_u->level;
7343 UNISTR2 *uni_formname = &q_u->formname;
7344 RPC_BUFFER *buffer = NULL;
7345 uint32 offered = q_u->offered;
7346 uint32 *needed = &r_u->needed;
7348 nt_forms_struct *list=NULL;
7349 nt_forms_struct builtin_form;
7354 int numofforms=0, i=0;
7356 /* that's an [in out] buffer */
7358 if (!q_u->buffer && (offered!=0)) {
7359 return WERR_INVALID_PARAM;
7362 rpcbuf_move(q_u->buffer, &r_u->buffer);
7363 buffer = r_u->buffer;
7365 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7367 DEBUG(4,("_spoolss_getform\n"));
7368 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7369 DEBUGADD(5,("Info level [%d]\n", level));
7371 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7372 if (!foundBuiltin) {
7373 numofforms = get_ntforms(&list);
7374 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7376 if (numofforms == 0)
7383 fill_form_1(&form_1, &builtin_form);
7386 /* Check if the requested name is in the list of form structures */
7387 for (i=0; i<numofforms; i++) {
7389 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7391 if (strequal(form_name, list[i].name)) {
7392 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7393 fill_form_1(&form_1, &list[i]);
7399 if (i == numofforms) {
7403 /* check the required size. */
7405 *needed=spoolss_size_form_1(&form_1);
7407 if (*needed > offered)
7408 return WERR_INSUFFICIENT_BUFFER;
7410 if (!rpcbuf_alloc_size(buffer, buffer_size))
7413 /* fill the buffer with the form structures */
7414 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7415 smb_io_form_1("", buffer, &form_1, 0);
7421 return WERR_UNKNOWN_LEVEL;
7425 /****************************************************************************
7426 ****************************************************************************/
7428 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7430 init_unistr(&port->port_name, name);
7433 /****************************************************************************
7434 TODO: This probably needs distinguish between TCP/IP and Local ports
7436 ****************************************************************************/
7438 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7440 init_unistr(&port->port_name, name);
7441 init_unistr(&port->monitor_name, "Local Monitor");
7442 init_unistr(&port->description, SPL_LOCAL_PORT );
7443 port->port_type=PORT_TYPE_WRITE;
7448 /****************************************************************************
7449 wrapper around the enumer ports command
7450 ****************************************************************************/
7452 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7454 char *cmd = lp_enumports_cmd();
7455 char **qlines = NULL;
7456 char *command = NULL;
7464 /* if no hook then just fill in the default port */
7467 if (!(qlines = SMB_MALLOC_ARRAY( char*, 2 ))) {
7470 if (!(qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME ))) {
7478 /* we have a valid enumport command */
7480 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7485 DEBUG(10,("Running [%s]\n", command));
7486 ret = smbrun(command, &fd);
7487 DEBUG(10,("Returned [%d]\n", ret));
7488 TALLOC_FREE(command);
7493 return WERR_ACCESS_DENIED;
7497 qlines = fd_lines_load(fd, &numlines, 0);
7498 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7508 /****************************************************************************
7510 ****************************************************************************/
7512 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7514 PORT_INFO_1 *ports=NULL;
7516 WERROR result = WERR_OK;
7517 char **qlines = NULL;
7520 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7521 if (!W_ERROR_IS_OK(result)) {
7522 file_lines_free(qlines);
7527 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7528 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7529 dos_errstr(WERR_NOMEM)));
7530 file_lines_free(qlines);
7534 for (i=0; i<numlines; i++) {
7535 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7536 fill_port_1(&ports[i], qlines[i]);
7539 file_lines_free(qlines);
7541 *returned = numlines;
7543 /* check the required size. */
7544 for (i=0; i<*returned; i++) {
7545 DEBUGADD(6,("adding port [%d]'s size\n", i));
7546 *needed += spoolss_size_port_info_1(&ports[i]);
7549 if (*needed > offered) {
7550 result = WERR_INSUFFICIENT_BUFFER;
7554 if (!rpcbuf_alloc_size(buffer, *needed)) {
7555 result = WERR_NOMEM;
7559 /* fill the buffer with the ports structures */
7560 for (i=0; i<*returned; i++) {
7561 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7562 smb_io_port_1("", buffer, &ports[i], 0);
7568 if ( !W_ERROR_IS_OK(result) )
7574 /****************************************************************************
7576 ****************************************************************************/
7578 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7580 PORT_INFO_2 *ports=NULL;
7582 WERROR result = WERR_OK;
7583 char **qlines = NULL;
7586 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7587 if ( !W_ERROR_IS_OK(result)) {
7588 file_lines_free(qlines);
7593 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7594 file_lines_free(qlines);
7598 for (i=0; i<numlines; i++) {
7599 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7600 fill_port_2(&(ports[i]), qlines[i]);
7604 file_lines_free(qlines);
7606 *returned = numlines;
7608 /* check the required size. */
7609 for (i=0; i<*returned; i++) {
7610 DEBUGADD(6,("adding port [%d]'s size\n", i));
7611 *needed += spoolss_size_port_info_2(&ports[i]);
7614 if (*needed > offered) {
7615 result = WERR_INSUFFICIENT_BUFFER;
7619 if (!rpcbuf_alloc_size(buffer, *needed)) {
7620 result = WERR_NOMEM;
7624 /* fill the buffer with the ports structures */
7625 for (i=0; i<*returned; i++) {
7626 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7627 smb_io_port_2("", buffer, &ports[i], 0);
7633 if ( !W_ERROR_IS_OK(result) )
7639 /****************************************************************************
7641 ****************************************************************************/
7643 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7645 uint32 level = q_u->level;
7646 RPC_BUFFER *buffer = NULL;
7647 uint32 offered = q_u->offered;
7648 uint32 *needed = &r_u->needed;
7649 uint32 *returned = &r_u->returned;
7651 /* that's an [in out] buffer */
7653 if (!q_u->buffer && (offered!=0)) {
7654 return WERR_INVALID_PARAM;
7657 rpcbuf_move(q_u->buffer, &r_u->buffer);
7658 buffer = r_u->buffer;
7660 DEBUG(4,("_spoolss_enumports\n"));
7667 return enumports_level_1(buffer, offered, needed, returned);
7669 return enumports_level_2(buffer, offered, needed, returned);
7671 return WERR_UNKNOWN_LEVEL;
7675 /****************************************************************************
7676 ****************************************************************************/
7678 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7679 const SPOOL_PRINTER_INFO_LEVEL *info,
7680 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7681 uint32 user_switch, const SPOOL_USER_CTR *user,
7684 NT_PRINTER_INFO_LEVEL *printer = NULL;
7687 WERROR err = WERR_OK;
7689 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7690 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7694 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7695 if (!convert_printer_info(info, printer, 2)) {
7696 free_a_printer(&printer, 2);
7700 /* check to see if the printer already exists */
7702 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7703 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7704 printer->info_2->sharename));
7705 free_a_printer(&printer, 2);
7706 return WERR_PRINTER_ALREADY_EXISTS;
7709 /* FIXME!!! smbd should check to see if the driver is installed before
7710 trying to add a printer like this --jerry */
7712 if (*lp_addprinter_cmd() ) {
7713 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
7714 free_a_printer(&printer,2);
7715 return WERR_ACCESS_DENIED;
7718 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7719 "smb.conf parameter \"addprinter command\" is defined. This"
7720 "parameter must exist for this call to succeed\n",
7721 printer->info_2->sharename ));
7724 /* use our primary netbios name since get_a_printer() will convert
7725 it to what the client expects on a case by case basis */
7727 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7728 printer->info_2->sharename);
7731 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7732 free_a_printer(&printer,2);
7733 return WERR_ACCESS_DENIED;
7736 /* you must be a printer admin to add a new printer */
7737 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7738 free_a_printer(&printer,2);
7739 return WERR_ACCESS_DENIED;
7743 * Do sanity check on the requested changes for Samba.
7746 if (!check_printer_ok(printer->info_2, snum)) {
7747 free_a_printer(&printer,2);
7748 return WERR_INVALID_PARAM;
7752 * When a printer is created, the drivername bound to the printer is used
7753 * to lookup previously saved driver initialization info, which is then
7754 * bound to the new printer, simulating what happens in the Windows arch.
7759 set_driver_init(printer, 2);
7763 /* A valid devmode was included, convert and link it
7765 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7767 if (!convert_devicemode(printer->info_2->printername, devmode,
7768 &printer->info_2->devmode))
7772 /* write the ASCII on disk */
7773 err = mod_a_printer(printer, 2);
7774 if (!W_ERROR_IS_OK(err)) {
7775 free_a_printer(&printer,2);
7779 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7780 /* Handle open failed - remove addition. */
7781 del_a_printer(printer->info_2->sharename);
7782 free_a_printer(&printer,2);
7783 return WERR_ACCESS_DENIED;
7786 update_c_setprinter(False);
7787 free_a_printer(&printer,2);
7792 /****************************************************************************
7793 ****************************************************************************/
7795 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7797 UNISTR2 *uni_srv_name = q_u->server_name;
7798 uint32 level = q_u->level;
7799 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7800 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7801 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7802 uint32 user_switch = q_u->user_switch;
7803 SPOOL_USER_CTR *user = &q_u->user_ctr;
7804 POLICY_HND *handle = &r_u->handle;
7808 /* we don't handle yet */
7809 /* but I know what to do ... */
7810 return WERR_UNKNOWN_LEVEL;
7812 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7814 user_switch, user, handle);
7816 return WERR_UNKNOWN_LEVEL;
7820 /****************************************************************************
7821 ****************************************************************************/
7823 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7825 uint32 level = q_u->level;
7826 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7827 WERROR err = WERR_OK;
7828 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7829 fstring driver_name;
7832 ZERO_STRUCT(driver);
7834 if (!convert_printer_driver_info(info, &driver, level)) {
7839 DEBUG(5,("Cleaning driver's information\n"));
7840 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7841 if (!W_ERROR_IS_OK(err))
7844 DEBUG(5,("Moving driver to final destination\n"));
7845 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7849 if (add_a_printer_driver(driver, level)!=0) {
7850 err = WERR_ACCESS_DENIED;
7855 * I think this is where he DrvUpgradePrinter() hook would be
7856 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7857 * server. Right now, we just need to send ourselves a message
7858 * to update each printer bound to this driver. --jerry
7861 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7862 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7867 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7868 * decide if the driver init data should be deleted. The rules are:
7869 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7870 * 2) delete init data only if there is no 2k/Xp driver
7871 * 3) always delete init data
7872 * The generalized rule is always use init data from the highest order driver.
7873 * It is necessary to follow the driver install by an initialization step to
7874 * finish off this process.
7877 version = driver.info_3->cversion;
7878 else if (level == 6)
7879 version = driver.info_6->version;
7884 * 9x printer driver - never delete init data
7887 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7892 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7893 * there is no 2k/Xp driver init data for this driver name.
7897 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7899 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7901 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7903 if (!del_driver_init(driver_name))
7904 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7907 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7909 free_a_printer_driver(driver1,3);
7910 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7917 * 2k or Xp printer driver - always delete init data
7920 if (!del_driver_init(driver_name))
7921 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7925 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7931 free_a_printer_driver(driver, level);
7935 /********************************************************************
7936 * spoolss_addprinterdriverex
7937 ********************************************************************/
7939 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7941 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7942 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7945 * we only support the semantics of AddPrinterDriver()
7946 * i.e. only copy files that are newer than existing ones
7949 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7950 return WERR_ACCESS_DENIED;
7952 ZERO_STRUCT(q_u_local);
7953 ZERO_STRUCT(r_u_local);
7955 /* just pass the information off to _spoolss_addprinterdriver() */
7956 q_u_local.server_name_ptr = q_u->server_name_ptr;
7957 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7958 q_u_local.level = q_u->level;
7959 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7961 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7964 /****************************************************************************
7965 ****************************************************************************/
7967 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7969 init_unistr(&info->name, name);
7972 /****************************************************************************
7973 ****************************************************************************/
7975 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7978 char *long_archi = NULL;
7979 char *servername = NULL;
7980 char *pservername = NULL;
7981 const char *short_archi;
7982 DRIVER_DIRECTORY_1 *info=NULL;
7983 WERROR result = WERR_OK;
7984 TALLOC_CTX *ctx = talloc_tos();
7986 servername = unistr2_to_ascii_talloc(ctx, name);
7990 long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
7995 /* check for beginning double '\'s and that the server
7998 pservername = servername;
7999 if ( *pservername == '\\' && strlen(servername)>2 ) {
8003 if ( !is_myname_or_ipaddr( pservername ) )
8004 return WERR_INVALID_PARAM;
8006 if (!(short_archi = get_short_archi(long_archi)))
8007 return WERR_INVALID_ENVIRONMENT;
8009 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8012 path = talloc_asprintf(ctx,
8013 "\\\\%s\\print$\\%s", pservername, short_archi);
8015 result = WERR_NOMEM;
8019 DEBUG(4,("printer driver directory: [%s]\n", path));
8021 fill_driverdir_1(info, path);
8023 *needed += spoolss_size_driverdir_info_1(info);
8025 if (*needed > offered) {
8026 result = WERR_INSUFFICIENT_BUFFER;
8030 if (!rpcbuf_alloc_size(buffer, *needed)) {
8031 result = WERR_NOMEM;
8035 smb_io_driverdir_1("", buffer, info, 0);
8043 /****************************************************************************
8044 ****************************************************************************/
8046 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8048 UNISTR2 *name = &q_u->name;
8049 UNISTR2 *uni_environment = &q_u->environment;
8050 uint32 level = q_u->level;
8051 RPC_BUFFER *buffer = NULL;
8052 uint32 offered = q_u->offered;
8053 uint32 *needed = &r_u->needed;
8055 /* that's an [in out] buffer */
8057 if (!q_u->buffer && (offered!=0)) {
8058 return WERR_INVALID_PARAM;
8061 rpcbuf_move(q_u->buffer, &r_u->buffer);
8062 buffer = r_u->buffer;
8064 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8070 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8072 return WERR_UNKNOWN_LEVEL;
8076 /****************************************************************************
8077 ****************************************************************************/
8079 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8081 POLICY_HND *handle = &q_u->handle;
8082 uint32 idx = q_u->index;
8083 uint32 in_value_len = q_u->valuesize;
8084 uint32 in_data_len = q_u->datasize;
8085 uint32 *out_max_value_len = &r_u->valuesize;
8086 uint16 **out_value = &r_u->value;
8087 uint32 *out_value_len = &r_u->realvaluesize;
8088 uint32 *out_type = &r_u->type;
8089 uint32 *out_max_data_len = &r_u->datasize;
8090 uint8 **data_out = &r_u->data;
8091 uint32 *out_data_len = &r_u->realdatasize;
8093 NT_PRINTER_INFO_LEVEL *printer = NULL;
8095 uint32 biggest_valuesize;
8096 uint32 biggest_datasize;
8098 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8101 REGISTRY_VALUE *val = NULL;
8102 NT_PRINTER_DATA *p_data;
8103 int i, key_index, num_values;
8108 *out_max_data_len = 0;
8112 DEBUG(5,("spoolss_enumprinterdata\n"));
8115 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8119 if (!get_printer_snum(p,handle, &snum, NULL))
8122 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8123 if (!W_ERROR_IS_OK(result))
8126 p_data = printer->info_2->data;
8127 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8132 * The NT machine wants to know the biggest size of value and data
8134 * cf: MSDN EnumPrinterData remark section
8137 if ( !in_value_len && !in_data_len && (key_index != -1) )
8139 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8141 biggest_valuesize = 0;
8142 biggest_datasize = 0;
8144 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8146 for ( i=0; i<num_values; i++ )
8148 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8150 name_length = strlen(val->valuename);
8151 if ( strlen(val->valuename) > biggest_valuesize )
8152 biggest_valuesize = name_length;
8154 if ( val->size > biggest_datasize )
8155 biggest_datasize = val->size;
8157 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8161 /* the value is an UNICODE string but real_value_size is the length
8162 in bytes including the trailing 0 */
8164 *out_value_len = 2 * (1+biggest_valuesize);
8165 *out_data_len = biggest_datasize;
8167 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8173 * the value len is wrong in NT sp3
8174 * that's the number of bytes not the number of unicode chars
8177 if ( key_index != -1 )
8178 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8183 /* out_value should default to "" or else NT4 has
8184 problems unmarshalling the response */
8186 *out_max_value_len=(in_value_len/sizeof(uint16));
8189 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8191 result = WERR_NOMEM;
8194 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8200 /* the data is counted in bytes */
8202 *out_max_data_len = in_data_len;
8203 *out_data_len = in_data_len;
8205 /* only allocate when given a non-zero data_len */
8207 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8209 result = WERR_NOMEM;
8213 result = WERR_NO_MORE_ITEMS;
8219 * - counted in bytes in the request
8220 * - counted in UNICODE chars in the max reply
8221 * - counted in bytes in the real size
8223 * take a pause *before* coding not *during* coding
8227 *out_max_value_len=(in_value_len/sizeof(uint16));
8229 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8231 result = WERR_NOMEM;
8235 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8243 *out_type = regval_type( val );
8245 /* data - counted in bytes */
8247 *out_max_data_len = in_data_len;
8248 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8250 result = WERR_NOMEM;
8253 data_len = regval_size(val);
8254 if ( *data_out && data_len )
8255 memcpy( *data_out, regval_data_p(val), data_len );
8256 *out_data_len = data_len;
8260 free_a_printer(&printer, 2);
8264 /****************************************************************************
8265 ****************************************************************************/
8267 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8269 POLICY_HND *handle = &q_u->handle;
8270 UNISTR2 *value = &q_u->value;
8271 uint32 type = q_u->type;
8272 uint8 *data = q_u->data;
8273 uint32 real_len = q_u->real_len;
8275 NT_PRINTER_INFO_LEVEL *printer = NULL;
8277 WERROR status = WERR_OK;
8278 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8281 DEBUG(5,("spoolss_setprinterdata\n"));
8284 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8288 if ( Printer->printer_type == SPLHND_SERVER ) {
8289 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8290 return WERR_INVALID_PARAM;
8293 if (!get_printer_snum(p,handle, &snum, NULL))
8297 * Access check : NT returns "access denied" if you make a
8298 * SetPrinterData call without the necessary privildge.
8299 * we were originally returning OK if nothing changed
8300 * which made Win2k issue **a lot** of SetPrinterData
8301 * when connecting to a printer --jerry
8304 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8306 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8307 status = WERR_ACCESS_DENIED;
8311 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8312 if (!W_ERROR_IS_OK(status))
8315 unistr2_to_ascii(valuename, value, sizeof(valuename));
8318 * When client side code sets a magic printer data key, detect it and save
8319 * the current printer data and the magic key's data (its the DEVMODE) for
8320 * future printer/driver initializations.
8322 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8324 /* Set devmode and printer initialization info */
8325 status = save_driver_init( printer, 2, data, real_len );
8327 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8331 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8332 type, data, real_len );
8333 if ( W_ERROR_IS_OK(status) )
8334 status = mod_a_printer(printer, 2);
8338 free_a_printer(&printer, 2);
8343 /****************************************************************************
8344 ****************************************************************************/
8346 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8348 POLICY_HND *handle = &q_u->handle;
8349 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8352 DEBUG(5,("_spoolss_resetprinter\n"));
8355 * All we do is to check to see if the handle and queue is valid.
8356 * This call really doesn't mean anything to us because we only
8357 * support RAW printing. --jerry
8361 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8365 if (!get_printer_snum(p,handle, &snum, NULL))
8369 /* blindly return success */
8374 /****************************************************************************
8375 ****************************************************************************/
8377 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8379 POLICY_HND *handle = &q_u->handle;
8380 UNISTR2 *value = &q_u->valuename;
8382 NT_PRINTER_INFO_LEVEL *printer = NULL;
8384 WERROR status = WERR_OK;
8385 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8386 char *valuename = NULL;
8387 TALLOC_CTX *ctx = p->mem_ctx;
8389 DEBUG(5,("spoolss_deleteprinterdata\n"));
8392 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8396 if (!get_printer_snum(p, handle, &snum, NULL))
8399 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8400 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8401 return WERR_ACCESS_DENIED;
8404 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8405 if (!W_ERROR_IS_OK(status))
8408 valuename = unistr2_to_ascii_talloc(ctx, value);
8410 free_a_printer(&printer, 2);
8414 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8416 if ( W_ERROR_IS_OK(status) )
8417 mod_a_printer( printer, 2 );
8419 free_a_printer(&printer, 2);
8420 TALLOC_FREE(valuename);
8425 /****************************************************************************
8426 ****************************************************************************/
8428 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8430 POLICY_HND *handle = &q_u->handle;
8431 FORM *form = &q_u->form;
8432 nt_forms_struct tmpForm;
8434 WERROR status = WERR_OK;
8435 NT_PRINTER_INFO_LEVEL *printer = NULL;
8438 nt_forms_struct *list=NULL;
8439 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8441 DEBUG(5,("spoolss_addform\n"));
8444 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8449 /* forms can be added on printer of on the print server handle */
8451 if ( Printer->printer_type == SPLHND_PRINTER )
8453 if (!get_printer_snum(p,handle, &snum, NULL))
8456 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8457 if (!W_ERROR_IS_OK(status))
8461 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8462 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8463 status = WERR_ACCESS_DENIED;
8467 /* can't add if builtin */
8469 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8470 status = WERR_ALREADY_EXISTS;
8474 count = get_ntforms(&list);
8476 if(!add_a_form(&list, form, &count)) {
8477 status = WERR_NOMEM;
8481 write_ntforms(&list, count);
8484 * ChangeID must always be set if this is a printer
8487 if ( Printer->printer_type == SPLHND_PRINTER )
8488 status = mod_a_printer(printer, 2);
8492 free_a_printer(&printer, 2);
8498 /****************************************************************************
8499 ****************************************************************************/
8501 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8503 POLICY_HND *handle = &q_u->handle;
8504 UNISTR2 *form_name = &q_u->name;
8505 nt_forms_struct tmpForm;
8507 nt_forms_struct *list=NULL;
8508 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8510 WERROR status = WERR_OK;
8511 NT_PRINTER_INFO_LEVEL *printer = NULL;
8513 DEBUG(5,("spoolss_deleteform\n"));
8516 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8520 /* forms can be deleted on printer of on the print server handle */
8522 if ( Printer->printer_type == SPLHND_PRINTER )
8524 if (!get_printer_snum(p,handle, &snum, NULL))
8527 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8528 if (!W_ERROR_IS_OK(status))
8532 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8533 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8534 status = WERR_ACCESS_DENIED;
8538 /* can't delete if builtin */
8540 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8541 status = WERR_INVALID_PARAM;
8545 count = get_ntforms(&list);
8547 if ( !delete_a_form(&list, form_name, &count, &status ))
8551 * ChangeID must always be set if this is a printer
8554 if ( Printer->printer_type == SPLHND_PRINTER )
8555 status = mod_a_printer(printer, 2);
8559 free_a_printer(&printer, 2);
8565 /****************************************************************************
8566 ****************************************************************************/
8568 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8570 POLICY_HND *handle = &q_u->handle;
8571 FORM *form = &q_u->form;
8572 nt_forms_struct tmpForm;
8574 WERROR status = WERR_OK;
8575 NT_PRINTER_INFO_LEVEL *printer = NULL;
8578 nt_forms_struct *list=NULL;
8579 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8581 DEBUG(5,("spoolss_setform\n"));
8584 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8588 /* forms can be modified on printer of on the print server handle */
8590 if ( Printer->printer_type == SPLHND_PRINTER )
8592 if (!get_printer_snum(p,handle, &snum, NULL))
8595 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8596 if (!W_ERROR_IS_OK(status))
8600 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8601 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8602 status = WERR_ACCESS_DENIED;
8606 /* can't set if builtin */
8607 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8608 status = WERR_INVALID_PARAM;
8612 count = get_ntforms(&list);
8613 update_a_form(&list, form, count);
8614 write_ntforms(&list, count);
8617 * ChangeID must always be set if this is a printer
8620 if ( Printer->printer_type == SPLHND_PRINTER )
8621 status = mod_a_printer(printer, 2);
8626 free_a_printer(&printer, 2);
8632 /****************************************************************************
8633 enumprintprocessors level 1.
8634 ****************************************************************************/
8636 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8638 PRINTPROCESSOR_1 *info_1=NULL;
8639 WERROR result = WERR_OK;
8641 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8646 init_unistr(&info_1->name, "winprint");
8648 *needed += spoolss_size_printprocessor_info_1(info_1);
8650 if (*needed > offered) {
8651 result = WERR_INSUFFICIENT_BUFFER;
8655 if (!rpcbuf_alloc_size(buffer, *needed)) {
8656 result = WERR_NOMEM;
8660 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8665 if ( !W_ERROR_IS_OK(result) )
8671 /****************************************************************************
8672 ****************************************************************************/
8674 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8676 uint32 level = q_u->level;
8677 RPC_BUFFER *buffer = NULL;
8678 uint32 offered = q_u->offered;
8679 uint32 *needed = &r_u->needed;
8680 uint32 *returned = &r_u->returned;
8682 /* that's an [in out] buffer */
8684 if (!q_u->buffer && (offered!=0)) {
8685 return WERR_INVALID_PARAM;
8688 rpcbuf_move(q_u->buffer, &r_u->buffer);
8689 buffer = r_u->buffer;
8691 DEBUG(5,("spoolss_enumprintprocessors\n"));
8694 * Enumerate the print processors ...
8696 * Just reply with "winprint", to keep NT happy
8697 * and I can use my nice printer checker.
8705 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8707 return WERR_UNKNOWN_LEVEL;
8711 /****************************************************************************
8712 enumprintprocdatatypes level 1.
8713 ****************************************************************************/
8715 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8717 PRINTPROCDATATYPE_1 *info_1=NULL;
8718 WERROR result = WERR_OK;
8720 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8725 init_unistr(&info_1->name, "RAW");
8727 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8729 if (*needed > offered) {
8730 result = WERR_INSUFFICIENT_BUFFER;
8734 if (!rpcbuf_alloc_size(buffer, *needed)) {
8735 result = WERR_NOMEM;
8739 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8744 if ( !W_ERROR_IS_OK(result) )
8750 /****************************************************************************
8751 ****************************************************************************/
8753 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8755 uint32 level = q_u->level;
8756 RPC_BUFFER *buffer = NULL;
8757 uint32 offered = q_u->offered;
8758 uint32 *needed = &r_u->needed;
8759 uint32 *returned = &r_u->returned;
8761 /* that's an [in out] buffer */
8763 if (!q_u->buffer && (offered!=0)) {
8764 return WERR_INVALID_PARAM;
8767 rpcbuf_move(q_u->buffer, &r_u->buffer);
8768 buffer = r_u->buffer;
8770 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8777 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8779 return WERR_UNKNOWN_LEVEL;
8783 /****************************************************************************
8784 enumprintmonitors level 1.
8785 ****************************************************************************/
8787 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8789 PRINTMONITOR_1 *info_1;
8790 WERROR result = WERR_OK;
8793 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8798 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8799 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8801 for ( i=0; i<*returned; i++ ) {
8802 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8805 if (*needed > offered) {
8806 result = WERR_INSUFFICIENT_BUFFER;
8810 if (!rpcbuf_alloc_size(buffer, *needed)) {
8811 result = WERR_NOMEM;
8815 for ( i=0; i<*returned; i++ ) {
8816 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8822 if ( !W_ERROR_IS_OK(result) )
8828 /****************************************************************************
8829 enumprintmonitors level 2.
8830 ****************************************************************************/
8832 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8834 PRINTMONITOR_2 *info_2;
8835 WERROR result = WERR_OK;
8838 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8843 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8844 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8845 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8847 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8848 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8849 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8851 for ( i=0; i<*returned; i++ ) {
8852 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8855 if (*needed > offered) {
8856 result = WERR_INSUFFICIENT_BUFFER;
8860 if (!rpcbuf_alloc_size(buffer, *needed)) {
8861 result = WERR_NOMEM;
8865 for ( i=0; i<*returned; i++ ) {
8866 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8872 if ( !W_ERROR_IS_OK(result) )
8878 /****************************************************************************
8879 ****************************************************************************/
8881 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8883 uint32 level = q_u->level;
8884 RPC_BUFFER *buffer = NULL;
8885 uint32 offered = q_u->offered;
8886 uint32 *needed = &r_u->needed;
8887 uint32 *returned = &r_u->returned;
8889 /* that's an [in out] buffer */
8891 if (!q_u->buffer && (offered!=0)) {
8892 return WERR_INVALID_PARAM;
8895 rpcbuf_move(q_u->buffer, &r_u->buffer);
8896 buffer = r_u->buffer;
8898 DEBUG(5,("spoolss_enumprintmonitors\n"));
8901 * Enumerate the print monitors ...
8903 * Just reply with "Local Port", to keep NT happy
8904 * and I can use my nice printer checker.
8912 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8914 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8916 return WERR_UNKNOWN_LEVEL;
8920 /****************************************************************************
8921 ****************************************************************************/
8923 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8924 NT_PRINTER_INFO_LEVEL *ntprinter,
8925 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8930 JOB_INFO_1 *info_1=NULL;
8931 WERROR result = WERR_OK;
8933 info_1=SMB_MALLOC_P(JOB_INFO_1);
8935 if (info_1 == NULL) {
8939 for (i=0; i<count && found==False; i++) {
8940 if ((*queue)[i].job==(int)jobid)
8946 /* NT treats not found as bad param... yet another bad choice */
8947 return WERR_INVALID_PARAM;
8950 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8952 *needed += spoolss_size_job_info_1(info_1);
8954 if (*needed > offered) {
8955 result = WERR_INSUFFICIENT_BUFFER;
8959 if (!rpcbuf_alloc_size(buffer, *needed)) {
8960 result = WERR_NOMEM;
8964 smb_io_job_info_1("", buffer, info_1, 0);
8972 /****************************************************************************
8973 ****************************************************************************/
8975 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8976 NT_PRINTER_INFO_LEVEL *ntprinter,
8977 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8984 DEVICEMODE *devmode = NULL;
8985 NT_DEVICEMODE *nt_devmode = NULL;
8987 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8990 ZERO_STRUCTP(info_2);
8992 for ( i=0; i<count && found==False; i++ )
8994 if ((*queue)[i].job == (int)jobid)
8999 /* NT treats not found as bad param... yet another bad
9001 result = WERR_INVALID_PARAM;
9006 * if the print job does not have a DEVMODE associated with it,
9007 * just use the one for the printer. A NULL devicemode is not
9008 * a failure condition
9011 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9012 devmode = construct_dev_mode(lp_const_servicename(snum));
9014 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9015 ZERO_STRUCTP( devmode );
9016 convert_nt_devicemode( devmode, nt_devmode );
9020 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9022 *needed += spoolss_size_job_info_2(info_2);
9024 if (*needed > offered) {
9025 result = WERR_INSUFFICIENT_BUFFER;
9029 if (!rpcbuf_alloc_size(buffer, *needed)) {
9030 result = WERR_NOMEM;
9034 smb_io_job_info_2("", buffer, info_2, 0);
9039 /* Cleanup allocated memory */
9041 free_job_info_2(info_2); /* Also frees devmode */
9047 /****************************************************************************
9048 ****************************************************************************/
9050 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9052 POLICY_HND *handle = &q_u->handle;
9053 uint32 jobid = q_u->jobid;
9054 uint32 level = q_u->level;
9055 RPC_BUFFER *buffer = NULL;
9056 uint32 offered = q_u->offered;
9057 uint32 *needed = &r_u->needed;
9058 WERROR wstatus = WERR_OK;
9059 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9062 print_queue_struct *queue = NULL;
9063 print_status_struct prt_status;
9065 /* that's an [in out] buffer */
9067 if (!q_u->buffer && (offered!=0)) {
9068 return WERR_INVALID_PARAM;
9071 rpcbuf_move(q_u->buffer, &r_u->buffer);
9072 buffer = r_u->buffer;
9074 DEBUG(5,("spoolss_getjob\n"));
9078 if (!get_printer_snum(p, handle, &snum, NULL))
9081 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9082 if ( !W_ERROR_IS_OK(wstatus) )
9085 count = print_queue_status(snum, &queue, &prt_status);
9087 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9088 count, prt_status.status, prt_status.message));
9092 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9093 buffer, offered, needed);
9096 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9097 buffer, offered, needed);
9100 wstatus = WERR_UNKNOWN_LEVEL;
9105 free_a_printer( &ntprinter, 2 );
9110 /********************************************************************
9111 spoolss_getprinterdataex
9113 From MSDN documentation of GetPrinterDataEx: pass request
9114 to GetPrinterData if key is "PrinterDriverData".
9115 ********************************************************************/
9117 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9119 POLICY_HND *handle = &q_u->handle;
9120 uint32 in_size = q_u->size;
9121 uint32 *type = &r_u->type;
9122 uint32 *out_size = &r_u->size;
9123 uint8 **data = &r_u->data;
9124 uint32 *needed = &r_u->needed;
9125 fstring keyname, valuename;
9127 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9129 NT_PRINTER_INFO_LEVEL *printer = NULL;
9131 WERROR status = WERR_OK;
9133 DEBUG(4,("_spoolss_getprinterdataex\n"));
9135 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9136 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9138 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9139 keyname, valuename));
9141 /* in case of problem, return some default values */
9145 *out_size = in_size;
9148 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9149 status = WERR_BADFID;
9153 /* Is the handle to a printer or to the server? */
9155 if (Printer->printer_type == SPLHND_SERVER) {
9156 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9157 status = WERR_INVALID_PARAM;
9161 if ( !get_printer_snum(p,handle, &snum, NULL) )
9164 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9165 if ( !W_ERROR_IS_OK(status) )
9168 /* check to see if the keyname is valid */
9169 if ( !strlen(keyname) ) {
9170 status = WERR_INVALID_PARAM;
9174 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9175 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9176 free_a_printer( &printer, 2 );
9177 status = WERR_BADFILE;
9181 /* When given a new keyname, we should just create it */
9183 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9185 if (*needed > *out_size)
9186 status = WERR_MORE_DATA;
9189 if ( !W_ERROR_IS_OK(status) )
9191 DEBUG(5, ("error: allocating %d\n", *out_size));
9193 /* reply this param doesn't exist */
9197 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9198 status = WERR_NOMEM;
9207 free_a_printer( &printer, 2 );
9212 /********************************************************************
9213 * spoolss_setprinterdataex
9214 ********************************************************************/
9216 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9218 POLICY_HND *handle = &q_u->handle;
9219 uint32 type = q_u->type;
9220 uint8 *data = q_u->data;
9221 uint32 real_len = q_u->real_len;
9223 NT_PRINTER_INFO_LEVEL *printer = NULL;
9225 WERROR status = WERR_OK;
9226 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9231 DEBUG(4,("_spoolss_setprinterdataex\n"));
9233 /* From MSDN documentation of SetPrinterDataEx: pass request to
9234 SetPrinterData if key is "PrinterDriverData" */
9237 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9241 if ( Printer->printer_type == SPLHND_SERVER ) {
9242 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9243 return WERR_INVALID_PARAM;
9246 if ( !get_printer_snum(p,handle, &snum, NULL) )
9250 * Access check : NT returns "access denied" if you make a
9251 * SetPrinterData call without the necessary privildge.
9252 * we were originally returning OK if nothing changed
9253 * which made Win2k issue **a lot** of SetPrinterData
9254 * when connecting to a printer --jerry
9257 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9259 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9260 return WERR_ACCESS_DENIED;
9263 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9264 if (!W_ERROR_IS_OK(status))
9267 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9268 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9270 /* check for OID in valuename */
9272 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9278 /* save the registry data */
9280 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9282 if ( W_ERROR_IS_OK(status) )
9284 /* save the OID if one was specified */
9286 fstrcat( keyname, "\\" );
9287 fstrcat( keyname, SPOOL_OID_KEY );
9290 * I'm not checking the status here on purpose. Don't know
9291 * if this is right, but I'm returning the status from the
9292 * previous set_printer_dataex() call. I have no idea if
9293 * this is right. --jerry
9296 set_printer_dataex( printer, keyname, valuename,
9297 REG_SZ, (uint8 *)oid_string,
9298 strlen(oid_string)+1 );
9301 status = mod_a_printer(printer, 2);
9304 free_a_printer(&printer, 2);
9310 /********************************************************************
9311 * spoolss_deleteprinterdataex
9312 ********************************************************************/
9314 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9316 POLICY_HND *handle = &q_u->handle;
9317 UNISTR2 *value = &q_u->valuename;
9318 UNISTR2 *key = &q_u->keyname;
9320 NT_PRINTER_INFO_LEVEL *printer = NULL;
9322 WERROR status = WERR_OK;
9323 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9324 char *valuename = NULL;
9325 char *keyname = NULL;
9326 TALLOC_CTX *ctx = p->mem_ctx;
9328 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9331 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9335 if (!get_printer_snum(p, handle, &snum, NULL))
9338 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9339 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9340 return WERR_ACCESS_DENIED;
9343 valuename = unistr2_to_ascii_talloc(ctx, value);
9344 keyname = unistr2_to_ascii_talloc(ctx, key);
9345 if (!valuename || !keyname) {
9349 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9350 if (!W_ERROR_IS_OK(status))
9353 status = delete_printer_dataex( printer, keyname, valuename );
9355 if ( W_ERROR_IS_OK(status) )
9356 mod_a_printer( printer, 2 );
9358 free_a_printer(&printer, 2);
9363 /********************************************************************
9364 * spoolss_enumprinterkey
9365 ********************************************************************/
9368 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9371 fstring *keynames = NULL;
9372 uint16 *enumkeys = NULL;
9375 POLICY_HND *handle = &q_u->handle;
9376 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9377 NT_PRINTER_DATA *data;
9378 NT_PRINTER_INFO_LEVEL *printer = NULL;
9380 WERROR status = WERR_BADFILE;
9383 DEBUG(4,("_spoolss_enumprinterkey\n"));
9386 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9390 if ( !get_printer_snum(p,handle, &snum, NULL) )
9393 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9394 if (!W_ERROR_IS_OK(status))
9397 /* get the list of subkey names */
9399 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9400 data = printer->info_2->data;
9402 num_keys = get_printer_subkeys( data, key, &keynames );
9404 if ( num_keys == -1 ) {
9405 status = WERR_BADFILE;
9409 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9411 r_u->needed = printerkey_len*2;
9413 if ( q_u->size < r_u->needed ) {
9414 status = WERR_MORE_DATA;
9418 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9419 status = WERR_NOMEM;
9425 if ( q_u->size < r_u->needed )
9426 status = WERR_MORE_DATA;
9429 free_a_printer( &printer, 2 );
9430 SAFE_FREE( keynames );
9435 /********************************************************************
9436 * spoolss_deleteprinterkey
9437 ********************************************************************/
9439 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9441 POLICY_HND *handle = &q_u->handle;
9442 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9444 NT_PRINTER_INFO_LEVEL *printer = NULL;
9448 DEBUG(5,("spoolss_deleteprinterkey\n"));
9451 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9455 /* if keyname == NULL, return error */
9457 if ( !q_u->keyname.buffer )
9458 return WERR_INVALID_PARAM;
9460 if (!get_printer_snum(p, handle, &snum, NULL))
9463 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9464 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9465 return WERR_ACCESS_DENIED;
9468 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9469 if (!W_ERROR_IS_OK(status))
9472 /* delete the key and all subneys */
9474 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9476 status = delete_all_printer_data( printer->info_2, key );
9478 if ( W_ERROR_IS_OK(status) )
9479 status = mod_a_printer(printer, 2);
9481 free_a_printer( &printer, 2 );
9487 /********************************************************************
9488 * spoolss_enumprinterdataex
9489 ********************************************************************/
9491 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9493 POLICY_HND *handle = &q_u->handle;
9494 uint32 in_size = q_u->size;
9497 NT_PRINTER_INFO_LEVEL *printer = NULL;
9498 PRINTER_ENUM_VALUES *enum_values = NULL;
9499 NT_PRINTER_DATA *p_data;
9501 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9506 REGISTRY_VALUE *val;
9511 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9514 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9519 * first check for a keyname of NULL or "". Win2k seems to send
9520 * this a lot and we should send back WERR_INVALID_PARAM
9521 * no need to spend time looking up the printer in this case.
9525 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9526 if ( !strlen(key) ) {
9527 result = WERR_INVALID_PARAM;
9531 /* get the printer off of disk */
9533 if (!get_printer_snum(p,handle, &snum, NULL))
9536 ZERO_STRUCT(printer);
9537 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9538 if (!W_ERROR_IS_OK(result))
9541 /* now look for a match on the key name */
9543 p_data = printer->info_2->data;
9545 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9546 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9548 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9549 result = WERR_INVALID_PARAM;
9556 /* allocate the memory for the array of pointers -- if necessary */
9558 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9561 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9563 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9564 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9565 result = WERR_NOMEM;
9569 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9573 * loop through all params and build the array to pass
9574 * back to the client
9577 for ( i=0; i<num_entries; i++ )
9579 /* lookup the registry value */
9581 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9582 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9586 value_name = regval_name( val );
9587 init_unistr( &enum_values[i].valuename, value_name );
9588 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9589 enum_values[i].type = regval_type( val );
9591 data_len = regval_size( val );
9593 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9595 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9597 result = WERR_NOMEM;
9601 enum_values[i].data_len = data_len;
9603 /* keep track of the size of the array in bytes */
9605 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9608 /* housekeeping information in the reply */
9610 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9611 * the hand marshalled container size is a multiple
9612 * of 4 bytes for RPC alignment.
9616 needed += 4-(needed % 4);
9619 r_u->needed = needed;
9620 r_u->returned = num_entries;
9622 if (needed > in_size) {
9623 result = WERR_MORE_DATA;
9627 /* copy data into the reply */
9629 r_u->ctr.size = r_u->needed;
9631 r_u->ctr.size_of_array = r_u->returned;
9632 r_u->ctr.values = enum_values;
9638 free_a_printer(&printer, 2);
9643 /****************************************************************************
9644 ****************************************************************************/
9646 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9648 init_unistr(&info->name, name);
9651 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9652 UNISTR2 *environment,
9657 char *long_archi = NULL;
9658 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9659 WERROR result = WERR_OK;
9660 TALLOC_CTX *ctx = talloc_tos();
9662 long_archi = unistr2_to_ascii_talloc(ctx, environment);
9667 if (!get_short_archi(long_archi))
9668 return WERR_INVALID_ENVIRONMENT;
9670 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9673 fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9675 *needed += spoolss_size_printprocessordirectory_info_1(info);
9677 if (*needed > offered) {
9678 result = WERR_INSUFFICIENT_BUFFER;
9682 if (!rpcbuf_alloc_size(buffer, *needed)) {
9683 result = WERR_INSUFFICIENT_BUFFER;
9687 smb_io_printprocessordirectory_1("", buffer, info, 0);
9695 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9697 uint32 level = q_u->level;
9698 RPC_BUFFER *buffer = NULL;
9699 uint32 offered = q_u->offered;
9700 uint32 *needed = &r_u->needed;
9703 /* that's an [in out] buffer */
9705 if (!q_u->buffer && (offered!=0)) {
9706 return WERR_INVALID_PARAM;
9709 rpcbuf_move(q_u->buffer, &r_u->buffer);
9710 buffer = r_u->buffer;
9712 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9718 result = getprintprocessordirectory_level_1
9719 (&q_u->name, &q_u->environment, buffer, offered, needed);
9722 result = WERR_UNKNOWN_LEVEL;
9728 /*******************************************************************
9729 Streams the monitor UI DLL name in UNICODE
9730 *******************************************************************/
9732 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9733 RPC_BUFFER *out, uint32 *needed )
9735 const char *dllname = "tcpmonui.dll";
9737 *needed = (strlen(dllname)+1) * 2;
9739 if ( rpcbuf_get_size(out) < *needed ) {
9740 return WERR_INSUFFICIENT_BUFFER;
9743 if ( !make_monitorui_buf( out, dllname ) ) {
9750 /*******************************************************************
9751 Create a new TCP/IP port
9752 *******************************************************************/
9754 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9755 RPC_BUFFER *out, uint32 *needed )
9757 NT_PORT_DATA_1 port1;
9758 TALLOC_CTX *ctx = talloc_tos();
9759 char *device_uri = NULL;
9761 ZERO_STRUCT( port1 );
9763 /* convert to our internal port data structure */
9765 if ( !convert_port_data_1( &port1, in ) ) {
9769 /* create the device URI and call the add_port_hook() */
9771 switch ( port1.protocol ) {
9772 case PORT_PROTOCOL_DIRECT:
9773 device_uri = talloc_asprintf(ctx,
9774 "socket://%s:%d/", port1.hostaddr, port1.port );
9777 case PORT_PROTOCOL_LPR:
9778 device_uri = talloc_asprintf(ctx,
9779 "lpr://%s/%s", port1.hostaddr, port1.queue );
9783 return WERR_UNKNOWN_PORT;
9790 return add_port_hook(ctx, token, port1.name, device_uri );
9793 /*******************************************************************
9794 *******************************************************************/
9796 struct xcv_api_table xcvtcp_cmds[] = {
9797 { "MonitorUI", xcvtcp_monitorui },
9798 { "AddPort", xcvtcp_addport},
9802 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9803 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9808 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9810 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9811 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9812 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9815 return WERR_BADFUNC;
9818 /*******************************************************************
9819 *******************************************************************/
9820 #if 0 /* don't support management using the "Local Port" monitor */
9822 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9823 RPC_BUFFER *out, uint32 *needed )
9825 const char *dllname = "localui.dll";
9827 *needed = (strlen(dllname)+1) * 2;
9829 if ( rpcbuf_get_size(out) < *needed ) {
9830 return WERR_INSUFFICIENT_BUFFER;
9833 if ( !make_monitorui_buf( out, dllname )) {
9840 /*******************************************************************
9841 *******************************************************************/
9843 struct xcv_api_table xcvlocal_cmds[] = {
9844 { "MonitorUI", xcvlocal_monitorui },
9848 struct xcv_api_table xcvlocal_cmds[] = {
9855 /*******************************************************************
9856 *******************************************************************/
9858 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9859 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9864 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9866 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9867 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9868 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9870 return WERR_BADFUNC;
9873 /*******************************************************************
9874 *******************************************************************/
9876 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9878 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9882 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9886 /* Has to be a handle to the TCP/IP port monitor */
9888 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9889 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9893 /* requires administrative access to the server */
9895 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9896 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9897 return WERR_ACCESS_DENIED;
9900 /* Get the command name. There's numerous commands supported by the
9901 TCPMON interface. */
9903 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9904 q_u->dataname.uni_str_len*2, 0);
9906 /* Allocate the outgoing buffer */
9908 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9910 switch ( Printer->printer_type ) {
9911 case SPLHND_PORTMON_TCP:
9912 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9913 &q_u->indata, &r_u->outdata, &r_u->needed );
9914 case SPLHND_PORTMON_LOCAL:
9915 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9916 &q_u->indata, &r_u->outdata, &r_u->needed );
9919 return WERR_INVALID_PRINT_MONITOR;