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 if (asprintf(&guid_str, "{%s}",
4361 smb_uuid_string(talloc_tos(), guid)) == -1) {
4364 strupper_m(guid_str);
4365 init_unistr(&printer->guid, guid_str);
4366 SAFE_FREE(guid_str);
4367 printer->action = SPOOL_DS_PUBLISH;
4369 init_unistr(&printer->guid, "");
4370 printer->action = SPOOL_DS_UNPUBLISH;
4376 /********************************************************************
4377 Spoolss_enumprinters.
4378 ********************************************************************/
4380 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4384 int n_services=lp_numservices();
4385 PRINTER_INFO_1 *printers=NULL;
4386 PRINTER_INFO_1 current_prt;
4387 WERROR result = WERR_OK;
4389 DEBUG(4,("enum_all_printers_info_1\n"));
4391 for (snum=0; snum<n_services; snum++) {
4392 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4393 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4395 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4396 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4397 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4401 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4403 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4409 /* check the required size. */
4410 for (i=0; i<*returned; i++)
4411 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4413 if (*needed > offered) {
4414 result = WERR_INSUFFICIENT_BUFFER;
4418 if (!rpcbuf_alloc_size(buffer, *needed)) {
4419 result = WERR_NOMEM;
4423 /* fill the buffer with the structures */
4424 for (i=0; i<*returned; i++)
4425 smb_io_printer_info_1("", buffer, &printers[i], 0);
4430 SAFE_FREE(printers);
4432 if ( !W_ERROR_IS_OK(result) )
4438 /********************************************************************
4439 enum_all_printers_info_1_local.
4440 *********************************************************************/
4442 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4444 DEBUG(4,("enum_all_printers_info_1_local\n"));
4446 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4449 /********************************************************************
4450 enum_all_printers_info_1_name.
4451 *********************************************************************/
4453 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4457 DEBUG(4,("enum_all_printers_info_1_name\n"));
4459 if ((name[0] == '\\') && (name[1] == '\\'))
4462 if (is_myname_or_ipaddr(s)) {
4463 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4466 return WERR_INVALID_NAME;
4469 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4470 /********************************************************************
4471 enum_all_printers_info_1_remote.
4472 *********************************************************************/
4474 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4476 PRINTER_INFO_1 *printer;
4477 fstring printername;
4480 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4481 WERROR result = WERR_OK;
4483 /* JFM: currently it's more a place holder than anything else.
4484 * In the spooler world there is a notion of server registration.
4485 * the print servers are registered on the PDC (in the same domain)
4487 * We should have a TDB here. The registration is done thru an
4488 * undocumented RPC call.
4491 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4496 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4497 slprintf(desc, sizeof(desc)-1,"%s", name);
4498 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4500 init_unistr(&printer->description, desc);
4501 init_unistr(&printer->name, printername);
4502 init_unistr(&printer->comment, comment);
4503 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4505 /* check the required size. */
4506 *needed += spoolss_size_printer_info_1(printer);
4508 if (*needed > offered) {
4509 result = WERR_INSUFFICIENT_BUFFER;
4513 if (!rpcbuf_alloc_size(buffer, *needed)) {
4514 result = WERR_NOMEM;
4518 /* fill the buffer with the structures */
4519 smb_io_printer_info_1("", buffer, printer, 0);
4525 if ( !W_ERROR_IS_OK(result) )
4533 /********************************************************************
4534 enum_all_printers_info_1_network.
4535 *********************************************************************/
4537 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4541 DEBUG(4,("enum_all_printers_info_1_network\n"));
4543 /* If we respond to a enum_printers level 1 on our name with flags
4544 set to PRINTER_ENUM_REMOTE with a list of printers then these
4545 printers incorrectly appear in the APW browse list.
4546 Specifically the printers for the server appear at the workgroup
4547 level where all the other servers in the domain are
4548 listed. Windows responds to this call with a
4549 WERR_CAN_NOT_COMPLETE so we should do the same. */
4551 if (name[0] == '\\' && name[1] == '\\')
4554 if (is_myname_or_ipaddr(s))
4555 return WERR_CAN_NOT_COMPLETE;
4557 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4560 /********************************************************************
4561 * api_spoolss_enumprinters
4563 * called from api_spoolss_enumprinters (see this to understand)
4564 ********************************************************************/
4566 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4570 int n_services=lp_numservices();
4571 PRINTER_INFO_2 *printers=NULL;
4572 PRINTER_INFO_2 current_prt;
4573 WERROR result = WERR_OK;
4577 for (snum=0; snum<n_services; snum++) {
4578 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4579 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4581 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4582 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4583 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4588 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4590 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4597 /* check the required size. */
4598 for (i=0; i<*returned; i++)
4599 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4601 if (*needed > offered) {
4602 result = WERR_INSUFFICIENT_BUFFER;
4606 if (!rpcbuf_alloc_size(buffer, *needed)) {
4607 result = WERR_NOMEM;
4611 /* fill the buffer with the structures */
4612 for (i=0; i<*returned; i++)
4613 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4618 for (i=0; i<*returned; i++)
4619 free_devmode(printers[i].devmode);
4621 SAFE_FREE(printers);
4623 if ( !W_ERROR_IS_OK(result) )
4629 /********************************************************************
4630 * handle enumeration of printers at level 1
4631 ********************************************************************/
4633 static WERROR enumprinters_level1( uint32 flags, fstring name,
4634 RPC_BUFFER *buffer, uint32 offered,
4635 uint32 *needed, uint32 *returned)
4637 /* Not all the flags are equals */
4639 if (flags & PRINTER_ENUM_LOCAL)
4640 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4642 if (flags & PRINTER_ENUM_NAME)
4643 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4645 #if 0 /* JERRY - disabled for now */
4646 if (flags & PRINTER_ENUM_REMOTE)
4647 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4650 if (flags & PRINTER_ENUM_NETWORK)
4651 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4653 return WERR_OK; /* NT4sp5 does that */
4656 /********************************************************************
4657 * handle enumeration of printers at level 2
4658 ********************************************************************/
4660 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4661 RPC_BUFFER *buffer, uint32 offered,
4662 uint32 *needed, uint32 *returned)
4664 char *s = servername;
4666 if (flags & PRINTER_ENUM_LOCAL) {
4667 return enum_all_printers_info_2(buffer, offered, needed, returned);
4670 if (flags & PRINTER_ENUM_NAME) {
4671 if ((servername[0] == '\\') && (servername[1] == '\\'))
4673 if (is_myname_or_ipaddr(s))
4674 return enum_all_printers_info_2(buffer, offered, needed, returned);
4676 return WERR_INVALID_NAME;
4679 if (flags & PRINTER_ENUM_REMOTE)
4680 return WERR_UNKNOWN_LEVEL;
4685 /********************************************************************
4686 * handle enumeration of printers at level 5
4687 ********************************************************************/
4689 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4690 RPC_BUFFER *buffer, uint32 offered,
4691 uint32 *needed, uint32 *returned)
4693 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4697 /********************************************************************
4698 * api_spoolss_enumprinters
4700 * called from api_spoolss_enumprinters (see this to understand)
4701 ********************************************************************/
4703 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4705 uint32 flags = q_u->flags;
4706 UNISTR2 *servername = &q_u->servername;
4707 uint32 level = q_u->level;
4708 RPC_BUFFER *buffer = NULL;
4709 uint32 offered = q_u->offered;
4710 uint32 *needed = &r_u->needed;
4711 uint32 *returned = &r_u->returned;
4715 /* that's an [in out] buffer */
4717 if (!q_u->buffer && (offered!=0)) {
4718 return WERR_INVALID_PARAM;
4721 rpcbuf_move(q_u->buffer, &r_u->buffer);
4722 buffer = r_u->buffer;
4724 DEBUG(4,("_spoolss_enumprinters\n"));
4731 * flags==PRINTER_ENUM_NAME
4732 * if name=="" then enumerates all printers
4733 * if name!="" then enumerate the printer
4734 * flags==PRINTER_ENUM_REMOTE
4735 * name is NULL, enumerate printers
4736 * Level 2: name!="" enumerates printers, name can't be NULL
4737 * Level 3: doesn't exist
4738 * Level 4: does a local registry lookup
4739 * Level 5: same as Level 2
4742 unistr2_to_ascii(name, servername, sizeof(name));
4747 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4749 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4751 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4756 return WERR_UNKNOWN_LEVEL;
4759 /****************************************************************************
4760 ****************************************************************************/
4762 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4764 PRINTER_INFO_0 *printer=NULL;
4765 WERROR result = WERR_OK;
4767 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4770 construct_printer_info_0(print_hnd, printer, snum);
4772 /* check the required size. */
4773 *needed += spoolss_size_printer_info_0(printer);
4775 if (*needed > offered) {
4776 result = WERR_INSUFFICIENT_BUFFER;
4780 if (!rpcbuf_alloc_size(buffer, *needed)) {
4781 result = WERR_NOMEM;
4785 /* fill the buffer with the structures */
4786 smb_io_printer_info_0("", buffer, printer, 0);
4796 /****************************************************************************
4797 ****************************************************************************/
4799 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4801 PRINTER_INFO_1 *printer=NULL;
4802 WERROR result = WERR_OK;
4804 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4807 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4809 /* check the required size. */
4810 *needed += spoolss_size_printer_info_1(printer);
4812 if (*needed > offered) {
4813 result = WERR_INSUFFICIENT_BUFFER;
4817 if (!rpcbuf_alloc_size(buffer, *needed)) {
4818 result = WERR_NOMEM;
4822 /* fill the buffer with the structures */
4823 smb_io_printer_info_1("", buffer, printer, 0);
4832 /****************************************************************************
4833 ****************************************************************************/
4835 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4837 PRINTER_INFO_2 *printer=NULL;
4838 WERROR result = WERR_OK;
4840 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4843 construct_printer_info_2(print_hnd, printer, snum);
4845 /* check the required size. */
4846 *needed += spoolss_size_printer_info_2(printer);
4848 if (*needed > offered) {
4849 result = WERR_INSUFFICIENT_BUFFER;
4853 if (!rpcbuf_alloc_size(buffer, *needed)) {
4854 result = WERR_NOMEM;
4858 /* fill the buffer with the structures */
4859 if (!smb_io_printer_info_2("", buffer, printer, 0))
4860 result = WERR_NOMEM;
4864 free_printer_info_2(printer);
4869 /****************************************************************************
4870 ****************************************************************************/
4872 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4874 PRINTER_INFO_3 *printer=NULL;
4875 WERROR result = WERR_OK;
4877 if (!construct_printer_info_3(print_hnd, &printer, snum))
4880 /* check the required size. */
4881 *needed += spoolss_size_printer_info_3(printer);
4883 if (*needed > offered) {
4884 result = WERR_INSUFFICIENT_BUFFER;
4888 if (!rpcbuf_alloc_size(buffer, *needed)) {
4889 result = WERR_NOMEM;
4893 /* fill the buffer with the structures */
4894 smb_io_printer_info_3("", buffer, printer, 0);
4898 free_printer_info_3(printer);
4903 /****************************************************************************
4904 ****************************************************************************/
4906 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4908 PRINTER_INFO_4 *printer=NULL;
4909 WERROR result = WERR_OK;
4911 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4914 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4919 /* check the required size. */
4920 *needed += spoolss_size_printer_info_4(printer);
4922 if (*needed > offered) {
4923 result = WERR_INSUFFICIENT_BUFFER;
4927 if (!rpcbuf_alloc_size(buffer, *needed)) {
4928 result = WERR_NOMEM;
4932 /* fill the buffer with the structures */
4933 smb_io_printer_info_4("", buffer, printer, 0);
4937 free_printer_info_4(printer);
4942 /****************************************************************************
4943 ****************************************************************************/
4945 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4947 PRINTER_INFO_5 *printer=NULL;
4948 WERROR result = WERR_OK;
4950 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4953 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4954 free_printer_info_5(printer);
4958 /* check the required size. */
4959 *needed += spoolss_size_printer_info_5(printer);
4961 if (*needed > offered) {
4962 result = WERR_INSUFFICIENT_BUFFER;
4966 if (!rpcbuf_alloc_size(buffer, *needed)) {
4967 result = WERR_NOMEM;
4971 /* fill the buffer with the structures */
4972 smb_io_printer_info_5("", buffer, printer, 0);
4976 free_printer_info_5(printer);
4981 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4983 RPC_BUFFER *buffer, uint32 offered,
4986 PRINTER_INFO_6 *printer;
4987 WERROR result = WERR_OK;
4989 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4993 if (!construct_printer_info_6(print_hnd, printer, snum)) {
4994 free_printer_info_6(printer);
4998 /* check the required size. */
4999 *needed += spoolss_size_printer_info_6(printer);
5001 if (*needed > offered) {
5002 result = WERR_INSUFFICIENT_BUFFER;
5006 if (!rpcbuf_alloc_size(buffer, *needed)) {
5007 result = WERR_NOMEM;
5011 /* fill the buffer with the structures */
5012 smb_io_printer_info_6("", buffer, printer, 0);
5016 free_printer_info_6(printer);
5021 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5023 PRINTER_INFO_7 *printer=NULL;
5024 WERROR result = WERR_OK;
5026 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5029 if (!construct_printer_info_7(print_hnd, printer, snum))
5032 /* check the required size. */
5033 *needed += spoolss_size_printer_info_7(printer);
5035 if (*needed > offered) {
5036 result = WERR_INSUFFICIENT_BUFFER;
5040 if (!rpcbuf_alloc_size(buffer, *needed)) {
5041 result = WERR_NOMEM;
5046 /* fill the buffer with the structures */
5047 smb_io_printer_info_7("", buffer, printer, 0);
5051 free_printer_info_7(printer);
5056 /****************************************************************************
5057 ****************************************************************************/
5059 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5061 POLICY_HND *handle = &q_u->handle;
5062 uint32 level = q_u->level;
5063 RPC_BUFFER *buffer = NULL;
5064 uint32 offered = q_u->offered;
5065 uint32 *needed = &r_u->needed;
5066 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5070 /* that's an [in out] buffer */
5072 if (!q_u->buffer && (offered!=0)) {
5073 return WERR_INVALID_PARAM;
5076 rpcbuf_move(q_u->buffer, &r_u->buffer);
5077 buffer = r_u->buffer;
5081 if (!get_printer_snum(p, handle, &snum, NULL))
5086 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5088 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5090 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5092 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5094 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5096 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5098 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5100 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5102 return WERR_UNKNOWN_LEVEL;
5105 /********************************************************************
5106 * fill a DRIVER_INFO_1 struct
5107 ********************************************************************/
5109 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5111 init_unistr( &info->name, driver.info_3->name);
5114 /********************************************************************
5115 * construct_printer_driver_info_1
5116 ********************************************************************/
5118 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5120 NT_PRINTER_INFO_LEVEL *printer = NULL;
5121 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5123 ZERO_STRUCT(driver);
5125 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5126 return WERR_INVALID_PRINTER_NAME;
5128 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5129 free_a_printer(&printer, 2);
5130 return WERR_UNKNOWN_PRINTER_DRIVER;
5133 fill_printer_driver_info_1(info, driver, servername, architecture);
5135 free_a_printer(&printer,2);
5140 /********************************************************************
5141 * construct_printer_driver_info_2
5142 * fill a printer_info_2 struct
5143 ********************************************************************/
5145 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5147 TALLOC_CTX *ctx = talloc_tos();
5150 info->version=driver.info_3->cversion;
5152 init_unistr( &info->name, driver.info_3->name );
5153 init_unistr( &info->architecture, driver.info_3->environment );
5156 if (strlen(driver.info_3->driverpath)) {
5157 temp = talloc_asprintf(ctx,
5160 driver.info_3->driverpath);
5161 init_unistr( &info->driverpath, temp );
5163 init_unistr( &info->driverpath, "" );
5167 if (strlen(driver.info_3->datafile)) {
5168 temp = talloc_asprintf(ctx,
5171 driver.info_3->datafile);
5172 init_unistr( &info->datafile, temp );
5174 init_unistr( &info->datafile, "" );
5177 if (strlen(driver.info_3->configfile)) {
5178 temp = talloc_asprintf(ctx,
5181 driver.info_3->configfile);
5182 init_unistr( &info->configfile, temp );
5184 init_unistr( &info->configfile, "" );
5187 /********************************************************************
5188 * construct_printer_driver_info_2
5189 * fill a printer_info_2 struct
5190 ********************************************************************/
5192 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5194 NT_PRINTER_INFO_LEVEL *printer = NULL;
5195 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5197 ZERO_STRUCT(printer);
5198 ZERO_STRUCT(driver);
5200 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5201 return WERR_INVALID_PRINTER_NAME;
5203 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5204 free_a_printer(&printer, 2);
5205 return WERR_UNKNOWN_PRINTER_DRIVER;
5208 fill_printer_driver_info_2(info, driver, servername);
5210 free_a_printer(&printer,2);
5215 /********************************************************************
5216 * copy a strings array and convert to UNICODE
5218 * convert an array of ascii string to a UNICODE string
5219 ********************************************************************/
5221 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5227 TALLOC_CTX *ctx = talloc_tos();
5229 DEBUG(6,("init_unistr_array\n"));
5233 if ( !char_array ) {
5238 v = ""; /* hack to handle null lists */
5241 /* hack to allow this to be used in places other than when generating
5242 the list of dependent files */
5246 line = talloc_asprintf(ctx,
5251 line = talloc_strdup(ctx, v);
5255 SAFE_FREE(*uni_array);
5258 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5260 /* add one extra unit16 for the second terminating NULL */
5262 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5263 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5270 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5275 /* special case for ""; we need to add both NULL's here */
5277 (*uni_array)[j++]=0x0000;
5278 (*uni_array)[j]=0x0000;
5281 DEBUGADD(6,("last one:done\n"));
5283 /* return size of array in uint16's */
5288 /********************************************************************
5289 * construct_printer_info_3
5290 * fill a printer_info_3 struct
5291 ********************************************************************/
5293 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5296 TALLOC_CTX *ctx = talloc_tos();
5300 info->version=driver.info_3->cversion;
5302 init_unistr( &info->name, driver.info_3->name );
5303 init_unistr( &info->architecture, driver.info_3->environment );
5305 if (strlen(driver.info_3->driverpath)) {
5306 temp = talloc_asprintf(ctx,
5309 driver.info_3->driverpath);
5310 init_unistr( &info->driverpath, temp );
5312 init_unistr( &info->driverpath, "" );
5315 if (strlen(driver.info_3->datafile)) {
5316 temp = talloc_asprintf(ctx,
5319 driver.info_3->datafile);
5320 init_unistr( &info->datafile, temp );
5322 init_unistr( &info->datafile, "" );
5325 if (strlen(driver.info_3->configfile)) {
5326 temp = talloc_asprintf(ctx,
5329 driver.info_3->configfile);
5330 init_unistr( &info->configfile, temp );
5332 init_unistr( &info->configfile, "" );
5335 if (strlen(driver.info_3->helpfile)) {
5336 temp = talloc_asprintf(ctx,
5339 driver.info_3->helpfile);
5340 init_unistr( &info->helpfile, temp );
5342 init_unistr( &info->helpfile, "" );
5345 init_unistr( &info->monitorname, driver.info_3->monitorname );
5346 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5348 info->dependentfiles=NULL;
5349 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5352 /********************************************************************
5353 * construct_printer_info_3
5354 * fill a printer_info_3 struct
5355 ********************************************************************/
5357 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5359 NT_PRINTER_INFO_LEVEL *printer = NULL;
5360 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5362 ZERO_STRUCT(driver);
5364 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5365 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5366 if (!W_ERROR_IS_OK(status))
5367 return WERR_INVALID_PRINTER_NAME;
5369 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5370 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5375 * I put this code in during testing. Helpful when commenting out the
5376 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5377 * as win2k always queries the driver using an infor level of 6.
5378 * I've left it in (but ifdef'd out) because I'll probably
5379 * use it in experimentation again in the future. --jerry 22/01/2002
5382 if (!W_ERROR_IS_OK(status)) {
5384 * Is this a W2k client ?
5387 /* Yes - try again with a WinNT driver. */
5389 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5390 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5394 if (!W_ERROR_IS_OK(status)) {
5395 free_a_printer(&printer,2);
5396 return WERR_UNKNOWN_PRINTER_DRIVER;
5404 fill_printer_driver_info_3(info, driver, servername);
5406 free_a_printer(&printer,2);
5411 /********************************************************************
5412 * construct_printer_info_6
5413 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5414 ********************************************************************/
5416 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5420 TALLOC_CTX *ctx = talloc_tos();
5423 memset(&nullstr, '\0', sizeof(fstring));
5425 info->version=driver.info_3->cversion;
5427 init_unistr( &info->name, driver.info_3->name );
5428 init_unistr( &info->architecture, driver.info_3->environment );
5430 if (strlen(driver.info_3->driverpath)) {
5431 temp = talloc_asprintf(ctx,
5434 driver.info_3->driverpath);
5435 init_unistr( &info->driverpath, temp );
5437 init_unistr( &info->driverpath, "" );
5440 if (strlen(driver.info_3->datafile)) {
5441 temp = talloc_asprintf(ctx,
5444 driver.info_3->datafile);
5445 init_unistr( &info->datafile, temp );
5447 init_unistr( &info->datafile, "" );
5450 if (strlen(driver.info_3->configfile)) {
5451 temp = talloc_asprintf(ctx,
5454 driver.info_3->configfile);
5455 init_unistr( &info->configfile, temp );
5457 init_unistr( &info->configfile, "" );
5460 if (strlen(driver.info_3->helpfile)) {
5461 temp = talloc_asprintf(ctx,
5464 driver.info_3->helpfile);
5465 init_unistr( &info->helpfile, temp );
5467 init_unistr( &info->helpfile, "" );
5470 init_unistr( &info->monitorname, driver.info_3->monitorname );
5471 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5473 info->dependentfiles = NULL;
5474 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5476 info->previousdrivernames=NULL;
5477 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5479 info->driver_date=0;
5482 info->driver_version_low=0;
5483 info->driver_version_high=0;
5485 init_unistr( &info->mfgname, "");
5486 init_unistr( &info->oem_url, "");
5487 init_unistr( &info->hardware_id, "");
5488 init_unistr( &info->provider, "");
5491 /********************************************************************
5492 * construct_printer_info_6
5493 * fill a printer_info_6 struct
5494 ********************************************************************/
5496 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5497 fstring servername, fstring architecture, uint32 version)
5499 NT_PRINTER_INFO_LEVEL *printer = NULL;
5500 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5503 ZERO_STRUCT(driver);
5505 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5507 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5509 if (!W_ERROR_IS_OK(status))
5510 return WERR_INVALID_PRINTER_NAME;
5512 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5514 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5516 if (!W_ERROR_IS_OK(status))
5519 * Is this a W2k client ?
5523 free_a_printer(&printer,2);
5524 return WERR_UNKNOWN_PRINTER_DRIVER;
5527 /* Yes - try again with a WinNT driver. */
5529 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5530 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5531 if (!W_ERROR_IS_OK(status)) {
5532 free_a_printer(&printer,2);
5533 return WERR_UNKNOWN_PRINTER_DRIVER;
5537 fill_printer_driver_info_6(info, driver, servername);
5539 free_a_printer(&printer,2);
5540 free_a_printer_driver(driver, 3);
5545 /****************************************************************************
5546 ****************************************************************************/
5548 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5550 SAFE_FREE(info->dependentfiles);
5553 /****************************************************************************
5554 ****************************************************************************/
5556 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5558 SAFE_FREE(info->dependentfiles);
5561 /****************************************************************************
5562 ****************************************************************************/
5564 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5566 DRIVER_INFO_1 *info=NULL;
5569 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5572 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5573 if (!W_ERROR_IS_OK(result))
5576 /* check the required size. */
5577 *needed += spoolss_size_printer_driver_info_1(info);
5579 if (*needed > offered) {
5580 result = WERR_INSUFFICIENT_BUFFER;
5584 if (!rpcbuf_alloc_size(buffer, *needed)) {
5585 result = WERR_NOMEM;
5589 /* fill the buffer with the structures */
5590 smb_io_printer_driver_info_1("", buffer, info, 0);
5599 /****************************************************************************
5600 ****************************************************************************/
5602 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5604 DRIVER_INFO_2 *info=NULL;
5607 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5610 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5611 if (!W_ERROR_IS_OK(result))
5614 /* check the required size. */
5615 *needed += spoolss_size_printer_driver_info_2(info);
5617 if (*needed > offered) {
5618 result = WERR_INSUFFICIENT_BUFFER;
5622 if (!rpcbuf_alloc_size(buffer, *needed)) {
5623 result = WERR_NOMEM;
5627 /* fill the buffer with the structures */
5628 smb_io_printer_driver_info_2("", buffer, info, 0);
5637 /****************************************************************************
5638 ****************************************************************************/
5640 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5647 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5648 if (!W_ERROR_IS_OK(result))
5651 /* check the required size. */
5652 *needed += spoolss_size_printer_driver_info_3(&info);
5654 if (*needed > offered) {
5655 result = WERR_INSUFFICIENT_BUFFER;
5659 if (!rpcbuf_alloc_size(buffer, *needed)) {
5660 result = WERR_NOMEM;
5664 /* fill the buffer with the structures */
5665 smb_io_printer_driver_info_3("", buffer, &info, 0);
5668 free_printer_driver_info_3(&info);
5673 /****************************************************************************
5674 ****************************************************************************/
5676 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5683 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5684 if (!W_ERROR_IS_OK(result))
5687 /* check the required size. */
5688 *needed += spoolss_size_printer_driver_info_6(&info);
5690 if (*needed > offered) {
5691 result = WERR_INSUFFICIENT_BUFFER;
5695 if (!rpcbuf_alloc_size(buffer, *needed)) {
5696 result = WERR_NOMEM;
5700 /* fill the buffer with the structures */
5701 smb_io_printer_driver_info_6("", buffer, &info, 0);
5704 free_printer_driver_info_6(&info);
5709 /****************************************************************************
5710 ****************************************************************************/
5712 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5714 POLICY_HND *handle = &q_u->handle;
5715 UNISTR2 *uni_arch = &q_u->architecture;
5716 uint32 level = q_u->level;
5717 uint32 clientmajorversion = q_u->clientmajorversion;
5718 RPC_BUFFER *buffer = NULL;
5719 uint32 offered = q_u->offered;
5720 uint32 *needed = &r_u->needed;
5721 uint32 *servermajorversion = &r_u->servermajorversion;
5722 uint32 *serverminorversion = &r_u->serverminorversion;
5723 Printer_entry *printer;
5726 fstring architecture;
5729 /* that's an [in out] buffer */
5731 if (!q_u->buffer && (offered!=0)) {
5732 return WERR_INVALID_PARAM;
5735 rpcbuf_move(q_u->buffer, &r_u->buffer);
5736 buffer = r_u->buffer;
5738 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5740 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5741 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5742 return WERR_INVALID_PRINTER_NAME;
5746 *servermajorversion = 0;
5747 *serverminorversion = 0;
5749 fstrcpy(servername, get_server_name( printer ));
5750 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5752 if (!get_printer_snum(p, handle, &snum, NULL))
5757 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5759 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5761 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5763 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5766 /* apparently this call is the equivalent of
5767 EnumPrinterDataEx() for the DsDriver key */
5772 return WERR_UNKNOWN_LEVEL;
5775 /****************************************************************************
5776 ****************************************************************************/
5778 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5780 POLICY_HND *handle = &q_u->handle;
5782 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5785 DEBUG(3,("Error in startpageprinter printer handle\n"));
5789 Printer->page_started=True;
5793 /****************************************************************************
5794 ****************************************************************************/
5796 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5798 POLICY_HND *handle = &q_u->handle;
5801 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5804 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5808 if (!get_printer_snum(p, handle, &snum, NULL))
5811 Printer->page_started=False;
5812 print_job_endpage(snum, Printer->jobid);
5817 /********************************************************************
5818 * api_spoolss_getprinter
5819 * called from the spoolss dispatcher
5821 ********************************************************************/
5823 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5825 POLICY_HND *handle = &q_u->handle;
5826 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5827 uint32 *jobid = &r_u->jobid;
5828 TALLOC_CTX *ctx = p->mem_ctx;
5829 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5831 char *jobname = NULL;
5833 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5836 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5841 * a nice thing with NT is it doesn't listen to what you tell it.
5842 * when asked to send _only_ RAW datas, it tries to send datas
5845 * So I add checks like in NT Server ...
5848 if (info_1->p_datatype != 0) {
5849 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5850 if (strcmp(datatype, "RAW") != 0) {
5852 return WERR_INVALID_DATATYPE;
5856 /* get the share number of the printer */
5857 if (!get_printer_snum(p, handle, &snum, NULL)) {
5861 jobname = unistr2_to_ascii_talloc(ctx, &info_1->docname);
5863 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5865 /* An error occured in print_job_start() so return an appropriate
5868 if (Printer->jobid == -1) {
5869 return map_werror_from_unix(errno);
5872 Printer->document_started=True;
5873 (*jobid) = Printer->jobid;
5878 /********************************************************************
5879 * api_spoolss_getprinter
5880 * called from the spoolss dispatcher
5882 ********************************************************************/
5884 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5886 POLICY_HND *handle = &q_u->handle;
5888 return _spoolss_enddocprinter_internal(p, handle);
5891 /****************************************************************************
5892 ****************************************************************************/
5894 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5896 POLICY_HND *handle = &q_u->handle;
5897 uint32 buffer_size = q_u->buffer_size;
5898 uint8 *buffer = q_u->buffer;
5899 uint32 *buffer_written = &q_u->buffer_size2;
5901 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5904 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5905 r_u->buffer_written = q_u->buffer_size2;
5909 if (!get_printer_snum(p, handle, &snum, NULL))
5912 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5913 (SMB_OFF_T)-1, (size_t)buffer_size);
5914 if (*buffer_written == (uint32)-1) {
5915 r_u->buffer_written = 0;
5916 if (errno == ENOSPC)
5917 return WERR_NO_SPOOL_SPACE;
5919 return WERR_ACCESS_DENIED;
5922 r_u->buffer_written = q_u->buffer_size2;
5927 /********************************************************************
5928 * api_spoolss_getprinter
5929 * called from the spoolss dispatcher
5931 ********************************************************************/
5933 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5937 WERROR errcode = WERR_BADFUNC;
5938 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5941 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5945 if (!get_printer_snum(p, handle, &snum, NULL))
5949 case PRINTER_CONTROL_PAUSE:
5950 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5954 case PRINTER_CONTROL_RESUME:
5955 case PRINTER_CONTROL_UNPAUSE:
5956 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5960 case PRINTER_CONTROL_PURGE:
5961 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5966 return WERR_UNKNOWN_LEVEL;
5972 /********************************************************************
5973 * api_spoolss_abortprinter
5974 * From MSDN: "Deletes printer's spool file if printer is configured
5976 ********************************************************************/
5978 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5980 POLICY_HND *handle = &q_u->handle;
5981 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5983 WERROR errcode = WERR_OK;
5986 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5990 if (!get_printer_snum(p, handle, &snum, NULL))
5993 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5998 /********************************************************************
5999 * called by spoolss_api_setprinter
6000 * when updating a printer description
6001 ********************************************************************/
6003 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6004 const SPOOL_PRINTER_INFO_LEVEL *info,
6005 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6007 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6011 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6013 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6014 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6015 OUR_HANDLE(handle)));
6017 result = WERR_BADFID;
6022 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6023 result = WERR_INVALID_PARAM;
6027 /* Check the user has permissions to change the security
6028 descriptor. By experimentation with two NT machines, the user
6029 requires Full Access to the printer to change security
6032 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6033 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6034 result = WERR_ACCESS_DENIED;
6038 /* NT seems to like setting the security descriptor even though
6039 nothing may have actually changed. */
6041 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6042 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6043 result = WERR_BADFID;
6047 if (DEBUGLEVEL >= 10) {
6051 the_acl = old_secdesc_ctr->sd->dacl;
6052 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6053 PRINTERNAME(snum), the_acl->num_aces));
6055 for (i = 0; i < the_acl->num_aces; i++) {
6056 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6057 &the_acl->aces[i].trustee),
6058 the_acl->aces[i].access_mask));
6061 the_acl = secdesc_ctr->sd->dacl;
6064 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6065 PRINTERNAME(snum), the_acl->num_aces));
6067 for (i = 0; i < the_acl->num_aces; i++) {
6068 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6069 &the_acl->aces[i].trustee),
6070 the_acl->aces[i].access_mask));
6073 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6077 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6078 if (!new_secdesc_ctr) {
6079 result = WERR_NOMEM;
6083 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6088 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6095 /********************************************************************
6096 Canonicalize printer info from a client
6098 ATTN: It does not matter what we set the servername to hear
6099 since we do the necessary work in get_a_printer() to set it to
6100 the correct value based on what the client sent in the
6101 _spoolss_open_printer_ex().
6102 ********************************************************************/
6104 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6106 fstring printername;
6109 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6110 "portname=%s drivername=%s comment=%s location=%s\n",
6111 info->servername, info->printername, info->sharename,
6112 info->portname, info->drivername, info->comment, info->location));
6114 /* we force some elements to "correct" values */
6115 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6116 fstrcpy(info->sharename, lp_servicename(snum));
6118 /* check to see if we allow printername != sharename */
6120 if ( lp_force_printername(snum) ) {
6121 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6122 global_myname(), info->sharename );
6125 /* make sure printername is in \\server\printername format */
6127 fstrcpy( printername, info->printername );
6129 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6130 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6134 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6135 global_myname(), p );
6138 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6139 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6146 /****************************************************************************
6147 ****************************************************************************/
6149 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6151 char *cmd = lp_addport_cmd();
6152 char *command = NULL;
6155 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6156 bool is_print_op = False;
6159 return WERR_ACCESS_DENIED;
6162 command = talloc_asprintf(ctx,
6163 "%s \"%s\" \"%s\"", cmd, portname, uri );
6169 is_print_op = user_has_privileges( token, &se_printop );
6171 DEBUG(10,("Running [%s]\n", command));
6173 /********* BEGIN SePrintOperatorPrivilege **********/
6178 ret = smbrun(command, &fd);
6183 /********* END SePrintOperatorPrivilege **********/
6185 DEBUGADD(10,("returned [%d]\n", ret));
6187 TALLOC_FREE(command);
6192 return WERR_ACCESS_DENIED;
6198 /****************************************************************************
6199 ****************************************************************************/
6201 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6203 char *cmd = lp_addprinter_cmd();
6205 char *command = NULL;
6209 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6210 bool is_print_op = False;
6211 char *remote_machine = talloc_strdup(ctx, "%m");
6213 if (!remote_machine) {
6216 remote_machine = talloc_sub_basic(ctx,
6217 current_user_info.smb_name,
6218 current_user_info.domain,
6220 if (!remote_machine) {
6224 command = talloc_asprintf(ctx,
6225 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6226 cmd, printer->info_2->printername, printer->info_2->sharename,
6227 printer->info_2->portname, printer->info_2->drivername,
6228 printer->info_2->location, printer->info_2->comment, remote_machine);
6234 is_print_op = user_has_privileges( token, &se_printop );
6236 DEBUG(10,("Running [%s]\n", command));
6238 /********* BEGIN SePrintOperatorPrivilege **********/
6243 if ( (ret = smbrun(command, &fd)) == 0 ) {
6244 /* Tell everyone we updated smb.conf. */
6245 message_send_all(smbd_messaging_context(),
6246 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6252 /********* END SePrintOperatorPrivilege **********/
6254 DEBUGADD(10,("returned [%d]\n", ret));
6256 TALLOC_FREE(command);
6257 TALLOC_FREE(remote_machine);
6265 /* reload our services immediately */
6266 reload_services( False );
6269 /* Get lines and convert them back to dos-codepage */
6270 qlines = fd_lines_load(fd, &numlines, 0);
6271 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6274 /* Set the portname to what the script says the portname should be. */
6275 /* but don't require anything to be return from the script exit a good error code */
6278 /* Set the portname to what the script says the portname should be. */
6279 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6280 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6283 file_lines_free(qlines);
6288 /********************************************************************
6289 * Called by spoolss_api_setprinter
6290 * when updating a printer description.
6291 ********************************************************************/
6293 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6294 const SPOOL_PRINTER_INFO_LEVEL *info,
6295 DEVICEMODE *devmode)
6298 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6299 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6304 DEBUG(8,("update_printer\n"));
6309 result = WERR_BADFID;
6313 if (!get_printer_snum(p, handle, &snum, NULL)) {
6314 result = WERR_BADFID;
6318 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6319 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6320 result = WERR_BADFID;
6324 DEBUGADD(8,("Converting info_2 struct\n"));
6327 * convert_printer_info converts the incoming
6328 * info from the client and overwrites the info
6329 * just read from the tdb in the pointer 'printer'.
6332 if (!convert_printer_info(info, printer, level)) {
6333 result = WERR_NOMEM;
6338 /* we have a valid devmode
6339 convert it and link it*/
6341 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6342 if (!convert_devicemode(printer->info_2->printername, devmode,
6343 &printer->info_2->devmode)) {
6344 result = WERR_NOMEM;
6349 /* Do sanity check on the requested changes for Samba */
6351 if (!check_printer_ok(printer->info_2, snum)) {
6352 result = WERR_INVALID_PARAM;
6356 /* FIXME!!! If the driver has changed we really should verify that
6357 it is installed before doing much else --jerry */
6359 /* Check calling user has permission to update printer description */
6361 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6362 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6363 result = WERR_ACCESS_DENIED;
6367 /* Call addprinter hook */
6368 /* Check changes to see if this is really needed */
6370 if ( *lp_addprinter_cmd()
6371 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6372 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6373 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6374 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6376 /* add_printer_hook() will call reload_services() */
6378 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
6379 result = WERR_ACCESS_DENIED;
6385 * When a *new* driver is bound to a printer, the drivername is used to
6386 * lookup previously saved driver initialization info, which is then
6387 * bound to the printer, simulating what happens in the Windows arch.
6389 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6391 if (!set_driver_init(printer, 2))
6393 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6394 printer->info_2->drivername));
6397 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6398 printer->info_2->drivername));
6400 notify_printer_driver(snum, printer->info_2->drivername);
6404 * flag which changes actually occured. This is a small subset of
6405 * all the possible changes. We also have to update things in the
6409 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6410 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6411 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6412 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6414 notify_printer_comment(snum, printer->info_2->comment);
6417 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6418 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6419 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6420 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6422 notify_printer_sharename(snum, printer->info_2->sharename);
6425 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6428 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6431 pname = printer->info_2->printername;
6434 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6435 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6436 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6438 notify_printer_printername( snum, pname );
6441 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6442 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6443 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6444 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6446 notify_printer_port(snum, printer->info_2->portname);
6449 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6450 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6451 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6452 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6454 notify_printer_location(snum, printer->info_2->location);
6457 /* here we need to update some more DsSpooler keys */
6458 /* uNCName, serverName, shortServerName */
6460 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6461 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6462 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6463 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6464 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6466 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6467 global_myname(), printer->info_2->sharename );
6468 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6469 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6470 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6472 /* Update printer info */
6473 result = mod_a_printer(printer, 2);
6476 free_a_printer(&printer, 2);
6477 free_a_printer(&old_printer, 2);
6483 /****************************************************************************
6484 ****************************************************************************/
6485 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6486 const SPOOL_PRINTER_INFO_LEVEL *info)
6489 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6491 Printer_entry *Printer;
6493 if ( lp_security() != SEC_ADS ) {
6494 return WERR_UNKNOWN_LEVEL;
6497 Printer = find_printer_index_by_hnd(p, handle);
6499 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6504 if (!get_printer_snum(p, handle, &snum, NULL))
6507 nt_printer_publish(Printer, snum, info7->action);
6511 return WERR_UNKNOWN_LEVEL;
6514 /****************************************************************************
6515 ****************************************************************************/
6517 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6519 POLICY_HND *handle = &q_u->handle;
6520 uint32 level = q_u->level;
6521 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6522 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6523 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6524 uint32 command = q_u->command;
6527 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6530 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6534 /* check the level */
6537 return control_printer(handle, command, p);
6539 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6540 if (!W_ERROR_IS_OK(result))
6543 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6546 return update_printer_sec(handle, level, info, p,
6549 return publish_or_unpublish_printer(p, handle, info);
6551 return WERR_UNKNOWN_LEVEL;
6555 /****************************************************************************
6556 ****************************************************************************/
6558 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6560 POLICY_HND *handle = &q_u->handle;
6561 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6564 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6568 if (Printer->notify.client_connected==True) {
6571 if ( Printer->printer_type == SPLHND_SERVER)
6573 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6574 !get_printer_snum(p, handle, &snum, NULL) )
6577 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6580 Printer->notify.flags=0;
6581 Printer->notify.options=0;
6582 Printer->notify.localmachine[0]='\0';
6583 Printer->notify.printerlocal=0;
6584 if (Printer->notify.option)
6585 free_spool_notify_option(&Printer->notify.option);
6586 Printer->notify.client_connected=False;
6591 /****************************************************************************
6592 ****************************************************************************/
6594 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6596 /* that's an [in out] buffer */
6598 if (!q_u->buffer && (q_u->offered!=0)) {
6599 return WERR_INVALID_PARAM;
6602 rpcbuf_move(q_u->buffer, &r_u->buffer);
6605 return WERR_INVALID_PARAM; /* this is what a NT server
6606 returns for AddJob. AddJob
6607 must fail on non-local
6611 /****************************************************************************
6612 ****************************************************************************/
6614 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6615 int position, int snum,
6616 const NT_PRINTER_INFO_LEVEL *ntprinter)
6620 t=gmtime(&queue->time);
6622 job_info->jobid=queue->job;
6623 init_unistr(&job_info->printername, lp_servicename(snum));
6624 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6625 init_unistr(&job_info->username, queue->fs_user);
6626 init_unistr(&job_info->document, queue->fs_file);
6627 init_unistr(&job_info->datatype, "RAW");
6628 init_unistr(&job_info->text_status, "");
6629 job_info->status=nt_printj_status(queue->status);
6630 job_info->priority=queue->priority;
6631 job_info->position=position;
6632 job_info->totalpages=queue->page_count;
6633 job_info->pagesprinted=0;
6635 make_systemtime(&job_info->submitted, t);
6638 /****************************************************************************
6639 ****************************************************************************/
6641 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6642 int position, int snum,
6643 const NT_PRINTER_INFO_LEVEL *ntprinter,
6644 DEVICEMODE *devmode)
6648 t=gmtime(&queue->time);
6650 job_info->jobid=queue->job;
6652 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6654 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6655 init_unistr(&job_info->username, queue->fs_user);
6656 init_unistr(&job_info->document, queue->fs_file);
6657 init_unistr(&job_info->notifyname, queue->fs_user);
6658 init_unistr(&job_info->datatype, "RAW");
6659 init_unistr(&job_info->printprocessor, "winprint");
6660 init_unistr(&job_info->parameters, "");
6661 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6662 init_unistr(&job_info->text_status, "");
6664 /* and here the security descriptor */
6666 job_info->status=nt_printj_status(queue->status);
6667 job_info->priority=queue->priority;
6668 job_info->position=position;
6669 job_info->starttime=0;
6670 job_info->untiltime=0;
6671 job_info->totalpages=queue->page_count;
6672 job_info->size=queue->size;
6673 make_systemtime(&(job_info->submitted), t);
6674 job_info->timeelapsed=0;
6675 job_info->pagesprinted=0;
6677 job_info->devmode = devmode;
6682 /****************************************************************************
6683 Enumjobs at level 1.
6684 ****************************************************************************/
6686 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6687 const NT_PRINTER_INFO_LEVEL *ntprinter,
6688 RPC_BUFFER *buffer, uint32 offered,
6689 uint32 *needed, uint32 *returned)
6693 WERROR result = WERR_OK;
6695 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6701 for (i=0; i<*returned; i++)
6702 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6704 /* check the required size. */
6705 for (i=0; i<*returned; i++)
6706 (*needed) += spoolss_size_job_info_1(&info[i]);
6708 if (*needed > offered) {
6709 result = WERR_INSUFFICIENT_BUFFER;
6713 if (!rpcbuf_alloc_size(buffer, *needed)) {
6714 result = WERR_NOMEM;
6718 /* fill the buffer with the structures */
6719 for (i=0; i<*returned; i++)
6720 smb_io_job_info_1("", buffer, &info[i], 0);
6726 if ( !W_ERROR_IS_OK(result) )
6732 /****************************************************************************
6733 Enumjobs at level 2.
6734 ****************************************************************************/
6736 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6737 const NT_PRINTER_INFO_LEVEL *ntprinter,
6738 RPC_BUFFER *buffer, uint32 offered,
6739 uint32 *needed, uint32 *returned)
6741 JOB_INFO_2 *info = NULL;
6743 WERROR result = WERR_OK;
6744 DEVICEMODE *devmode = NULL;
6746 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6751 /* this should not be a failure condition if the devmode is NULL */
6753 devmode = construct_dev_mode(lp_const_servicename(snum));
6755 for (i=0; i<*returned; i++)
6756 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6758 /* check the required size. */
6759 for (i=0; i<*returned; i++)
6760 (*needed) += spoolss_size_job_info_2(&info[i]);
6762 if (*needed > offered) {
6763 result = WERR_INSUFFICIENT_BUFFER;
6767 if (!rpcbuf_alloc_size(buffer, *needed)) {
6768 result = WERR_NOMEM;
6772 /* fill the buffer with the structures */
6773 for (i=0; i<*returned; i++)
6774 smb_io_job_info_2("", buffer, &info[i], 0);
6777 free_devmode(devmode);
6780 if ( !W_ERROR_IS_OK(result) )
6787 /****************************************************************************
6789 ****************************************************************************/
6791 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6793 POLICY_HND *handle = &q_u->handle;
6794 uint32 level = q_u->level;
6795 RPC_BUFFER *buffer = NULL;
6796 uint32 offered = q_u->offered;
6797 uint32 *needed = &r_u->needed;
6798 uint32 *returned = &r_u->returned;
6800 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6802 print_status_struct prt_status;
6803 print_queue_struct *queue=NULL;
6805 /* that's an [in out] buffer */
6807 if (!q_u->buffer && (offered!=0)) {
6808 return WERR_INVALID_PARAM;
6811 rpcbuf_move(q_u->buffer, &r_u->buffer);
6812 buffer = r_u->buffer;
6814 DEBUG(4,("_spoolss_enumjobs\n"));
6819 /* lookup the printer snum and tdb entry */
6821 if (!get_printer_snum(p, handle, &snum, NULL))
6824 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6825 if ( !W_ERROR_IS_OK(wret) )
6828 *returned = print_queue_status(snum, &queue, &prt_status);
6829 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6831 if (*returned == 0) {
6833 free_a_printer(&ntprinter, 2);
6839 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6842 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6846 wret = WERR_UNKNOWN_LEVEL;
6851 free_a_printer( &ntprinter, 2 );
6855 /****************************************************************************
6856 ****************************************************************************/
6858 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6863 /****************************************************************************
6864 ****************************************************************************/
6866 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6868 POLICY_HND *handle = &q_u->handle;
6869 uint32 jobid = q_u->jobid;
6870 uint32 command = q_u->command;
6873 WERROR errcode = WERR_BADFUNC;
6875 if (!get_printer_snum(p, handle, &snum, NULL)) {
6879 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6880 return WERR_INVALID_PRINTER_NAME;
6884 case JOB_CONTROL_CANCEL:
6885 case JOB_CONTROL_DELETE:
6886 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6890 case JOB_CONTROL_PAUSE:
6891 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6895 case JOB_CONTROL_RESTART:
6896 case JOB_CONTROL_RESUME:
6897 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6902 return WERR_UNKNOWN_LEVEL;
6908 /****************************************************************************
6909 Enumerates all printer drivers at level 1.
6910 ****************************************************************************/
6912 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6917 fstring *list = NULL;
6918 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6919 DRIVER_INFO_1 *driver_info_1=NULL;
6920 WERROR result = WERR_OK;
6924 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6926 ndrivers=get_ntdrivers(&list, architecture, version);
6927 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6929 if(ndrivers == -1) {
6930 SAFE_FREE(driver_info_1);
6935 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6936 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6942 for (i=0; i<ndrivers; i++) {
6944 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6945 ZERO_STRUCT(driver);
6946 status = get_a_printer_driver(&driver, 3, list[i],
6947 architecture, version);
6948 if (!W_ERROR_IS_OK(status)) {
6950 SAFE_FREE(driver_info_1);
6953 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6954 free_a_printer_driver(driver, 3);
6957 *returned+=ndrivers;
6961 /* check the required size. */
6962 for (i=0; i<*returned; i++) {
6963 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6964 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6967 if (*needed > offered) {
6968 result = WERR_INSUFFICIENT_BUFFER;
6972 if (!rpcbuf_alloc_size(buffer, *needed)) {
6973 result = WERR_NOMEM;
6977 /* fill the buffer with the driver structures */
6978 for (i=0; i<*returned; i++) {
6979 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6980 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6984 SAFE_FREE(driver_info_1);
6986 if ( !W_ERROR_IS_OK(result) )
6992 /****************************************************************************
6993 Enumerates all printer drivers at level 2.
6994 ****************************************************************************/
6996 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7001 fstring *list = NULL;
7002 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7003 DRIVER_INFO_2 *driver_info_2=NULL;
7004 WERROR result = WERR_OK;
7008 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7010 ndrivers=get_ntdrivers(&list, architecture, version);
7011 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7013 if(ndrivers == -1) {
7014 SAFE_FREE(driver_info_2);
7019 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7020 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7026 for (i=0; i<ndrivers; i++) {
7029 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7030 ZERO_STRUCT(driver);
7031 status = get_a_printer_driver(&driver, 3, list[i],
7032 architecture, version);
7033 if (!W_ERROR_IS_OK(status)) {
7035 SAFE_FREE(driver_info_2);
7038 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7039 free_a_printer_driver(driver, 3);
7042 *returned+=ndrivers;
7046 /* check the required size. */
7047 for (i=0; i<*returned; i++) {
7048 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7049 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7052 if (*needed > offered) {
7053 result = WERR_INSUFFICIENT_BUFFER;
7057 if (!rpcbuf_alloc_size(buffer, *needed)) {
7058 result = WERR_NOMEM;
7062 /* fill the buffer with the form structures */
7063 for (i=0; i<*returned; i++) {
7064 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7065 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7069 SAFE_FREE(driver_info_2);
7071 if ( !W_ERROR_IS_OK(result) )
7077 /****************************************************************************
7078 Enumerates all printer drivers at level 3.
7079 ****************************************************************************/
7081 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7086 fstring *list = NULL;
7087 DRIVER_INFO_3 *driver_info_3=NULL;
7088 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7089 WERROR result = WERR_OK;
7093 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7095 ndrivers=get_ntdrivers(&list, architecture, version);
7096 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7098 if(ndrivers == -1) {
7099 SAFE_FREE(driver_info_3);
7104 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7105 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7111 for (i=0; i<ndrivers; i++) {
7114 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7115 ZERO_STRUCT(driver);
7116 status = get_a_printer_driver(&driver, 3, list[i],
7117 architecture, version);
7118 if (!W_ERROR_IS_OK(status)) {
7120 SAFE_FREE(driver_info_3);
7123 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7124 free_a_printer_driver(driver, 3);
7127 *returned+=ndrivers;
7131 /* check the required size. */
7132 for (i=0; i<*returned; i++) {
7133 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7134 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7137 if (*needed > offered) {
7138 result = WERR_INSUFFICIENT_BUFFER;
7142 if (!rpcbuf_alloc_size(buffer, *needed)) {
7143 result = WERR_NOMEM;
7147 /* fill the buffer with the driver structures */
7148 for (i=0; i<*returned; i++) {
7149 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7150 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7154 for (i=0; i<*returned; i++) {
7155 SAFE_FREE(driver_info_3[i].dependentfiles);
7158 SAFE_FREE(driver_info_3);
7160 if ( !W_ERROR_IS_OK(result) )
7166 /****************************************************************************
7167 Enumerates all printer drivers.
7168 ****************************************************************************/
7170 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7172 uint32 level = q_u->level;
7173 RPC_BUFFER *buffer = NULL;
7174 uint32 offered = q_u->offered;
7175 uint32 *needed = &r_u->needed;
7176 uint32 *returned = &r_u->returned;
7179 fstring architecture;
7181 /* that's an [in out] buffer */
7183 if (!q_u->buffer && (offered!=0)) {
7184 return WERR_INVALID_PARAM;
7187 rpcbuf_move(q_u->buffer, &r_u->buffer);
7188 buffer = r_u->buffer;
7190 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7195 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7196 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7198 if ( !is_myname_or_ipaddr( servername ) )
7199 return WERR_UNKNOWN_PRINTER_DRIVER;
7203 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7205 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7207 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7209 return WERR_UNKNOWN_LEVEL;
7213 /****************************************************************************
7214 ****************************************************************************/
7216 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7218 form->flag=list->flag;
7219 init_unistr(&form->name, list->name);
7220 form->width=list->width;
7221 form->length=list->length;
7222 form->left=list->left;
7223 form->top=list->top;
7224 form->right=list->right;
7225 form->bottom=list->bottom;
7228 /****************************************************************************
7229 ****************************************************************************/
7231 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7233 uint32 level = q_u->level;
7234 RPC_BUFFER *buffer = NULL;
7235 uint32 offered = q_u->offered;
7236 uint32 *needed = &r_u->needed;
7237 uint32 *numofforms = &r_u->numofforms;
7238 uint32 numbuiltinforms;
7240 nt_forms_struct *list=NULL;
7241 nt_forms_struct *builtinlist=NULL;
7246 /* that's an [in out] buffer */
7248 if (!q_u->buffer && (offered!=0) ) {
7249 return WERR_INVALID_PARAM;
7252 rpcbuf_move(q_u->buffer, &r_u->buffer);
7253 buffer = r_u->buffer;
7255 DEBUG(4,("_spoolss_enumforms\n"));
7256 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7257 DEBUGADD(5,("Info level [%d]\n", level));
7259 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7260 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7261 *numofforms = get_ntforms(&list);
7262 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7263 *numofforms += numbuiltinforms;
7265 if (*numofforms == 0) {
7266 SAFE_FREE(builtinlist);
7268 return WERR_NO_MORE_ITEMS;
7273 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7274 SAFE_FREE(builtinlist);
7280 /* construct the list of form structures */
7281 for (i=0; i<numbuiltinforms; i++) {
7282 DEBUGADD(6,("Filling form number [%d]\n",i));
7283 fill_form_1(&forms_1[i], &builtinlist[i]);
7286 SAFE_FREE(builtinlist);
7288 for (; i<*numofforms; i++) {
7289 DEBUGADD(6,("Filling form number [%d]\n",i));
7290 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7295 /* check the required size. */
7296 for (i=0; i<numbuiltinforms; i++) {
7297 DEBUGADD(6,("adding form [%d]'s size\n",i));
7298 buffer_size += spoolss_size_form_1(&forms_1[i]);
7300 for (; i<*numofforms; i++) {
7301 DEBUGADD(6,("adding form [%d]'s size\n",i));
7302 buffer_size += spoolss_size_form_1(&forms_1[i]);
7305 *needed=buffer_size;
7307 if (*needed > offered) {
7310 return WERR_INSUFFICIENT_BUFFER;
7313 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7319 /* fill the buffer with the form structures */
7320 for (i=0; i<numbuiltinforms; i++) {
7321 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7322 smb_io_form_1("", buffer, &forms_1[i], 0);
7324 for (; i<*numofforms; i++) {
7325 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7326 smb_io_form_1("", buffer, &forms_1[i], 0);
7335 SAFE_FREE(builtinlist);
7336 return WERR_UNKNOWN_LEVEL;
7340 /****************************************************************************
7341 ****************************************************************************/
7343 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7345 uint32 level = q_u->level;
7346 UNISTR2 *uni_formname = &q_u->formname;
7347 RPC_BUFFER *buffer = NULL;
7348 uint32 offered = q_u->offered;
7349 uint32 *needed = &r_u->needed;
7351 nt_forms_struct *list=NULL;
7352 nt_forms_struct builtin_form;
7357 int numofforms=0, i=0;
7359 /* that's an [in out] buffer */
7361 if (!q_u->buffer && (offered!=0)) {
7362 return WERR_INVALID_PARAM;
7365 rpcbuf_move(q_u->buffer, &r_u->buffer);
7366 buffer = r_u->buffer;
7368 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7370 DEBUG(4,("_spoolss_getform\n"));
7371 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7372 DEBUGADD(5,("Info level [%d]\n", level));
7374 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7375 if (!foundBuiltin) {
7376 numofforms = get_ntforms(&list);
7377 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7379 if (numofforms == 0)
7386 fill_form_1(&form_1, &builtin_form);
7389 /* Check if the requested name is in the list of form structures */
7390 for (i=0; i<numofforms; i++) {
7392 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7394 if (strequal(form_name, list[i].name)) {
7395 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7396 fill_form_1(&form_1, &list[i]);
7402 if (i == numofforms) {
7406 /* check the required size. */
7408 *needed=spoolss_size_form_1(&form_1);
7410 if (*needed > offered)
7411 return WERR_INSUFFICIENT_BUFFER;
7413 if (!rpcbuf_alloc_size(buffer, buffer_size))
7416 /* fill the buffer with the form structures */
7417 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7418 smb_io_form_1("", buffer, &form_1, 0);
7424 return WERR_UNKNOWN_LEVEL;
7428 /****************************************************************************
7429 ****************************************************************************/
7431 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7433 init_unistr(&port->port_name, name);
7436 /****************************************************************************
7437 TODO: This probably needs distinguish between TCP/IP and Local ports
7439 ****************************************************************************/
7441 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7443 init_unistr(&port->port_name, name);
7444 init_unistr(&port->monitor_name, "Local Monitor");
7445 init_unistr(&port->description, SPL_LOCAL_PORT );
7446 port->port_type=PORT_TYPE_WRITE;
7451 /****************************************************************************
7452 wrapper around the enumer ports command
7453 ****************************************************************************/
7455 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7457 char *cmd = lp_enumports_cmd();
7458 char **qlines = NULL;
7459 char *command = NULL;
7467 /* if no hook then just fill in the default port */
7470 if (!(qlines = SMB_MALLOC_ARRAY( char*, 2 ))) {
7473 if (!(qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME ))) {
7481 /* we have a valid enumport command */
7483 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7488 DEBUG(10,("Running [%s]\n", command));
7489 ret = smbrun(command, &fd);
7490 DEBUG(10,("Returned [%d]\n", ret));
7491 TALLOC_FREE(command);
7496 return WERR_ACCESS_DENIED;
7500 qlines = fd_lines_load(fd, &numlines, 0);
7501 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7511 /****************************************************************************
7513 ****************************************************************************/
7515 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7517 PORT_INFO_1 *ports=NULL;
7519 WERROR result = WERR_OK;
7520 char **qlines = NULL;
7523 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7524 if (!W_ERROR_IS_OK(result)) {
7525 file_lines_free(qlines);
7530 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7531 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7532 dos_errstr(WERR_NOMEM)));
7533 file_lines_free(qlines);
7537 for (i=0; i<numlines; i++) {
7538 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7539 fill_port_1(&ports[i], qlines[i]);
7542 file_lines_free(qlines);
7544 *returned = numlines;
7546 /* check the required size. */
7547 for (i=0; i<*returned; i++) {
7548 DEBUGADD(6,("adding port [%d]'s size\n", i));
7549 *needed += spoolss_size_port_info_1(&ports[i]);
7552 if (*needed > offered) {
7553 result = WERR_INSUFFICIENT_BUFFER;
7557 if (!rpcbuf_alloc_size(buffer, *needed)) {
7558 result = WERR_NOMEM;
7562 /* fill the buffer with the ports structures */
7563 for (i=0; i<*returned; i++) {
7564 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7565 smb_io_port_1("", buffer, &ports[i], 0);
7571 if ( !W_ERROR_IS_OK(result) )
7577 /****************************************************************************
7579 ****************************************************************************/
7581 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7583 PORT_INFO_2 *ports=NULL;
7585 WERROR result = WERR_OK;
7586 char **qlines = NULL;
7589 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7590 if ( !W_ERROR_IS_OK(result)) {
7591 file_lines_free(qlines);
7596 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7597 file_lines_free(qlines);
7601 for (i=0; i<numlines; i++) {
7602 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7603 fill_port_2(&(ports[i]), qlines[i]);
7607 file_lines_free(qlines);
7609 *returned = numlines;
7611 /* check the required size. */
7612 for (i=0; i<*returned; i++) {
7613 DEBUGADD(6,("adding port [%d]'s size\n", i));
7614 *needed += spoolss_size_port_info_2(&ports[i]);
7617 if (*needed > offered) {
7618 result = WERR_INSUFFICIENT_BUFFER;
7622 if (!rpcbuf_alloc_size(buffer, *needed)) {
7623 result = WERR_NOMEM;
7627 /* fill the buffer with the ports structures */
7628 for (i=0; i<*returned; i++) {
7629 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7630 smb_io_port_2("", buffer, &ports[i], 0);
7636 if ( !W_ERROR_IS_OK(result) )
7642 /****************************************************************************
7644 ****************************************************************************/
7646 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7648 uint32 level = q_u->level;
7649 RPC_BUFFER *buffer = NULL;
7650 uint32 offered = q_u->offered;
7651 uint32 *needed = &r_u->needed;
7652 uint32 *returned = &r_u->returned;
7654 /* that's an [in out] buffer */
7656 if (!q_u->buffer && (offered!=0)) {
7657 return WERR_INVALID_PARAM;
7660 rpcbuf_move(q_u->buffer, &r_u->buffer);
7661 buffer = r_u->buffer;
7663 DEBUG(4,("_spoolss_enumports\n"));
7670 return enumports_level_1(buffer, offered, needed, returned);
7672 return enumports_level_2(buffer, offered, needed, returned);
7674 return WERR_UNKNOWN_LEVEL;
7678 /****************************************************************************
7679 ****************************************************************************/
7681 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7682 const SPOOL_PRINTER_INFO_LEVEL *info,
7683 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7684 uint32 user_switch, const SPOOL_USER_CTR *user,
7687 NT_PRINTER_INFO_LEVEL *printer = NULL;
7690 WERROR err = WERR_OK;
7692 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7693 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7697 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7698 if (!convert_printer_info(info, printer, 2)) {
7699 free_a_printer(&printer, 2);
7703 /* check to see if the printer already exists */
7705 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7706 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7707 printer->info_2->sharename));
7708 free_a_printer(&printer, 2);
7709 return WERR_PRINTER_ALREADY_EXISTS;
7712 /* FIXME!!! smbd should check to see if the driver is installed before
7713 trying to add a printer like this --jerry */
7715 if (*lp_addprinter_cmd() ) {
7716 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
7717 free_a_printer(&printer,2);
7718 return WERR_ACCESS_DENIED;
7721 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7722 "smb.conf parameter \"addprinter command\" is defined. This"
7723 "parameter must exist for this call to succeed\n",
7724 printer->info_2->sharename ));
7727 /* use our primary netbios name since get_a_printer() will convert
7728 it to what the client expects on a case by case basis */
7730 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7731 printer->info_2->sharename);
7734 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7735 free_a_printer(&printer,2);
7736 return WERR_ACCESS_DENIED;
7739 /* you must be a printer admin to add a new printer */
7740 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7741 free_a_printer(&printer,2);
7742 return WERR_ACCESS_DENIED;
7746 * Do sanity check on the requested changes for Samba.
7749 if (!check_printer_ok(printer->info_2, snum)) {
7750 free_a_printer(&printer,2);
7751 return WERR_INVALID_PARAM;
7755 * When a printer is created, the drivername bound to the printer is used
7756 * to lookup previously saved driver initialization info, which is then
7757 * bound to the new printer, simulating what happens in the Windows arch.
7762 set_driver_init(printer, 2);
7766 /* A valid devmode was included, convert and link it
7768 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7770 if (!convert_devicemode(printer->info_2->printername, devmode,
7771 &printer->info_2->devmode))
7775 /* write the ASCII on disk */
7776 err = mod_a_printer(printer, 2);
7777 if (!W_ERROR_IS_OK(err)) {
7778 free_a_printer(&printer,2);
7782 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7783 /* Handle open failed - remove addition. */
7784 del_a_printer(printer->info_2->sharename);
7785 free_a_printer(&printer,2);
7786 return WERR_ACCESS_DENIED;
7789 update_c_setprinter(False);
7790 free_a_printer(&printer,2);
7795 /****************************************************************************
7796 ****************************************************************************/
7798 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7800 UNISTR2 *uni_srv_name = q_u->server_name;
7801 uint32 level = q_u->level;
7802 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7803 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7804 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7805 uint32 user_switch = q_u->user_switch;
7806 SPOOL_USER_CTR *user = &q_u->user_ctr;
7807 POLICY_HND *handle = &r_u->handle;
7811 /* we don't handle yet */
7812 /* but I know what to do ... */
7813 return WERR_UNKNOWN_LEVEL;
7815 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7817 user_switch, user, handle);
7819 return WERR_UNKNOWN_LEVEL;
7823 /****************************************************************************
7824 ****************************************************************************/
7826 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7828 uint32 level = q_u->level;
7829 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7830 WERROR err = WERR_OK;
7831 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7832 fstring driver_name;
7835 ZERO_STRUCT(driver);
7837 if (!convert_printer_driver_info(info, &driver, level)) {
7842 DEBUG(5,("Cleaning driver's information\n"));
7843 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7844 if (!W_ERROR_IS_OK(err))
7847 DEBUG(5,("Moving driver to final destination\n"));
7848 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7852 if (add_a_printer_driver(driver, level)!=0) {
7853 err = WERR_ACCESS_DENIED;
7858 * I think this is where he DrvUpgradePrinter() hook would be
7859 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7860 * server. Right now, we just need to send ourselves a message
7861 * to update each printer bound to this driver. --jerry
7864 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7865 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7870 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7871 * decide if the driver init data should be deleted. The rules are:
7872 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7873 * 2) delete init data only if there is no 2k/Xp driver
7874 * 3) always delete init data
7875 * The generalized rule is always use init data from the highest order driver.
7876 * It is necessary to follow the driver install by an initialization step to
7877 * finish off this process.
7880 version = driver.info_3->cversion;
7881 else if (level == 6)
7882 version = driver.info_6->version;
7887 * 9x printer driver - never delete init data
7890 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7895 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7896 * there is no 2k/Xp driver init data for this driver name.
7900 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7902 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7904 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7906 if (!del_driver_init(driver_name))
7907 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7910 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7912 free_a_printer_driver(driver1,3);
7913 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7920 * 2k or Xp printer driver - always delete init data
7923 if (!del_driver_init(driver_name))
7924 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7928 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7934 free_a_printer_driver(driver, level);
7938 /********************************************************************
7939 * spoolss_addprinterdriverex
7940 ********************************************************************/
7942 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7944 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7945 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7948 * we only support the semantics of AddPrinterDriver()
7949 * i.e. only copy files that are newer than existing ones
7952 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7953 return WERR_ACCESS_DENIED;
7955 ZERO_STRUCT(q_u_local);
7956 ZERO_STRUCT(r_u_local);
7958 /* just pass the information off to _spoolss_addprinterdriver() */
7959 q_u_local.server_name_ptr = q_u->server_name_ptr;
7960 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7961 q_u_local.level = q_u->level;
7962 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7964 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7967 /****************************************************************************
7968 ****************************************************************************/
7970 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7972 init_unistr(&info->name, name);
7975 /****************************************************************************
7976 ****************************************************************************/
7978 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7981 char *long_archi = NULL;
7982 char *servername = NULL;
7983 char *pservername = NULL;
7984 const char *short_archi;
7985 DRIVER_DIRECTORY_1 *info=NULL;
7986 WERROR result = WERR_OK;
7987 TALLOC_CTX *ctx = talloc_tos();
7989 servername = unistr2_to_ascii_talloc(ctx, name);
7993 long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
7998 /* check for beginning double '\'s and that the server
8001 pservername = servername;
8002 if ( *pservername == '\\' && strlen(servername)>2 ) {
8006 if ( !is_myname_or_ipaddr( pservername ) )
8007 return WERR_INVALID_PARAM;
8009 if (!(short_archi = get_short_archi(long_archi)))
8010 return WERR_INVALID_ENVIRONMENT;
8012 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8015 path = talloc_asprintf(ctx,
8016 "\\\\%s\\print$\\%s", pservername, short_archi);
8018 result = WERR_NOMEM;
8022 DEBUG(4,("printer driver directory: [%s]\n", path));
8024 fill_driverdir_1(info, path);
8026 *needed += spoolss_size_driverdir_info_1(info);
8028 if (*needed > offered) {
8029 result = WERR_INSUFFICIENT_BUFFER;
8033 if (!rpcbuf_alloc_size(buffer, *needed)) {
8034 result = WERR_NOMEM;
8038 smb_io_driverdir_1("", buffer, info, 0);
8046 /****************************************************************************
8047 ****************************************************************************/
8049 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8051 UNISTR2 *name = &q_u->name;
8052 UNISTR2 *uni_environment = &q_u->environment;
8053 uint32 level = q_u->level;
8054 RPC_BUFFER *buffer = NULL;
8055 uint32 offered = q_u->offered;
8056 uint32 *needed = &r_u->needed;
8058 /* that's an [in out] buffer */
8060 if (!q_u->buffer && (offered!=0)) {
8061 return WERR_INVALID_PARAM;
8064 rpcbuf_move(q_u->buffer, &r_u->buffer);
8065 buffer = r_u->buffer;
8067 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8073 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8075 return WERR_UNKNOWN_LEVEL;
8079 /****************************************************************************
8080 ****************************************************************************/
8082 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8084 POLICY_HND *handle = &q_u->handle;
8085 uint32 idx = q_u->index;
8086 uint32 in_value_len = q_u->valuesize;
8087 uint32 in_data_len = q_u->datasize;
8088 uint32 *out_max_value_len = &r_u->valuesize;
8089 uint16 **out_value = &r_u->value;
8090 uint32 *out_value_len = &r_u->realvaluesize;
8091 uint32 *out_type = &r_u->type;
8092 uint32 *out_max_data_len = &r_u->datasize;
8093 uint8 **data_out = &r_u->data;
8094 uint32 *out_data_len = &r_u->realdatasize;
8096 NT_PRINTER_INFO_LEVEL *printer = NULL;
8098 uint32 biggest_valuesize;
8099 uint32 biggest_datasize;
8101 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8104 REGISTRY_VALUE *val = NULL;
8105 NT_PRINTER_DATA *p_data;
8106 int i, key_index, num_values;
8111 *out_max_data_len = 0;
8115 DEBUG(5,("spoolss_enumprinterdata\n"));
8118 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8122 if (!get_printer_snum(p,handle, &snum, NULL))
8125 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8126 if (!W_ERROR_IS_OK(result))
8129 p_data = printer->info_2->data;
8130 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8135 * The NT machine wants to know the biggest size of value and data
8137 * cf: MSDN EnumPrinterData remark section
8140 if ( !in_value_len && !in_data_len && (key_index != -1) )
8142 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8144 biggest_valuesize = 0;
8145 biggest_datasize = 0;
8147 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8149 for ( i=0; i<num_values; i++ )
8151 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8153 name_length = strlen(val->valuename);
8154 if ( strlen(val->valuename) > biggest_valuesize )
8155 biggest_valuesize = name_length;
8157 if ( val->size > biggest_datasize )
8158 biggest_datasize = val->size;
8160 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8164 /* the value is an UNICODE string but real_value_size is the length
8165 in bytes including the trailing 0 */
8167 *out_value_len = 2 * (1+biggest_valuesize);
8168 *out_data_len = biggest_datasize;
8170 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8176 * the value len is wrong in NT sp3
8177 * that's the number of bytes not the number of unicode chars
8180 if ( key_index != -1 )
8181 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8186 /* out_value should default to "" or else NT4 has
8187 problems unmarshalling the response */
8189 *out_max_value_len=(in_value_len/sizeof(uint16));
8192 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8194 result = WERR_NOMEM;
8197 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8203 /* the data is counted in bytes */
8205 *out_max_data_len = in_data_len;
8206 *out_data_len = in_data_len;
8208 /* only allocate when given a non-zero data_len */
8210 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8212 result = WERR_NOMEM;
8216 result = WERR_NO_MORE_ITEMS;
8222 * - counted in bytes in the request
8223 * - counted in UNICODE chars in the max reply
8224 * - counted in bytes in the real size
8226 * take a pause *before* coding not *during* coding
8230 *out_max_value_len=(in_value_len/sizeof(uint16));
8232 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8234 result = WERR_NOMEM;
8238 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8246 *out_type = regval_type( val );
8248 /* data - counted in bytes */
8250 *out_max_data_len = in_data_len;
8251 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8253 result = WERR_NOMEM;
8256 data_len = regval_size(val);
8257 if ( *data_out && data_len )
8258 memcpy( *data_out, regval_data_p(val), data_len );
8259 *out_data_len = data_len;
8263 free_a_printer(&printer, 2);
8267 /****************************************************************************
8268 ****************************************************************************/
8270 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8272 POLICY_HND *handle = &q_u->handle;
8273 UNISTR2 *value = &q_u->value;
8274 uint32 type = q_u->type;
8275 uint8 *data = q_u->data;
8276 uint32 real_len = q_u->real_len;
8278 NT_PRINTER_INFO_LEVEL *printer = NULL;
8280 WERROR status = WERR_OK;
8281 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8284 DEBUG(5,("spoolss_setprinterdata\n"));
8287 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8291 if ( Printer->printer_type == SPLHND_SERVER ) {
8292 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8293 return WERR_INVALID_PARAM;
8296 if (!get_printer_snum(p,handle, &snum, NULL))
8300 * Access check : NT returns "access denied" if you make a
8301 * SetPrinterData call without the necessary privildge.
8302 * we were originally returning OK if nothing changed
8303 * which made Win2k issue **a lot** of SetPrinterData
8304 * when connecting to a printer --jerry
8307 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8309 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8310 status = WERR_ACCESS_DENIED;
8314 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8315 if (!W_ERROR_IS_OK(status))
8318 unistr2_to_ascii(valuename, value, sizeof(valuename));
8321 * When client side code sets a magic printer data key, detect it and save
8322 * the current printer data and the magic key's data (its the DEVMODE) for
8323 * future printer/driver initializations.
8325 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8327 /* Set devmode and printer initialization info */
8328 status = save_driver_init( printer, 2, data, real_len );
8330 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8334 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8335 type, data, real_len );
8336 if ( W_ERROR_IS_OK(status) )
8337 status = mod_a_printer(printer, 2);
8341 free_a_printer(&printer, 2);
8346 /****************************************************************************
8347 ****************************************************************************/
8349 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8351 POLICY_HND *handle = &q_u->handle;
8352 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8355 DEBUG(5,("_spoolss_resetprinter\n"));
8358 * All we do is to check to see if the handle and queue is valid.
8359 * This call really doesn't mean anything to us because we only
8360 * support RAW printing. --jerry
8364 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8368 if (!get_printer_snum(p,handle, &snum, NULL))
8372 /* blindly return success */
8377 /****************************************************************************
8378 ****************************************************************************/
8380 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8382 POLICY_HND *handle = &q_u->handle;
8383 UNISTR2 *value = &q_u->valuename;
8385 NT_PRINTER_INFO_LEVEL *printer = NULL;
8387 WERROR status = WERR_OK;
8388 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8389 char *valuename = NULL;
8390 TALLOC_CTX *ctx = p->mem_ctx;
8392 DEBUG(5,("spoolss_deleteprinterdata\n"));
8395 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8399 if (!get_printer_snum(p, handle, &snum, NULL))
8402 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8403 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8404 return WERR_ACCESS_DENIED;
8407 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8408 if (!W_ERROR_IS_OK(status))
8411 valuename = unistr2_to_ascii_talloc(ctx, value);
8413 free_a_printer(&printer, 2);
8417 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8419 if ( W_ERROR_IS_OK(status) )
8420 mod_a_printer( printer, 2 );
8422 free_a_printer(&printer, 2);
8423 TALLOC_FREE(valuename);
8428 /****************************************************************************
8429 ****************************************************************************/
8431 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8433 POLICY_HND *handle = &q_u->handle;
8434 FORM *form = &q_u->form;
8435 nt_forms_struct tmpForm;
8437 WERROR status = WERR_OK;
8438 NT_PRINTER_INFO_LEVEL *printer = NULL;
8441 nt_forms_struct *list=NULL;
8442 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8444 DEBUG(5,("spoolss_addform\n"));
8447 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8452 /* forms can be added on printer of on the print server handle */
8454 if ( Printer->printer_type == SPLHND_PRINTER )
8456 if (!get_printer_snum(p,handle, &snum, NULL))
8459 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8460 if (!W_ERROR_IS_OK(status))
8464 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8465 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8466 status = WERR_ACCESS_DENIED;
8470 /* can't add if builtin */
8472 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8473 status = WERR_ALREADY_EXISTS;
8477 count = get_ntforms(&list);
8479 if(!add_a_form(&list, form, &count)) {
8480 status = WERR_NOMEM;
8484 write_ntforms(&list, count);
8487 * ChangeID must always be set if this is a printer
8490 if ( Printer->printer_type == SPLHND_PRINTER )
8491 status = mod_a_printer(printer, 2);
8495 free_a_printer(&printer, 2);
8501 /****************************************************************************
8502 ****************************************************************************/
8504 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8506 POLICY_HND *handle = &q_u->handle;
8507 UNISTR2 *form_name = &q_u->name;
8508 nt_forms_struct tmpForm;
8510 nt_forms_struct *list=NULL;
8511 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8513 WERROR status = WERR_OK;
8514 NT_PRINTER_INFO_LEVEL *printer = NULL;
8516 DEBUG(5,("spoolss_deleteform\n"));
8519 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8523 /* forms can be deleted on printer of on the print server handle */
8525 if ( Printer->printer_type == SPLHND_PRINTER )
8527 if (!get_printer_snum(p,handle, &snum, NULL))
8530 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8531 if (!W_ERROR_IS_OK(status))
8535 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8536 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8537 status = WERR_ACCESS_DENIED;
8541 /* can't delete if builtin */
8543 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8544 status = WERR_INVALID_PARAM;
8548 count = get_ntforms(&list);
8550 if ( !delete_a_form(&list, form_name, &count, &status ))
8554 * ChangeID must always be set if this is a printer
8557 if ( Printer->printer_type == SPLHND_PRINTER )
8558 status = mod_a_printer(printer, 2);
8562 free_a_printer(&printer, 2);
8568 /****************************************************************************
8569 ****************************************************************************/
8571 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8573 POLICY_HND *handle = &q_u->handle;
8574 FORM *form = &q_u->form;
8575 nt_forms_struct tmpForm;
8577 WERROR status = WERR_OK;
8578 NT_PRINTER_INFO_LEVEL *printer = NULL;
8581 nt_forms_struct *list=NULL;
8582 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8584 DEBUG(5,("spoolss_setform\n"));
8587 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8591 /* forms can be modified on printer of on the print server handle */
8593 if ( Printer->printer_type == SPLHND_PRINTER )
8595 if (!get_printer_snum(p,handle, &snum, NULL))
8598 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8599 if (!W_ERROR_IS_OK(status))
8603 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8604 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8605 status = WERR_ACCESS_DENIED;
8609 /* can't set if builtin */
8610 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8611 status = WERR_INVALID_PARAM;
8615 count = get_ntforms(&list);
8616 update_a_form(&list, form, count);
8617 write_ntforms(&list, count);
8620 * ChangeID must always be set if this is a printer
8623 if ( Printer->printer_type == SPLHND_PRINTER )
8624 status = mod_a_printer(printer, 2);
8629 free_a_printer(&printer, 2);
8635 /****************************************************************************
8636 enumprintprocessors level 1.
8637 ****************************************************************************/
8639 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8641 PRINTPROCESSOR_1 *info_1=NULL;
8642 WERROR result = WERR_OK;
8644 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8649 init_unistr(&info_1->name, "winprint");
8651 *needed += spoolss_size_printprocessor_info_1(info_1);
8653 if (*needed > offered) {
8654 result = WERR_INSUFFICIENT_BUFFER;
8658 if (!rpcbuf_alloc_size(buffer, *needed)) {
8659 result = WERR_NOMEM;
8663 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8668 if ( !W_ERROR_IS_OK(result) )
8674 /****************************************************************************
8675 ****************************************************************************/
8677 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8679 uint32 level = q_u->level;
8680 RPC_BUFFER *buffer = NULL;
8681 uint32 offered = q_u->offered;
8682 uint32 *needed = &r_u->needed;
8683 uint32 *returned = &r_u->returned;
8685 /* that's an [in out] buffer */
8687 if (!q_u->buffer && (offered!=0)) {
8688 return WERR_INVALID_PARAM;
8691 rpcbuf_move(q_u->buffer, &r_u->buffer);
8692 buffer = r_u->buffer;
8694 DEBUG(5,("spoolss_enumprintprocessors\n"));
8697 * Enumerate the print processors ...
8699 * Just reply with "winprint", to keep NT happy
8700 * and I can use my nice printer checker.
8708 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8710 return WERR_UNKNOWN_LEVEL;
8714 /****************************************************************************
8715 enumprintprocdatatypes level 1.
8716 ****************************************************************************/
8718 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8720 PRINTPROCDATATYPE_1 *info_1=NULL;
8721 WERROR result = WERR_OK;
8723 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8728 init_unistr(&info_1->name, "RAW");
8730 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8732 if (*needed > offered) {
8733 result = WERR_INSUFFICIENT_BUFFER;
8737 if (!rpcbuf_alloc_size(buffer, *needed)) {
8738 result = WERR_NOMEM;
8742 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8747 if ( !W_ERROR_IS_OK(result) )
8753 /****************************************************************************
8754 ****************************************************************************/
8756 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8758 uint32 level = q_u->level;
8759 RPC_BUFFER *buffer = NULL;
8760 uint32 offered = q_u->offered;
8761 uint32 *needed = &r_u->needed;
8762 uint32 *returned = &r_u->returned;
8764 /* that's an [in out] buffer */
8766 if (!q_u->buffer && (offered!=0)) {
8767 return WERR_INVALID_PARAM;
8770 rpcbuf_move(q_u->buffer, &r_u->buffer);
8771 buffer = r_u->buffer;
8773 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8780 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8782 return WERR_UNKNOWN_LEVEL;
8786 /****************************************************************************
8787 enumprintmonitors level 1.
8788 ****************************************************************************/
8790 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8792 PRINTMONITOR_1 *info_1;
8793 WERROR result = WERR_OK;
8796 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8801 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8802 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8804 for ( i=0; i<*returned; i++ ) {
8805 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8808 if (*needed > offered) {
8809 result = WERR_INSUFFICIENT_BUFFER;
8813 if (!rpcbuf_alloc_size(buffer, *needed)) {
8814 result = WERR_NOMEM;
8818 for ( i=0; i<*returned; i++ ) {
8819 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8825 if ( !W_ERROR_IS_OK(result) )
8831 /****************************************************************************
8832 enumprintmonitors level 2.
8833 ****************************************************************************/
8835 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8837 PRINTMONITOR_2 *info_2;
8838 WERROR result = WERR_OK;
8841 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8846 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8847 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8848 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8850 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8851 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8852 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8854 for ( i=0; i<*returned; i++ ) {
8855 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8858 if (*needed > offered) {
8859 result = WERR_INSUFFICIENT_BUFFER;
8863 if (!rpcbuf_alloc_size(buffer, *needed)) {
8864 result = WERR_NOMEM;
8868 for ( i=0; i<*returned; i++ ) {
8869 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8875 if ( !W_ERROR_IS_OK(result) )
8881 /****************************************************************************
8882 ****************************************************************************/
8884 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8886 uint32 level = q_u->level;
8887 RPC_BUFFER *buffer = NULL;
8888 uint32 offered = q_u->offered;
8889 uint32 *needed = &r_u->needed;
8890 uint32 *returned = &r_u->returned;
8892 /* that's an [in out] buffer */
8894 if (!q_u->buffer && (offered!=0)) {
8895 return WERR_INVALID_PARAM;
8898 rpcbuf_move(q_u->buffer, &r_u->buffer);
8899 buffer = r_u->buffer;
8901 DEBUG(5,("spoolss_enumprintmonitors\n"));
8904 * Enumerate the print monitors ...
8906 * Just reply with "Local Port", to keep NT happy
8907 * and I can use my nice printer checker.
8915 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8917 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8919 return WERR_UNKNOWN_LEVEL;
8923 /****************************************************************************
8924 ****************************************************************************/
8926 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8927 NT_PRINTER_INFO_LEVEL *ntprinter,
8928 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8933 JOB_INFO_1 *info_1=NULL;
8934 WERROR result = WERR_OK;
8936 info_1=SMB_MALLOC_P(JOB_INFO_1);
8938 if (info_1 == NULL) {
8942 for (i=0; i<count && found==False; i++) {
8943 if ((*queue)[i].job==(int)jobid)
8949 /* NT treats not found as bad param... yet another bad choice */
8950 return WERR_INVALID_PARAM;
8953 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8955 *needed += spoolss_size_job_info_1(info_1);
8957 if (*needed > offered) {
8958 result = WERR_INSUFFICIENT_BUFFER;
8962 if (!rpcbuf_alloc_size(buffer, *needed)) {
8963 result = WERR_NOMEM;
8967 smb_io_job_info_1("", buffer, info_1, 0);
8975 /****************************************************************************
8976 ****************************************************************************/
8978 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8979 NT_PRINTER_INFO_LEVEL *ntprinter,
8980 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8987 DEVICEMODE *devmode = NULL;
8988 NT_DEVICEMODE *nt_devmode = NULL;
8990 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8993 ZERO_STRUCTP(info_2);
8995 for ( i=0; i<count && found==False; i++ )
8997 if ((*queue)[i].job == (int)jobid)
9002 /* NT treats not found as bad param... yet another bad
9004 result = WERR_INVALID_PARAM;
9009 * if the print job does not have a DEVMODE associated with it,
9010 * just use the one for the printer. A NULL devicemode is not
9011 * a failure condition
9014 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9015 devmode = construct_dev_mode(lp_const_servicename(snum));
9017 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9018 ZERO_STRUCTP( devmode );
9019 convert_nt_devicemode( devmode, nt_devmode );
9023 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9025 *needed += spoolss_size_job_info_2(info_2);
9027 if (*needed > offered) {
9028 result = WERR_INSUFFICIENT_BUFFER;
9032 if (!rpcbuf_alloc_size(buffer, *needed)) {
9033 result = WERR_NOMEM;
9037 smb_io_job_info_2("", buffer, info_2, 0);
9042 /* Cleanup allocated memory */
9044 free_job_info_2(info_2); /* Also frees devmode */
9050 /****************************************************************************
9051 ****************************************************************************/
9053 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9055 POLICY_HND *handle = &q_u->handle;
9056 uint32 jobid = q_u->jobid;
9057 uint32 level = q_u->level;
9058 RPC_BUFFER *buffer = NULL;
9059 uint32 offered = q_u->offered;
9060 uint32 *needed = &r_u->needed;
9061 WERROR wstatus = WERR_OK;
9062 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9065 print_queue_struct *queue = NULL;
9066 print_status_struct prt_status;
9068 /* that's an [in out] buffer */
9070 if (!q_u->buffer && (offered!=0)) {
9071 return WERR_INVALID_PARAM;
9074 rpcbuf_move(q_u->buffer, &r_u->buffer);
9075 buffer = r_u->buffer;
9077 DEBUG(5,("spoolss_getjob\n"));
9081 if (!get_printer_snum(p, handle, &snum, NULL))
9084 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9085 if ( !W_ERROR_IS_OK(wstatus) )
9088 count = print_queue_status(snum, &queue, &prt_status);
9090 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9091 count, prt_status.status, prt_status.message));
9095 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9096 buffer, offered, needed);
9099 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9100 buffer, offered, needed);
9103 wstatus = WERR_UNKNOWN_LEVEL;
9108 free_a_printer( &ntprinter, 2 );
9113 /********************************************************************
9114 spoolss_getprinterdataex
9116 From MSDN documentation of GetPrinterDataEx: pass request
9117 to GetPrinterData if key is "PrinterDriverData".
9118 ********************************************************************/
9120 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9122 POLICY_HND *handle = &q_u->handle;
9123 uint32 in_size = q_u->size;
9124 uint32 *type = &r_u->type;
9125 uint32 *out_size = &r_u->size;
9126 uint8 **data = &r_u->data;
9127 uint32 *needed = &r_u->needed;
9128 fstring keyname, valuename;
9130 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9132 NT_PRINTER_INFO_LEVEL *printer = NULL;
9134 WERROR status = WERR_OK;
9136 DEBUG(4,("_spoolss_getprinterdataex\n"));
9138 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9139 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9141 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9142 keyname, valuename));
9144 /* in case of problem, return some default values */
9148 *out_size = in_size;
9151 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9152 status = WERR_BADFID;
9156 /* Is the handle to a printer or to the server? */
9158 if (Printer->printer_type == SPLHND_SERVER) {
9159 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9160 status = WERR_INVALID_PARAM;
9164 if ( !get_printer_snum(p,handle, &snum, NULL) )
9167 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9168 if ( !W_ERROR_IS_OK(status) )
9171 /* check to see if the keyname is valid */
9172 if ( !strlen(keyname) ) {
9173 status = WERR_INVALID_PARAM;
9177 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9178 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9179 free_a_printer( &printer, 2 );
9180 status = WERR_BADFILE;
9184 /* When given a new keyname, we should just create it */
9186 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9188 if (*needed > *out_size)
9189 status = WERR_MORE_DATA;
9192 if ( !W_ERROR_IS_OK(status) )
9194 DEBUG(5, ("error: allocating %d\n", *out_size));
9196 /* reply this param doesn't exist */
9200 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9201 status = WERR_NOMEM;
9210 free_a_printer( &printer, 2 );
9215 /********************************************************************
9216 * spoolss_setprinterdataex
9217 ********************************************************************/
9219 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9221 POLICY_HND *handle = &q_u->handle;
9222 uint32 type = q_u->type;
9223 uint8 *data = q_u->data;
9224 uint32 real_len = q_u->real_len;
9226 NT_PRINTER_INFO_LEVEL *printer = NULL;
9228 WERROR status = WERR_OK;
9229 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9234 DEBUG(4,("_spoolss_setprinterdataex\n"));
9236 /* From MSDN documentation of SetPrinterDataEx: pass request to
9237 SetPrinterData if key is "PrinterDriverData" */
9240 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9244 if ( Printer->printer_type == SPLHND_SERVER ) {
9245 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9246 return WERR_INVALID_PARAM;
9249 if ( !get_printer_snum(p,handle, &snum, NULL) )
9253 * Access check : NT returns "access denied" if you make a
9254 * SetPrinterData call without the necessary privildge.
9255 * we were originally returning OK if nothing changed
9256 * which made Win2k issue **a lot** of SetPrinterData
9257 * when connecting to a printer --jerry
9260 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9262 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9263 return WERR_ACCESS_DENIED;
9266 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9267 if (!W_ERROR_IS_OK(status))
9270 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9271 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9273 /* check for OID in valuename */
9275 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9281 /* save the registry data */
9283 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9285 if ( W_ERROR_IS_OK(status) )
9287 /* save the OID if one was specified */
9289 fstrcat( keyname, "\\" );
9290 fstrcat( keyname, SPOOL_OID_KEY );
9293 * I'm not checking the status here on purpose. Don't know
9294 * if this is right, but I'm returning the status from the
9295 * previous set_printer_dataex() call. I have no idea if
9296 * this is right. --jerry
9299 set_printer_dataex( printer, keyname, valuename,
9300 REG_SZ, (uint8 *)oid_string,
9301 strlen(oid_string)+1 );
9304 status = mod_a_printer(printer, 2);
9307 free_a_printer(&printer, 2);
9313 /********************************************************************
9314 * spoolss_deleteprinterdataex
9315 ********************************************************************/
9317 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9319 POLICY_HND *handle = &q_u->handle;
9320 UNISTR2 *value = &q_u->valuename;
9321 UNISTR2 *key = &q_u->keyname;
9323 NT_PRINTER_INFO_LEVEL *printer = NULL;
9325 WERROR status = WERR_OK;
9326 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9327 char *valuename = NULL;
9328 char *keyname = NULL;
9329 TALLOC_CTX *ctx = p->mem_ctx;
9331 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9334 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9338 if (!get_printer_snum(p, handle, &snum, NULL))
9341 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9342 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9343 return WERR_ACCESS_DENIED;
9346 valuename = unistr2_to_ascii_talloc(ctx, value);
9347 keyname = unistr2_to_ascii_talloc(ctx, key);
9348 if (!valuename || !keyname) {
9352 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9353 if (!W_ERROR_IS_OK(status))
9356 status = delete_printer_dataex( printer, keyname, valuename );
9358 if ( W_ERROR_IS_OK(status) )
9359 mod_a_printer( printer, 2 );
9361 free_a_printer(&printer, 2);
9366 /********************************************************************
9367 * spoolss_enumprinterkey
9368 ********************************************************************/
9371 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9374 fstring *keynames = NULL;
9375 uint16 *enumkeys = NULL;
9378 POLICY_HND *handle = &q_u->handle;
9379 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9380 NT_PRINTER_DATA *data;
9381 NT_PRINTER_INFO_LEVEL *printer = NULL;
9383 WERROR status = WERR_BADFILE;
9386 DEBUG(4,("_spoolss_enumprinterkey\n"));
9389 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9393 if ( !get_printer_snum(p,handle, &snum, NULL) )
9396 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9397 if (!W_ERROR_IS_OK(status))
9400 /* get the list of subkey names */
9402 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9403 data = printer->info_2->data;
9405 num_keys = get_printer_subkeys( data, key, &keynames );
9407 if ( num_keys == -1 ) {
9408 status = WERR_BADFILE;
9412 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9414 r_u->needed = printerkey_len*2;
9416 if ( q_u->size < r_u->needed ) {
9417 status = WERR_MORE_DATA;
9421 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9422 status = WERR_NOMEM;
9428 if ( q_u->size < r_u->needed )
9429 status = WERR_MORE_DATA;
9432 free_a_printer( &printer, 2 );
9433 SAFE_FREE( keynames );
9438 /********************************************************************
9439 * spoolss_deleteprinterkey
9440 ********************************************************************/
9442 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9444 POLICY_HND *handle = &q_u->handle;
9445 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9447 NT_PRINTER_INFO_LEVEL *printer = NULL;
9451 DEBUG(5,("spoolss_deleteprinterkey\n"));
9454 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9458 /* if keyname == NULL, return error */
9460 if ( !q_u->keyname.buffer )
9461 return WERR_INVALID_PARAM;
9463 if (!get_printer_snum(p, handle, &snum, NULL))
9466 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9467 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9468 return WERR_ACCESS_DENIED;
9471 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9472 if (!W_ERROR_IS_OK(status))
9475 /* delete the key and all subneys */
9477 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9479 status = delete_all_printer_data( printer->info_2, key );
9481 if ( W_ERROR_IS_OK(status) )
9482 status = mod_a_printer(printer, 2);
9484 free_a_printer( &printer, 2 );
9490 /********************************************************************
9491 * spoolss_enumprinterdataex
9492 ********************************************************************/
9494 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9496 POLICY_HND *handle = &q_u->handle;
9497 uint32 in_size = q_u->size;
9500 NT_PRINTER_INFO_LEVEL *printer = NULL;
9501 PRINTER_ENUM_VALUES *enum_values = NULL;
9502 NT_PRINTER_DATA *p_data;
9504 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9509 REGISTRY_VALUE *val;
9514 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9517 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9522 * first check for a keyname of NULL or "". Win2k seems to send
9523 * this a lot and we should send back WERR_INVALID_PARAM
9524 * no need to spend time looking up the printer in this case.
9528 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9529 if ( !strlen(key) ) {
9530 result = WERR_INVALID_PARAM;
9534 /* get the printer off of disk */
9536 if (!get_printer_snum(p,handle, &snum, NULL))
9539 ZERO_STRUCT(printer);
9540 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9541 if (!W_ERROR_IS_OK(result))
9544 /* now look for a match on the key name */
9546 p_data = printer->info_2->data;
9548 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9549 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9551 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9552 result = WERR_INVALID_PARAM;
9559 /* allocate the memory for the array of pointers -- if necessary */
9561 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9564 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9566 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9567 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9568 result = WERR_NOMEM;
9572 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9576 * loop through all params and build the array to pass
9577 * back to the client
9580 for ( i=0; i<num_entries; i++ )
9582 /* lookup the registry value */
9584 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9585 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9589 value_name = regval_name( val );
9590 init_unistr( &enum_values[i].valuename, value_name );
9591 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9592 enum_values[i].type = regval_type( val );
9594 data_len = regval_size( val );
9596 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9598 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9600 result = WERR_NOMEM;
9604 enum_values[i].data_len = data_len;
9606 /* keep track of the size of the array in bytes */
9608 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9611 /* housekeeping information in the reply */
9613 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9614 * the hand marshalled container size is a multiple
9615 * of 4 bytes for RPC alignment.
9619 needed += 4-(needed % 4);
9622 r_u->needed = needed;
9623 r_u->returned = num_entries;
9625 if (needed > in_size) {
9626 result = WERR_MORE_DATA;
9630 /* copy data into the reply */
9632 /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9633 response buffer size is != the offered buffer size
9635 r_u->ctr.size = r_u->needed;
9637 r_u->ctr.size = in_size;
9639 r_u->ctr.size_of_array = r_u->returned;
9640 r_u->ctr.values = enum_values;
9644 free_a_printer(&printer, 2);
9649 /****************************************************************************
9650 ****************************************************************************/
9652 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9654 init_unistr(&info->name, name);
9657 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9658 UNISTR2 *environment,
9663 char *long_archi = NULL;
9664 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9665 WERROR result = WERR_OK;
9666 TALLOC_CTX *ctx = talloc_tos();
9668 long_archi = unistr2_to_ascii_talloc(ctx, environment);
9673 if (!get_short_archi(long_archi))
9674 return WERR_INVALID_ENVIRONMENT;
9676 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9679 fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9681 *needed += spoolss_size_printprocessordirectory_info_1(info);
9683 if (*needed > offered) {
9684 result = WERR_INSUFFICIENT_BUFFER;
9688 if (!rpcbuf_alloc_size(buffer, *needed)) {
9689 result = WERR_INSUFFICIENT_BUFFER;
9693 smb_io_printprocessordirectory_1("", buffer, info, 0);
9701 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9703 uint32 level = q_u->level;
9704 RPC_BUFFER *buffer = NULL;
9705 uint32 offered = q_u->offered;
9706 uint32 *needed = &r_u->needed;
9709 /* that's an [in out] buffer */
9711 if (!q_u->buffer && (offered!=0)) {
9712 return WERR_INVALID_PARAM;
9715 rpcbuf_move(q_u->buffer, &r_u->buffer);
9716 buffer = r_u->buffer;
9718 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9724 result = getprintprocessordirectory_level_1
9725 (&q_u->name, &q_u->environment, buffer, offered, needed);
9728 result = WERR_UNKNOWN_LEVEL;
9734 /*******************************************************************
9735 Streams the monitor UI DLL name in UNICODE
9736 *******************************************************************/
9738 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9739 RPC_BUFFER *out, uint32 *needed )
9741 const char *dllname = "tcpmonui.dll";
9743 *needed = (strlen(dllname)+1) * 2;
9745 if ( rpcbuf_get_size(out) < *needed ) {
9746 return WERR_INSUFFICIENT_BUFFER;
9749 if ( !make_monitorui_buf( out, dllname ) ) {
9756 /*******************************************************************
9757 Create a new TCP/IP port
9758 *******************************************************************/
9760 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9761 RPC_BUFFER *out, uint32 *needed )
9763 NT_PORT_DATA_1 port1;
9764 TALLOC_CTX *ctx = talloc_tos();
9765 char *device_uri = NULL;
9767 ZERO_STRUCT( port1 );
9769 /* convert to our internal port data structure */
9771 if ( !convert_port_data_1( &port1, in ) ) {
9775 /* create the device URI and call the add_port_hook() */
9777 switch ( port1.protocol ) {
9778 case PORT_PROTOCOL_DIRECT:
9779 device_uri = talloc_asprintf(ctx,
9780 "socket://%s:%d/", port1.hostaddr, port1.port );
9783 case PORT_PROTOCOL_LPR:
9784 device_uri = talloc_asprintf(ctx,
9785 "lpr://%s/%s", port1.hostaddr, port1.queue );
9789 return WERR_UNKNOWN_PORT;
9796 return add_port_hook(ctx, token, port1.name, device_uri );
9799 /*******************************************************************
9800 *******************************************************************/
9802 struct xcv_api_table xcvtcp_cmds[] = {
9803 { "MonitorUI", xcvtcp_monitorui },
9804 { "AddPort", xcvtcp_addport},
9808 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9809 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9814 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9816 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9817 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9818 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9821 return WERR_BADFUNC;
9824 /*******************************************************************
9825 *******************************************************************/
9826 #if 0 /* don't support management using the "Local Port" monitor */
9828 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9829 RPC_BUFFER *out, uint32 *needed )
9831 const char *dllname = "localui.dll";
9833 *needed = (strlen(dllname)+1) * 2;
9835 if ( rpcbuf_get_size(out) < *needed ) {
9836 return WERR_INSUFFICIENT_BUFFER;
9839 if ( !make_monitorui_buf( out, dllname )) {
9846 /*******************************************************************
9847 *******************************************************************/
9849 struct xcv_api_table xcvlocal_cmds[] = {
9850 { "MonitorUI", xcvlocal_monitorui },
9854 struct xcv_api_table xcvlocal_cmds[] = {
9861 /*******************************************************************
9862 *******************************************************************/
9864 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9865 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9870 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9872 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9873 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9874 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9876 return WERR_BADFUNC;
9879 /*******************************************************************
9880 *******************************************************************/
9882 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9884 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9888 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9892 /* Has to be a handle to the TCP/IP port monitor */
9894 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9895 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9899 /* requires administrative access to the server */
9901 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9902 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9903 return WERR_ACCESS_DENIED;
9906 /* Get the command name. There's numerous commands supported by the
9907 TCPMON interface. */
9909 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9910 q_u->dataname.uni_str_len*2, 0);
9912 /* Allocate the outgoing buffer */
9914 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9916 switch ( Printer->printer_type ) {
9917 case SPLHND_PORTMON_TCP:
9918 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9919 &q_u->indata, &r_u->outdata, &r_u->needed );
9920 case SPLHND_PORTMON_LOCAL:
9921 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9922 &q_u->indata, &r_u->outdata, &r_u->needed );
9925 return WERR_INVALID_PRINT_MONITOR;