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 2 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, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern userdom_struct current_user_info;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 const char *long_archi;
45 const char *short_archi;
49 static Printer_entry *printers_list;
51 typedef struct _counter_printer_0 {
52 struct _counter_printer_0 *next;
53 struct _counter_printer_0 *prev;
59 static counter_printer_0 *counter_list;
61 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
62 static uint32 smb_connections=0;
65 /* in printing/nt_printing.c */
67 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
69 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
70 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
73 /* API table for Xcv Monitor functions */
75 struct xcv_api_table {
77 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
81 /* translate between internal status numbers and NT status numbers */
82 static int nt_printj_status(int v)
88 return JOB_STATUS_PAUSED;
90 return JOB_STATUS_SPOOLING;
92 return JOB_STATUS_PRINTING;
94 return JOB_STATUS_ERROR;
96 return JOB_STATUS_DELETING;
98 return JOB_STATUS_OFFLINE;
100 return JOB_STATUS_PAPEROUT;
102 return JOB_STATUS_PRINTED;
104 return JOB_STATUS_DELETED;
106 return JOB_STATUS_BLOCKED;
107 case LPQ_USER_INTERVENTION:
108 return JOB_STATUS_USER_INTERVENTION;
113 static int nt_printq_status(int v)
117 return PRINTER_STATUS_PAUSED;
126 /****************************************************************************
127 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
128 ****************************************************************************/
130 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
135 SAFE_FREE((*pp)->ctr.type);
139 /***************************************************************************
140 Disconnect from the client
141 ****************************************************************************/
143 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
148 * Tell the specific printing tdb we no longer want messages for this printer
149 * by deregistering our PID.
152 if (!print_notify_deregister_pid(snum))
153 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
155 /* weird if the test succeds !!! */
156 if (smb_connections==0) {
157 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
161 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
163 if (!W_ERROR_IS_OK(result))
164 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
165 dos_errstr(result)));
167 /* if it's the last connection, deconnect the IPC$ share */
168 if (smb_connections==1) {
170 cli_shutdown( notify_cli_pipe->cli );
171 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
173 message_deregister(MSG_PRINTER_NOTIFY2);
175 /* Tell the connections db we're no longer interested in
176 * printer notify messages. */
178 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
184 /****************************************************************************
185 Functions to free a printer entry datastruct.
186 ****************************************************************************/
188 static void free_printer_entry(void *ptr)
190 Printer_entry *Printer = (Printer_entry *)ptr;
192 if (Printer->notify.client_connected==True) {
195 if ( Printer->printer_type == SPLHND_SERVER) {
197 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
198 } else if (Printer->printer_type == SPLHND_PRINTER) {
199 snum = print_queue_snum(Printer->sharename);
201 srv_spoolss_replycloseprinter(snum,
202 &Printer->notify.client_hnd);
206 Printer->notify.flags=0;
207 Printer->notify.options=0;
208 Printer->notify.localmachine[0]='\0';
209 Printer->notify.printerlocal=0;
210 free_spool_notify_option(&Printer->notify.option);
211 Printer->notify.option=NULL;
212 Printer->notify.client_connected=False;
214 free_nt_devicemode( &Printer->nt_devmode );
215 free_a_printer( &Printer->printer_info, 2 );
217 talloc_destroy( Printer->ctx );
219 /* Remove from the internal list. */
220 DLIST_REMOVE(printers_list, Printer);
225 /****************************************************************************
226 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
227 ****************************************************************************/
229 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
231 SPOOL_NOTIFY_OPTION *new_sp = NULL;
236 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
243 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
245 if (!new_sp->ctr.type) {
254 /****************************************************************************
255 find printer index by handle
256 ****************************************************************************/
258 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
260 Printer_entry *find_printer = NULL;
262 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
263 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
270 /****************************************************************************
271 Close printer index by handle.
272 ****************************************************************************/
274 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
276 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
279 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
283 close_policy_hnd(p, hnd);
288 /****************************************************************************
289 Delete a printer given a handle.
290 ****************************************************************************/
291 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
293 char *cmd = lp_deleteprinter_cmd();
296 SE_PRIV se_printop = SE_PRINT_OPERATOR;
297 BOOL is_print_op = False;
299 /* can't fail if we don't try */
304 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
307 is_print_op = user_has_privileges( token, &se_printop );
309 DEBUG(10,("Running [%s]\n", command));
311 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
316 if ( (ret = smbrun(command, NULL)) == 0 ) {
317 /* Tell everyone we updated smb.conf. */
318 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
324 /********** END SePrintOperatorPrivlege BLOCK **********/
326 DEBUGADD(10,("returned [%d]\n", ret));
329 return WERR_BADFID; /* What to return here? */
331 /* go ahead and re-read the services immediately */
332 reload_services( False );
334 if ( share_defined( sharename ) )
335 return WERR_ACCESS_DENIED;
340 /****************************************************************************
341 Delete a printer given a handle.
342 ****************************************************************************/
344 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
346 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
349 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
354 * It turns out that Windows allows delete printer on a handle
355 * opened by an admin user, then used on a pipe handle created
356 * by an anonymous user..... but they're working on security.... riiight !
360 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
361 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
362 return WERR_ACCESS_DENIED;
365 /* this does not need a become root since the access check has been
366 done on the handle already */
368 if (del_a_printer( Printer->sharename ) != 0) {
369 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
373 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
376 /****************************************************************************
377 Return the snum of a printer corresponding to an handle.
378 ****************************************************************************/
380 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
382 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
385 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
389 switch (Printer->printer_type) {
391 DEBUG(4,("short name:%s\n", Printer->sharename));
392 *number = print_queue_snum(Printer->sharename);
393 return (*number != -1);
401 /****************************************************************************
402 Set printer handle type.
403 Check if it's \\server or \\server\printer
404 ****************************************************************************/
406 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
408 DEBUG(3,("Setting printer type=%s\n", handlename));
410 if ( strlen(handlename) < 3 ) {
411 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
415 /* it's a print server */
416 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
417 DEBUGADD(4,("Printer is a print server\n"));
418 Printer->printer_type = SPLHND_SERVER;
420 /* it's a printer (set_printer_hnd_name() will handle port monitors */
422 DEBUGADD(4,("Printer is a printer\n"));
423 Printer->printer_type = SPLHND_PRINTER;
429 /****************************************************************************
430 Set printer handle name.. Accept names like \\server, \\server\printer,
431 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
432 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
433 XcvDataPort() interface.
434 ****************************************************************************/
436 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
439 int n_services=lp_numservices();
440 char *aprinter, *printername;
441 const char *servername;
444 NT_PRINTER_INFO_LEVEL *printer = NULL;
447 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
449 aprinter = handlename;
450 if ( *handlename == '\\' ) {
451 servername = handlename + 2;
452 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
461 /* save the servername to fill in replies on this handle */
463 if ( !is_myname_or_ipaddr( servername ) )
466 fstrcpy( Printer->servername, servername );
468 if ( Printer->printer_type == SPLHND_SERVER )
471 if ( Printer->printer_type != SPLHND_PRINTER )
474 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
476 /* check for the Port Monitor Interface */
478 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
479 Printer->printer_type = SPLHND_PORTMON_TCP;
480 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
483 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
484 Printer->printer_type = SPLHND_PORTMON_LOCAL;
485 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
489 /* Search all sharenames first as this is easier than pulling
490 the printer_info_2 off of disk. Don't use find_service() since
491 that calls out to map_username() */
493 /* do another loop to look for printernames */
495 for (snum=0; !found && snum<n_services; snum++) {
497 /* no point going on if this is not a printer */
499 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
502 fstrcpy(sname, lp_servicename(snum));
503 if ( strequal( aprinter, sname ) ) {
508 /* no point looking up the printer object if
509 we aren't allowing printername != sharename */
511 if ( lp_force_printername(snum) )
514 fstrcpy(sname, lp_servicename(snum));
517 result = get_a_printer( NULL, &printer, 2, sname );
518 if ( !W_ERROR_IS_OK(result) ) {
519 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
520 sname, dos_errstr(result)));
524 /* printername is always returned as \\server\printername */
525 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
526 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
527 printer->info_2->printername));
528 free_a_printer( &printer, 2);
534 if ( strequal(printername, aprinter) ) {
535 free_a_printer( &printer, 2);
540 DEBUGADD(10, ("printername: %s\n", printername));
542 free_a_printer( &printer, 2);
545 free_a_printer( &printer, 2);
548 DEBUGADD(4,("Printer not found\n"));
552 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
554 fstrcpy(Printer->sharename, sname);
559 /****************************************************************************
560 Find first available printer slot. creates a printer handle for you.
561 ****************************************************************************/
563 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
565 Printer_entry *new_printer;
567 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
569 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
572 ZERO_STRUCTP(new_printer);
574 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
575 SAFE_FREE(new_printer);
579 /* Add to the internal list. */
580 DLIST_ADD(printers_list, new_printer);
582 new_printer->notify.option=NULL;
584 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
585 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
586 close_printer_handle(p, hnd);
590 if (!set_printer_hnd_printertype(new_printer, name)) {
591 close_printer_handle(p, hnd);
595 if (!set_printer_hnd_name(new_printer, name)) {
596 close_printer_handle(p, hnd);
600 new_printer->access_granted = access_granted;
602 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
607 /***************************************************************************
608 check to see if the client motify handle is monitoring the notification
609 given by (notify_type, notify_field).
610 **************************************************************************/
612 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
618 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
621 SPOOL_NOTIFY_OPTION *option = p->notify.option;
625 * Flags should always be zero when the change notify
626 * is registered by the client's spooler. A user Win32 app
627 * might use the flags though instead of the NOTIFY_OPTION_INFO
636 return is_monitoring_event_flags(
637 p->notify.flags, notify_type, notify_field);
639 for (i = 0; i < option->count; i++) {
641 /* Check match for notify_type */
643 if (option->ctr.type[i].type != notify_type)
646 /* Check match for field */
648 for (j = 0; j < option->ctr.type[i].count; j++) {
649 if (option->ctr.type[i].fields[j] == notify_field) {
655 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
656 p->servername, p->sharename, notify_type, notify_field));
661 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
663 static void notify_one_value(struct spoolss_notify_msg *msg,
664 SPOOL_NOTIFY_INFO_DATA *data,
667 data->notify_data.value[0] = msg->notify.value[0];
668 data->notify_data.value[1] = 0;
671 static void notify_string(struct spoolss_notify_msg *msg,
672 SPOOL_NOTIFY_INFO_DATA *data,
677 /* The length of the message includes the trailing \0 */
679 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
681 data->notify_data.data.length = msg->len * 2;
682 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
684 if (!data->notify_data.data.string) {
685 data->notify_data.data.length = 0;
689 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
692 static void notify_system_time(struct spoolss_notify_msg *msg,
693 SPOOL_NOTIFY_INFO_DATA *data,
699 if (msg->len != sizeof(time_t)) {
700 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
705 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
706 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
710 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
711 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
716 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
721 data->notify_data.data.length = prs_offset(&ps);
722 data->notify_data.data.string = (uint16 *)
723 TALLOC(mem_ctx, prs_offset(&ps));
724 if (!data->notify_data.data.string) {
729 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
734 struct notify2_message_table {
736 void (*fn)(struct spoolss_notify_msg *msg,
737 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
740 static struct notify2_message_table printer_notify_table[] = {
741 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
742 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
743 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
744 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
745 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
746 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
747 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
748 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
749 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
750 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
751 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
752 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
753 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
754 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
755 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
756 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
757 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
758 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
759 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
762 static struct notify2_message_table job_notify_table[] = {
763 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
764 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
765 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
766 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
767 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
768 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
769 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
770 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
771 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
772 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
773 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
774 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
775 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
776 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
777 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
778 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
779 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
780 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
781 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
782 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
783 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
784 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
785 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
786 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
790 /***********************************************************************
791 Allocate talloc context for container object
792 **********************************************************************/
794 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
799 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
804 /***********************************************************************
805 release all allocated memory and zero out structure
806 **********************************************************************/
808 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
814 talloc_destroy(ctr->ctx);
821 /***********************************************************************
822 **********************************************************************/
824 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
832 /***********************************************************************
833 **********************************************************************/
835 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
837 if ( !ctr || !ctr->msg_groups )
840 if ( idx >= ctr->num_groups )
843 return &ctr->msg_groups[idx];
847 /***********************************************************************
848 How many groups of change messages do we have ?
849 **********************************************************************/
851 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
856 return ctr->num_groups;
859 /***********************************************************************
860 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
861 **********************************************************************/
863 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
865 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
866 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
867 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
873 /* loop over all groups looking for a matching printer name */
875 for ( i=0; i<ctr->num_groups; i++ ) {
876 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
880 /* add a new group? */
882 if ( i == ctr->num_groups ) {
885 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
886 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
889 ctr->msg_groups = groups;
891 /* clear the new entry and set the printer name */
893 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
894 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
897 /* add the change messages; 'i' is the correct index now regardless */
899 msg_grp = &ctr->msg_groups[i];
903 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
904 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
907 msg_grp->msgs = msg_list;
909 new_slot = msg_grp->num_msgs-1;
910 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
912 /* need to allocate own copy of data */
915 msg_grp->msgs[new_slot].notify.data = (char *)
916 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
918 return ctr->num_groups;
921 /***********************************************************************
922 Send a change notication message on all handles which have a call
924 **********************************************************************/
926 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
929 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
930 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
931 SPOOLSS_NOTIFY_MSG *messages;
932 int sending_msg_count;
935 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
939 messages = msg_group->msgs;
942 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
946 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
948 /* loop over all printers */
950 for (p = printers_list; p; p = p->next) {
951 SPOOL_NOTIFY_INFO_DATA *data;
956 /* Is there notification on this handle? */
958 if ( !p->notify.client_connected )
961 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
963 /* For this printer? Print servers always receive
966 if ( ( p->printer_type == SPLHND_PRINTER ) &&
967 ( !strequal(msg_group->printername, p->sharename) ) )
970 DEBUG(10,("Our printer\n"));
972 /* allocate the max entries possible */
974 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
981 /* build the array of change notifications */
983 sending_msg_count = 0;
985 for ( i=0; i<msg_group->num_msgs; i++ ) {
986 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
988 /* Are we monitoring this event? */
990 if (!is_monitoring_event(p, msg->type, msg->field))
996 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
997 msg->type, msg->field, p->sharename));
1000 * if the is a printer notification handle and not a job notification
1001 * type, then set the id to 0. Other wise just use what was specified
1004 * When registering change notification on a print server handle
1005 * we always need to send back the id (snum) matching the printer
1006 * for which the change took place. For change notify registered
1007 * on a printer handle, this does not matter and the id should be 0.
1012 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1018 /* Convert unix jobid to smb jobid */
1020 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1021 id = sysjob_to_jobid(msg->id);
1024 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1029 construct_info_data( &data[data_len], msg->type, msg->field, id );
1032 case PRINTER_NOTIFY_TYPE:
1033 if ( printer_notify_table[msg->field].fn )
1034 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1037 case JOB_NOTIFY_TYPE:
1038 if ( job_notify_table[msg->field].fn )
1039 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1043 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1050 if ( sending_msg_count ) {
1051 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1052 data_len, data, p->notify.change, 0 );
1057 DEBUG(8,("send_notify2_changes: Exit...\n"));
1061 /***********************************************************************
1062 **********************************************************************/
1064 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1067 uint32 tv_sec, tv_usec;
1070 /* Unpack message */
1072 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1075 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1077 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1080 tdb_unpack((char *)buf + offset, len - offset, "dd",
1081 &msg->notify.value[0], &msg->notify.value[1]);
1083 tdb_unpack((char *)buf + offset, len - offset, "B",
1084 &msg->len, &msg->notify.data);
1086 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1087 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1089 tv->tv_sec = tv_sec;
1090 tv->tv_usec = tv_usec;
1093 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1094 msg->notify.value[1]));
1096 dump_data(3, msg->notify.data, msg->len);
1101 /********************************************************************
1102 Receive a notify2 message list
1103 ********************************************************************/
1105 static void receive_notify2_message_list(int msg_type, struct process_id src,
1106 void *msg, size_t len)
1108 size_t msg_count, i;
1109 char *buf = (char *)msg;
1112 SPOOLSS_NOTIFY_MSG notify;
1113 SPOOLSS_NOTIFY_MSG_CTR messages;
1117 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1121 msg_count = IVAL(buf, 0);
1124 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1126 if (msg_count == 0) {
1127 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1131 /* initialize the container */
1133 ZERO_STRUCT( messages );
1134 notify_msg_ctr_init( &messages );
1137 * build message groups for each printer identified
1138 * in a change_notify msg. Remember that a PCN message
1139 * includes the handle returned for the srv_spoolss_replyopenprinter()
1140 * call. Therefore messages are grouped according to printer handle.
1143 for ( i=0; i<msg_count; i++ ) {
1144 struct timeval msg_tv;
1146 if (msg_ptr + 4 - buf > len) {
1147 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1151 msg_len = IVAL(msg_ptr,0);
1154 if (msg_ptr + msg_len - buf > len) {
1155 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1159 /* unpack messages */
1161 ZERO_STRUCT( notify );
1162 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1165 /* add to correct list in container */
1167 notify_msg_ctr_addmsg( &messages, ¬ify );
1169 /* free memory that might have been allocated by notify2_unpack_msg() */
1171 if ( notify.len != 0 )
1172 SAFE_FREE( notify.notify.data );
1175 /* process each group of messages */
1177 num_groups = notify_msg_ctr_numgroups( &messages );
1178 for ( i=0; i<num_groups; i++ )
1179 send_notify2_changes( &messages, i );
1184 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1186 notify_msg_ctr_destroy( &messages );
1191 /********************************************************************
1192 Send a message to ourself about new driver being installed
1193 so we can upgrade the information for each printer bound to this
1195 ********************************************************************/
1197 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1199 int len = strlen(drivername);
1204 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1207 message_send_pid(pid_to_procid(sys_getpid()),
1208 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1213 /**********************************************************************
1214 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1215 over all printers, upgrading ones as necessary
1216 **********************************************************************/
1218 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1222 int n_services = lp_numservices();
1224 len = MIN(len,sizeof(drivername)-1);
1225 strncpy(drivername, (const char *)buf, len);
1227 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1229 /* Iterate the printer list */
1231 for (snum=0; snum<n_services; snum++)
1233 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1236 NT_PRINTER_INFO_LEVEL *printer = NULL;
1238 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1239 if (!W_ERROR_IS_OK(result))
1242 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1244 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1246 /* all we care about currently is the change_id */
1248 result = mod_a_printer(printer, 2);
1249 if (!W_ERROR_IS_OK(result)) {
1250 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1251 dos_errstr(result)));
1255 free_a_printer(&printer, 2);
1262 /********************************************************************
1263 Update the cache for all printq's with a registered client
1265 ********************************************************************/
1267 void update_monitored_printq_cache( void )
1269 Printer_entry *printer = printers_list;
1272 /* loop through all printers and update the cache where
1273 client_connected == True */
1276 if ( (printer->printer_type == SPLHND_PRINTER)
1277 && printer->notify.client_connected )
1279 snum = print_queue_snum(printer->sharename);
1280 print_queue_status( snum, NULL, NULL );
1283 printer = printer->next;
1288 /********************************************************************
1289 Send a message to ourself about new driver being installed
1290 so we can upgrade the information for each printer bound to this
1292 ********************************************************************/
1294 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1296 int len = strlen(drivername);
1301 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1304 message_send_pid(pid_to_procid(sys_getpid()),
1305 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1310 /**********************************************************************
1311 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1312 over all printers, resetting printer data as neessary
1313 **********************************************************************/
1315 void reset_all_printerdata(int msg_type, struct process_id src,
1316 void *buf, size_t len)
1320 int n_services = lp_numservices();
1322 len = MIN( len, sizeof(drivername)-1 );
1323 strncpy( drivername, (const char *)buf, len );
1325 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1327 /* Iterate the printer list */
1329 for ( snum=0; snum<n_services; snum++ )
1331 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1334 NT_PRINTER_INFO_LEVEL *printer = NULL;
1336 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1337 if ( !W_ERROR_IS_OK(result) )
1341 * if the printer is bound to the driver,
1342 * then reset to the new driver initdata
1345 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1347 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1349 if ( !set_driver_init(printer, 2) ) {
1350 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1351 printer->info_2->printername, printer->info_2->drivername));
1354 result = mod_a_printer( printer, 2 );
1355 if ( !W_ERROR_IS_OK(result) ) {
1356 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1357 get_dos_error_msg(result)));
1361 free_a_printer( &printer, 2 );
1370 /********************************************************************
1371 Copy routines used by convert_to_openprinterex()
1372 *******************************************************************/
1374 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1382 DEBUG (8,("dup_devmode\n"));
1384 /* bulk copy first */
1386 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1390 /* dup the pointer members separately */
1392 len = unistrlen(devmode->devicename.buffer);
1394 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1395 if (!d->devicename.buffer) {
1398 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1403 len = unistrlen(devmode->formname.buffer);
1405 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1406 if (!d->devicename.buffer) {
1409 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1413 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1414 devmode->driverextra);
1415 if (!d->dev_private) {
1421 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1423 if (!new_ctr || !ctr)
1426 DEBUG(8,("copy_devmode_ctr\n"));
1428 new_ctr->size = ctr->size;
1429 new_ctr->devmode_ptr = ctr->devmode_ptr;
1431 if(ctr->devmode_ptr)
1432 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1435 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1437 if (!new_def || !def)
1440 DEBUG(8,("copy_printer_defaults\n"));
1442 new_def->datatype_ptr = def->datatype_ptr;
1444 if (def->datatype_ptr)
1445 copy_unistr2(&new_def->datatype, &def->datatype);
1447 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1449 new_def->access_required = def->access_required;
1452 /********************************************************************
1453 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1454 * SPOOL_Q_OPEN_PRINTER_EX structure
1455 ********************************************************************/
1457 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1459 if (!q_u_ex || !q_u)
1462 DEBUG(8,("convert_to_openprinterex\n"));
1464 if ( q_u->printername ) {
1465 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1466 if (q_u_ex->printername == NULL)
1468 copy_unistr2(q_u_ex->printername, q_u->printername);
1471 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1476 /********************************************************************
1477 * spoolss_open_printer
1479 * called from the spoolss dispatcher
1480 ********************************************************************/
1482 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1484 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1485 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1490 ZERO_STRUCT(q_u_ex);
1491 ZERO_STRUCT(r_u_ex);
1493 /* convert the OpenPrinter() call to OpenPrinterEx() */
1495 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1496 if (!W_ERROR_IS_OK(r_u_ex.status))
1497 return r_u_ex.status;
1499 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1501 /* convert back to OpenPrinter() */
1503 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1508 /********************************************************************
1509 ********************************************************************/
1511 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1513 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1514 POLICY_HND *handle = &r_u->handle;
1518 Printer_entry *Printer=NULL;
1520 if ( !q_u->printername )
1521 return WERR_INVALID_PRINTER_NAME;
1523 /* some sanity check because you can open a printer or a print server */
1524 /* aka: \\server\printer or \\server */
1526 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1528 DEBUGADD(3,("checking name: %s\n",name));
1530 if (!open_printer_hnd(p, handle, name, 0))
1531 return WERR_INVALID_PRINTER_NAME;
1533 Printer=find_printer_index_by_hnd(p, handle);
1535 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1536 "handle we created for printer %s\n", name ));
1537 close_printer_handle(p,handle);
1538 return WERR_INVALID_PRINTER_NAME;
1542 * First case: the user is opening the print server:
1544 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1545 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1547 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1548 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1549 * or if the user is listed in the smb.conf printer admin parameter.
1551 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1552 * client view printer folder, but does not show the MSAPW.
1554 * Note: this test needs code to check access rights here too. Jeremy
1555 * could you look at this?
1557 * Second case: the user is opening a printer:
1558 * NT doesn't let us connect to a printer if the connecting user
1559 * doesn't have print permission.
1561 * Third case: user is opening a Port Monitor
1562 * access checks same as opening a handle to the print server.
1565 switch (Printer->printer_type )
1568 case SPLHND_PORTMON_TCP:
1569 case SPLHND_PORTMON_LOCAL:
1570 /* Printserver handles use global struct... */
1574 /* Map standard access rights to object specific access rights */
1576 se_map_standard(&printer_default->access_required,
1577 &printserver_std_mapping);
1579 /* Deny any object specific bits that don't apply to print
1580 servers (i.e printer and job specific bits) */
1582 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1584 if (printer_default->access_required &
1585 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1586 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1587 close_printer_handle(p, handle);
1588 return WERR_ACCESS_DENIED;
1591 /* Allow admin access */
1593 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1595 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1597 if (!lp_ms_add_printer_wizard()) {
1598 close_printer_handle(p, handle);
1599 return WERR_ACCESS_DENIED;
1602 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1603 and not a printer admin, then fail */
1605 if ((p->pipe_user.ut.uid != 0) &&
1606 !user_has_privileges(p->pipe_user.nt_user_token,
1608 !token_contains_name_in_list(
1609 uidtoname(p->pipe_user.ut.uid), NULL,
1610 p->pipe_user.nt_user_token,
1611 lp_printer_admin(snum))) {
1612 close_printer_handle(p, handle);
1613 return WERR_ACCESS_DENIED;
1616 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1620 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1623 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1624 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1626 /* We fall through to return WERR_OK */
1629 case SPLHND_PRINTER:
1630 /* NT doesn't let us connect to a printer if the connecting user
1631 doesn't have print permission. */
1633 if (!get_printer_snum(p, handle, &snum)) {
1634 close_printer_handle(p, handle);
1638 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1640 /* map an empty access mask to the minimum access mask */
1641 if (printer_default->access_required == 0x0)
1642 printer_default->access_required = PRINTER_ACCESS_USE;
1645 * If we are not serving the printer driver for this printer,
1646 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1647 * will keep NT clients happy --jerry
1650 if (lp_use_client_driver(snum)
1651 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1653 printer_default->access_required = PRINTER_ACCESS_USE;
1656 /* check smb.conf parameters and the the sec_desc */
1658 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1659 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1660 return WERR_ACCESS_DENIED;
1663 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1664 p->pipe_user.nt_user_token, snum) ||
1665 !print_access_check(&p->pipe_user, snum,
1666 printer_default->access_required)) {
1667 DEBUG(3, ("access DENIED for printer open\n"));
1668 close_printer_handle(p, handle);
1669 return WERR_ACCESS_DENIED;
1672 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1673 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1674 close_printer_handle(p, handle);
1675 return WERR_ACCESS_DENIED;
1678 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1679 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1681 printer_default->access_required = PRINTER_ACCESS_USE;
1683 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1684 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1689 /* sanity check to prevent programmer error */
1693 Printer->access_granted = printer_default->access_required;
1696 * If the client sent a devmode in the OpenPrinter() call, then
1697 * save it here in case we get a job submission on this handle
1700 if ( (Printer->printer_type != SPLHND_SERVER)
1701 && q_u->printer_default.devmode_cont.devmode_ptr )
1703 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1704 &Printer->nt_devmode );
1707 #if 0 /* JERRY -- I'm doubtful this is really effective */
1708 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1709 optimization in Windows 2000 clients --jerry */
1711 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1712 && (RA_WIN2K == get_remote_arch()) )
1714 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1715 sys_usleep( 500000 );
1722 /****************************************************************************
1723 ****************************************************************************/
1725 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1726 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1732 /* allocate memory if needed. Messy because
1733 convert_printer_info is used to update an existing
1734 printer or build a new one */
1736 if ( !printer->info_2 ) {
1737 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1738 if ( !printer->info_2 ) {
1739 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1744 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1745 printer->info_2->setuptime = time(NULL);
1753 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1754 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1760 printer->info_3=NULL;
1761 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1765 printer->info_6=NULL;
1766 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1776 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1777 NT_DEVICEMODE **pp_nt_devmode)
1779 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1782 * Ensure nt_devmode is a valid pointer
1783 * as we will be overwriting it.
1786 if (nt_devmode == NULL) {
1787 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1788 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1792 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1793 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1795 nt_devmode->specversion=devmode->specversion;
1796 nt_devmode->driverversion=devmode->driverversion;
1797 nt_devmode->size=devmode->size;
1798 nt_devmode->fields=devmode->fields;
1799 nt_devmode->orientation=devmode->orientation;
1800 nt_devmode->papersize=devmode->papersize;
1801 nt_devmode->paperlength=devmode->paperlength;
1802 nt_devmode->paperwidth=devmode->paperwidth;
1803 nt_devmode->scale=devmode->scale;
1804 nt_devmode->copies=devmode->copies;
1805 nt_devmode->defaultsource=devmode->defaultsource;
1806 nt_devmode->printquality=devmode->printquality;
1807 nt_devmode->color=devmode->color;
1808 nt_devmode->duplex=devmode->duplex;
1809 nt_devmode->yresolution=devmode->yresolution;
1810 nt_devmode->ttoption=devmode->ttoption;
1811 nt_devmode->collate=devmode->collate;
1813 nt_devmode->logpixels=devmode->logpixels;
1814 nt_devmode->bitsperpel=devmode->bitsperpel;
1815 nt_devmode->pelswidth=devmode->pelswidth;
1816 nt_devmode->pelsheight=devmode->pelsheight;
1817 nt_devmode->displayflags=devmode->displayflags;
1818 nt_devmode->displayfrequency=devmode->displayfrequency;
1819 nt_devmode->icmmethod=devmode->icmmethod;
1820 nt_devmode->icmintent=devmode->icmintent;
1821 nt_devmode->mediatype=devmode->mediatype;
1822 nt_devmode->dithertype=devmode->dithertype;
1823 nt_devmode->reserved1=devmode->reserved1;
1824 nt_devmode->reserved2=devmode->reserved2;
1825 nt_devmode->panningwidth=devmode->panningwidth;
1826 nt_devmode->panningheight=devmode->panningheight;
1829 * Only change private and driverextra if the incoming devmode
1830 * has a new one. JRA.
1833 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1834 SAFE_FREE(nt_devmode->nt_dev_private);
1835 nt_devmode->driverextra=devmode->driverextra;
1836 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1838 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1841 *pp_nt_devmode = nt_devmode;
1846 /********************************************************************
1847 * _spoolss_enddocprinter_internal.
1848 ********************************************************************/
1850 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1852 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1856 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1860 if (!get_printer_snum(p, handle, &snum))
1863 Printer->document_started=False;
1864 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1865 /* error codes unhandled so far ... */
1870 /********************************************************************
1871 * api_spoolss_closeprinter
1872 ********************************************************************/
1874 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1876 POLICY_HND *handle = &q_u->handle;
1878 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1880 if (Printer && Printer->document_started)
1881 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1883 if (!close_printer_handle(p, handle))
1886 /* clear the returned printer handle. Observed behavior
1887 from Win2k server. Don't think this really matters.
1888 Previous code just copied the value of the closed
1891 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1896 /********************************************************************
1897 * api_spoolss_deleteprinter
1899 ********************************************************************/
1901 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1903 POLICY_HND *handle = &q_u->handle;
1904 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1907 if (Printer && Printer->document_started)
1908 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1910 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1912 result = delete_printer_handle(p, handle);
1914 update_c_setprinter(False);
1919 /*******************************************************************
1920 * static function to lookup the version id corresponding to an
1921 * long architecture string
1922 ******************************************************************/
1924 static int get_version_id (char * arch)
1927 struct table_node archi_table[]= {
1929 {"Windows 4.0", "WIN40", 0 },
1930 {"Windows NT x86", "W32X86", 2 },
1931 {"Windows NT R4000", "W32MIPS", 2 },
1932 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1933 {"Windows NT PowerPC", "W32PPC", 2 },
1934 {"Windows IA64", "IA64", 3 },
1935 {"Windows x64", "x64", 3 },
1939 for (i=0; archi_table[i].long_archi != NULL; i++)
1941 if (strcmp(arch, archi_table[i].long_archi) == 0)
1942 return (archi_table[i].version);
1948 /********************************************************************
1949 * _spoolss_deleteprinterdriver
1950 ********************************************************************/
1952 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1956 NT_PRINTER_DRIVER_INFO_LEVEL info;
1957 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1960 WERROR status_win2k = WERR_ACCESS_DENIED;
1961 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1963 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1964 and not a printer admin, then fail */
1966 if ( (p->pipe_user.ut.uid != 0)
1967 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1968 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1969 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1971 return WERR_ACCESS_DENIED;
1974 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1975 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1977 /* check that we have a valid driver name first */
1979 if ((version=get_version_id(arch)) == -1)
1980 return WERR_INVALID_ENVIRONMENT;
1983 ZERO_STRUCT(info_win2k);
1985 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1987 /* try for Win2k driver if "Windows NT x86" */
1989 if ( version == 2 ) {
1991 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1992 status = WERR_UNKNOWN_PRINTER_DRIVER;
1996 /* otherwise it was a failure */
1998 status = WERR_UNKNOWN_PRINTER_DRIVER;
2004 if (printer_driver_in_use(info.info_3)) {
2005 status = WERR_PRINTER_DRIVER_IN_USE;
2011 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2013 /* if we get to here, we now have 2 driver info structures to remove */
2014 /* remove the Win2k driver first*/
2016 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2017 free_a_printer_driver( info_win2k, 3 );
2019 /* this should not have failed---if it did, report to client */
2020 if ( !W_ERROR_IS_OK(status_win2k) )
2022 status = status_win2k;
2028 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2030 /* if at least one of the deletes succeeded return OK */
2032 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2036 free_a_printer_driver( info, 3 );
2041 /********************************************************************
2042 * spoolss_deleteprinterdriverex
2043 ********************************************************************/
2045 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2049 NT_PRINTER_DRIVER_INFO_LEVEL info;
2050 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2052 uint32 flags = q_u->delete_flags;
2055 WERROR status_win2k = WERR_ACCESS_DENIED;
2056 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2058 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2059 and not a printer admin, then fail */
2061 if ( (p->pipe_user.ut.uid != 0)
2062 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2063 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2064 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2066 return WERR_ACCESS_DENIED;
2069 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2070 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2072 /* check that we have a valid driver name first */
2073 if ((version=get_version_id(arch)) == -1) {
2074 /* this is what NT returns */
2075 return WERR_INVALID_ENVIRONMENT;
2078 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2079 version = q_u->version;
2082 ZERO_STRUCT(info_win2k);
2084 status = get_a_printer_driver(&info, 3, driver, arch, version);
2086 if ( !W_ERROR_IS_OK(status) )
2089 * if the client asked for a specific version,
2090 * or this is something other than Windows NT x86,
2094 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2097 /* try for Win2k driver if "Windows NT x86" */
2100 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2101 status = WERR_UNKNOWN_PRINTER_DRIVER;
2106 if ( printer_driver_in_use(info.info_3) ) {
2107 status = WERR_PRINTER_DRIVER_IN_USE;
2112 * we have a couple of cases to consider.
2113 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2114 * then the delete should fail if **any** files overlap with
2116 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2117 * non-overlapping files
2118 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2119 * is set, the do not delete any files
2120 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2123 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2125 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2127 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2128 /* no idea of the correct error here */
2129 status = WERR_ACCESS_DENIED;
2134 /* also check for W32X86/3 if necessary; maybe we already have? */
2136 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2137 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2140 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2141 /* no idea of the correct error here */
2142 free_a_printer_driver( info_win2k, 3 );
2143 status = WERR_ACCESS_DENIED;
2147 /* if we get to here, we now have 2 driver info structures to remove */
2148 /* remove the Win2k driver first*/
2150 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2151 free_a_printer_driver( info_win2k, 3 );
2153 /* this should not have failed---if it did, report to client */
2155 if ( !W_ERROR_IS_OK(status_win2k) )
2160 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2162 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2165 free_a_printer_driver( info, 3 );
2171 /****************************************************************************
2172 Internal routine for retreiving printerdata
2173 ***************************************************************************/
2175 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2176 const char *key, const char *value, uint32 *type, uint8 **data,
2177 uint32 *needed, uint32 in_size )
2179 REGISTRY_VALUE *val;
2183 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2184 return WERR_BADFILE;
2186 *type = regval_type( val );
2188 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2190 size = regval_size( val );
2192 /* copy the min(in_size, len) */
2195 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2197 /* special case for 0 length values */
2199 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2203 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2212 DEBUG(5,("get_printer_dataex: copy done\n"));
2217 /****************************************************************************
2218 Internal routine for removing printerdata
2219 ***************************************************************************/
2221 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2223 return delete_printer_data( printer->info_2, key, value );
2226 /****************************************************************************
2227 Internal routine for storing printerdata
2228 ***************************************************************************/
2230 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2231 uint32 type, uint8 *data, int real_len )
2233 /* the registry objects enforce uniqueness based on value name */
2235 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2238 /********************************************************************
2239 GetPrinterData on a printer server Handle.
2240 ********************************************************************/
2242 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2246 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2248 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2250 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2256 if (!StrCaseCmp(value, "BeepEnabled")) {
2258 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2260 SIVAL(*data, 0, 0x00);
2265 if (!StrCaseCmp(value, "EventLog")) {
2267 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2269 /* formally was 0x1b */
2270 SIVAL(*data, 0, 0x0);
2275 if (!StrCaseCmp(value, "NetPopup")) {
2277 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2279 SIVAL(*data, 0, 0x00);
2284 if (!StrCaseCmp(value, "MajorVersion")) {
2286 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2289 /* Windows NT 4.0 seems to not allow uploading of drivers
2290 to a server that reports 0x3 as the MajorVersion.
2291 need to investigate more how Win2k gets around this .
2294 if ( RA_WINNT == get_remote_arch() )
2303 if (!StrCaseCmp(value, "MinorVersion")) {
2305 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2313 * uint32 size = 0x114
2315 * uint32 minor = [0|1]
2316 * uint32 build = [2195|2600]
2317 * extra unicode string = e.g. "Service Pack 3"
2319 if (!StrCaseCmp(value, "OSVersion")) {
2323 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2326 SIVAL(*data, 0, *needed); /* size */
2327 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2329 SIVAL(*data, 12, 2195); /* build */
2331 /* leave extra string empty */
2337 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2338 const char *string="C:\\PRINTERS";
2340 *needed = 2*(strlen(string)+1);
2341 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2343 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2345 /* it's done by hand ready to go on the wire */
2346 for (i=0; i<strlen(string); i++) {
2347 (*data)[2*i]=string[i];
2348 (*data)[2*i+1]='\0';
2353 if (!StrCaseCmp(value, "Architecture")) {
2354 const char *string="Windows NT x86";
2356 *needed = 2*(strlen(string)+1);
2357 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2359 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2360 for (i=0; i<strlen(string); i++) {
2361 (*data)[2*i]=string[i];
2362 (*data)[2*i+1]='\0';
2367 if (!StrCaseCmp(value, "DsPresent")) {
2369 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2372 /* only show the publish check box if we are a
2373 memeber of a AD domain */
2375 if ( lp_security() == SEC_ADS )
2376 SIVAL(*data, 0, 0x01);
2378 SIVAL(*data, 0, 0x00);
2384 if (!StrCaseCmp(value, "DNSMachineName")) {
2387 if (!get_mydnsfullname(hostname))
2388 return WERR_BADFILE;
2390 *needed = 2*(strlen(hostname)+1);
2391 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2393 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2394 for (i=0; i<strlen(hostname); i++) {
2395 (*data)[2*i]=hostname[i];
2396 (*data)[2*i+1]='\0';
2402 return WERR_BADFILE;
2405 /********************************************************************
2406 * spoolss_getprinterdata
2407 ********************************************************************/
2409 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2411 POLICY_HND *handle = &q_u->handle;
2412 UNISTR2 *valuename = &q_u->valuename;
2413 uint32 in_size = q_u->size;
2414 uint32 *type = &r_u->type;
2415 uint32 *out_size = &r_u->size;
2416 uint8 **data = &r_u->data;
2417 uint32 *needed = &r_u->needed;
2420 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2421 NT_PRINTER_INFO_LEVEL *printer = NULL;
2425 * Reminder: when it's a string, the length is in BYTES
2426 * even if UNICODE is negociated.
2431 *out_size = in_size;
2433 /* in case of problem, return some default values */
2438 DEBUG(4,("_spoolss_getprinterdata\n"));
2441 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2442 status = WERR_BADFID;
2446 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2448 if ( Printer->printer_type == SPLHND_SERVER )
2449 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2452 if ( !get_printer_snum(p,handle, &snum) ) {
2453 status = WERR_BADFID;
2457 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2458 if ( !W_ERROR_IS_OK(status) )
2461 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2463 if ( strequal(value, "ChangeId") ) {
2465 *needed = sizeof(uint32);
2466 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2467 status = WERR_NOMEM;
2470 SIVAL( *data, 0, printer->info_2->changeid );
2474 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2477 if (*needed > *out_size)
2478 status = WERR_MORE_DATA;
2481 if ( !W_ERROR_IS_OK(status) )
2483 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2485 /* reply this param doesn't exist */
2488 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2490 free_a_printer( &printer, 2 );
2499 /* cleanup & exit */
2502 free_a_printer( &printer, 2 );
2507 /*********************************************************
2508 Connect to the client machine.
2509 **********************************************************/
2511 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2512 struct in_addr *client_ip, const char *remote_machine)
2515 struct cli_state *the_cli;
2516 struct in_addr rm_addr;
2518 if ( is_zero_ip(*client_ip) ) {
2519 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2520 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2524 if ( ismyip( rm_addr )) {
2525 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2529 rm_addr.s_addr = client_ip->s_addr;
2530 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2531 inet_ntoa(*client_ip) ));
2534 /* setup the connection */
2536 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2537 &rm_addr, 0, "IPC$", "IPC",
2541 0, lp_client_signing(), NULL );
2543 if ( !NT_STATUS_IS_OK( ret ) ) {
2544 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2549 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2550 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2551 cli_shutdown(the_cli);
2556 * Ok - we have an anonymous connection to the IPC$ share.
2557 * Now start the NT Domain stuff :-).
2560 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2561 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2562 remote_machine, nt_errstr(ret)));
2563 cli_shutdown(the_cli);
2567 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2569 (*pp_pipe)->cli = the_cli;
2574 /***************************************************************************
2575 Connect to the client.
2576 ****************************************************************************/
2578 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2579 uint32 localprinter, uint32 type,
2580 POLICY_HND *handle, struct in_addr *client_ip)
2585 * If it's the first connection, contact the client
2586 * and connect to the IPC$ share anonymously
2588 if (smb_connections==0) {
2589 fstring unix_printer;
2591 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2593 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2596 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2597 /* Tell the connections db we're now interested in printer
2598 * notify messages. */
2599 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2603 * Tell the specific printing tdb we want messages for this printer
2604 * by registering our PID.
2607 if (!print_notify_register_pid(snum))
2608 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2612 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2615 if (!W_ERROR_IS_OK(result))
2616 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2617 dos_errstr(result)));
2619 return (W_ERROR_IS_OK(result));
2622 /********************************************************************
2624 * ReplyFindFirstPrinterChangeNotifyEx
2626 * before replying OK: status=0 a rpc call is made to the workstation
2627 * asking ReplyOpenPrinter
2629 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2630 * called from api_spoolss_rffpcnex
2631 ********************************************************************/
2633 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2635 POLICY_HND *handle = &q_u->handle;
2636 uint32 flags = q_u->flags;
2637 uint32 options = q_u->options;
2638 UNISTR2 *localmachine = &q_u->localmachine;
2639 uint32 printerlocal = q_u->printerlocal;
2641 SPOOL_NOTIFY_OPTION *option = q_u->option;
2642 struct in_addr client_ip;
2644 /* store the notify value in the printer struct */
2646 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2649 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2653 Printer->notify.flags=flags;
2654 Printer->notify.options=options;
2655 Printer->notify.printerlocal=printerlocal;
2657 if (Printer->notify.option)
2658 free_spool_notify_option(&Printer->notify.option);
2660 Printer->notify.option=dup_spool_notify_option(option);
2662 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2663 sizeof(Printer->notify.localmachine)-1);
2665 /* Connect to the client machine and send a ReplyOpenPrinter */
2667 if ( Printer->printer_type == SPLHND_SERVER)
2669 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2670 !get_printer_snum(p, handle, &snum) )
2673 client_ip.s_addr = inet_addr(p->conn->client_address);
2675 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2676 Printer->notify.printerlocal, 1,
2677 &Printer->notify.client_hnd, &client_ip))
2678 return WERR_SERVER_UNAVAILABLE;
2680 Printer->notify.client_connected=True;
2685 /*******************************************************************
2686 * fill a notify_info_data with the servername
2687 ********************************************************************/
2689 void spoolss_notify_server_name(int snum,
2690 SPOOL_NOTIFY_INFO_DATA *data,
2691 print_queue_struct *queue,
2692 NT_PRINTER_INFO_LEVEL *printer,
2693 TALLOC_CTX *mem_ctx)
2698 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2700 data->notify_data.data.length = len;
2701 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2703 if (!data->notify_data.data.string) {
2704 data->notify_data.data.length = 0;
2708 memcpy(data->notify_data.data.string, temp, len);
2711 /*******************************************************************
2712 * fill a notify_info_data with the printername (not including the servername).
2713 ********************************************************************/
2715 void spoolss_notify_printer_name(int snum,
2716 SPOOL_NOTIFY_INFO_DATA *data,
2717 print_queue_struct *queue,
2718 NT_PRINTER_INFO_LEVEL *printer,
2719 TALLOC_CTX *mem_ctx)
2724 /* the notify name should not contain the \\server\ part */
2725 char *p = strrchr(printer->info_2->printername, '\\');
2728 p = printer->info_2->printername;
2733 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2735 data->notify_data.data.length = len;
2736 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2738 if (!data->notify_data.data.string) {
2739 data->notify_data.data.length = 0;
2743 memcpy(data->notify_data.data.string, temp, len);
2746 /*******************************************************************
2747 * fill a notify_info_data with the servicename
2748 ********************************************************************/
2750 void spoolss_notify_share_name(int snum,
2751 SPOOL_NOTIFY_INFO_DATA *data,
2752 print_queue_struct *queue,
2753 NT_PRINTER_INFO_LEVEL *printer,
2754 TALLOC_CTX *mem_ctx)
2759 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2761 data->notify_data.data.length = len;
2762 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2764 if (!data->notify_data.data.string) {
2765 data->notify_data.data.length = 0;
2769 memcpy(data->notify_data.data.string, temp, len);
2772 /*******************************************************************
2773 * fill a notify_info_data with the port name
2774 ********************************************************************/
2776 void spoolss_notify_port_name(int snum,
2777 SPOOL_NOTIFY_INFO_DATA *data,
2778 print_queue_struct *queue,
2779 NT_PRINTER_INFO_LEVEL *printer,
2780 TALLOC_CTX *mem_ctx)
2785 /* even if it's strange, that's consistant in all the code */
2787 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2789 data->notify_data.data.length = len;
2790 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2792 if (!data->notify_data.data.string) {
2793 data->notify_data.data.length = 0;
2797 memcpy(data->notify_data.data.string, temp, len);
2800 /*******************************************************************
2801 * fill a notify_info_data with the printername
2802 * but it doesn't exist, have to see what to do
2803 ********************************************************************/
2805 void spoolss_notify_driver_name(int snum,
2806 SPOOL_NOTIFY_INFO_DATA *data,
2807 print_queue_struct *queue,
2808 NT_PRINTER_INFO_LEVEL *printer,
2809 TALLOC_CTX *mem_ctx)
2814 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2816 data->notify_data.data.length = len;
2817 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2819 if (!data->notify_data.data.string) {
2820 data->notify_data.data.length = 0;
2824 memcpy(data->notify_data.data.string, temp, len);
2827 /*******************************************************************
2828 * fill a notify_info_data with the comment
2829 ********************************************************************/
2831 void spoolss_notify_comment(int snum,
2832 SPOOL_NOTIFY_INFO_DATA *data,
2833 print_queue_struct *queue,
2834 NT_PRINTER_INFO_LEVEL *printer,
2835 TALLOC_CTX *mem_ctx)
2840 if (*printer->info_2->comment == '\0')
2841 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2843 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2845 data->notify_data.data.length = len;
2846 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2848 if (!data->notify_data.data.string) {
2849 data->notify_data.data.length = 0;
2853 memcpy(data->notify_data.data.string, temp, len);
2856 /*******************************************************************
2857 * fill a notify_info_data with the comment
2858 * location = "Room 1, floor 2, building 3"
2859 ********************************************************************/
2861 void spoolss_notify_location(int snum,
2862 SPOOL_NOTIFY_INFO_DATA *data,
2863 print_queue_struct *queue,
2864 NT_PRINTER_INFO_LEVEL *printer,
2865 TALLOC_CTX *mem_ctx)
2870 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2872 data->notify_data.data.length = len;
2873 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2875 if (!data->notify_data.data.string) {
2876 data->notify_data.data.length = 0;
2880 memcpy(data->notify_data.data.string, temp, len);
2883 /*******************************************************************
2884 * fill a notify_info_data with the device mode
2885 * jfm:xxxx don't to it for know but that's a real problem !!!
2886 ********************************************************************/
2888 static void spoolss_notify_devmode(int snum,
2889 SPOOL_NOTIFY_INFO_DATA *data,
2890 print_queue_struct *queue,
2891 NT_PRINTER_INFO_LEVEL *printer,
2892 TALLOC_CTX *mem_ctx)
2896 /*******************************************************************
2897 * fill a notify_info_data with the separator file name
2898 ********************************************************************/
2900 void spoolss_notify_sepfile(int snum,
2901 SPOOL_NOTIFY_INFO_DATA *data,
2902 print_queue_struct *queue,
2903 NT_PRINTER_INFO_LEVEL *printer,
2904 TALLOC_CTX *mem_ctx)
2909 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2911 data->notify_data.data.length = len;
2912 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2914 if (!data->notify_data.data.string) {
2915 data->notify_data.data.length = 0;
2919 memcpy(data->notify_data.data.string, temp, len);
2922 /*******************************************************************
2923 * fill a notify_info_data with the print processor
2924 * jfm:xxxx return always winprint to indicate we don't do anything to it
2925 ********************************************************************/
2927 void spoolss_notify_print_processor(int snum,
2928 SPOOL_NOTIFY_INFO_DATA *data,
2929 print_queue_struct *queue,
2930 NT_PRINTER_INFO_LEVEL *printer,
2931 TALLOC_CTX *mem_ctx)
2936 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2938 data->notify_data.data.length = len;
2939 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2941 if (!data->notify_data.data.string) {
2942 data->notify_data.data.length = 0;
2946 memcpy(data->notify_data.data.string, temp, len);
2949 /*******************************************************************
2950 * fill a notify_info_data with the print processor options
2951 * jfm:xxxx send an empty string
2952 ********************************************************************/
2954 void spoolss_notify_parameters(int snum,
2955 SPOOL_NOTIFY_INFO_DATA *data,
2956 print_queue_struct *queue,
2957 NT_PRINTER_INFO_LEVEL *printer,
2958 TALLOC_CTX *mem_ctx)
2963 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2965 data->notify_data.data.length = len;
2966 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2968 if (!data->notify_data.data.string) {
2969 data->notify_data.data.length = 0;
2973 memcpy(data->notify_data.data.string, temp, len);
2976 /*******************************************************************
2977 * fill a notify_info_data with the data type
2978 * jfm:xxxx always send RAW as data type
2979 ********************************************************************/
2981 void spoolss_notify_datatype(int snum,
2982 SPOOL_NOTIFY_INFO_DATA *data,
2983 print_queue_struct *queue,
2984 NT_PRINTER_INFO_LEVEL *printer,
2985 TALLOC_CTX *mem_ctx)
2990 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2992 data->notify_data.data.length = len;
2993 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2995 if (!data->notify_data.data.string) {
2996 data->notify_data.data.length = 0;
3000 memcpy(data->notify_data.data.string, temp, len);
3003 /*******************************************************************
3004 * fill a notify_info_data with the security descriptor
3005 * jfm:xxxx send an null pointer to say no security desc
3006 * have to implement security before !
3007 ********************************************************************/
3009 static void spoolss_notify_security_desc(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 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3016 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3019 /*******************************************************************
3020 * fill a notify_info_data with the attributes
3021 * jfm:xxxx a samba printer is always shared
3022 ********************************************************************/
3024 void spoolss_notify_attributes(int snum,
3025 SPOOL_NOTIFY_INFO_DATA *data,
3026 print_queue_struct *queue,
3027 NT_PRINTER_INFO_LEVEL *printer,
3028 TALLOC_CTX *mem_ctx)
3030 data->notify_data.value[0] = printer->info_2->attributes;
3031 data->notify_data.value[1] = 0;
3034 /*******************************************************************
3035 * fill a notify_info_data with the priority
3036 ********************************************************************/
3038 static void spoolss_notify_priority(int snum,
3039 SPOOL_NOTIFY_INFO_DATA *data,
3040 print_queue_struct *queue,
3041 NT_PRINTER_INFO_LEVEL *printer,
3042 TALLOC_CTX *mem_ctx)
3044 data->notify_data.value[0] = printer->info_2->priority;
3045 data->notify_data.value[1] = 0;
3048 /*******************************************************************
3049 * fill a notify_info_data with the default priority
3050 ********************************************************************/
3052 static void spoolss_notify_default_priority(int snum,
3053 SPOOL_NOTIFY_INFO_DATA *data,
3054 print_queue_struct *queue,
3055 NT_PRINTER_INFO_LEVEL *printer,
3056 TALLOC_CTX *mem_ctx)
3058 data->notify_data.value[0] = printer->info_2->default_priority;
3059 data->notify_data.value[1] = 0;
3062 /*******************************************************************
3063 * fill a notify_info_data with the start time
3064 ********************************************************************/
3066 static void spoolss_notify_start_time(int snum,
3067 SPOOL_NOTIFY_INFO_DATA *data,
3068 print_queue_struct *queue,
3069 NT_PRINTER_INFO_LEVEL *printer,
3070 TALLOC_CTX *mem_ctx)
3072 data->notify_data.value[0] = printer->info_2->starttime;
3073 data->notify_data.value[1] = 0;
3076 /*******************************************************************
3077 * fill a notify_info_data with the until time
3078 ********************************************************************/
3080 static void spoolss_notify_until_time(int snum,
3081 SPOOL_NOTIFY_INFO_DATA *data,
3082 print_queue_struct *queue,
3083 NT_PRINTER_INFO_LEVEL *printer,
3084 TALLOC_CTX *mem_ctx)
3086 data->notify_data.value[0] = printer->info_2->untiltime;
3087 data->notify_data.value[1] = 0;
3090 /*******************************************************************
3091 * fill a notify_info_data with the status
3092 ********************************************************************/
3094 static void spoolss_notify_status(int snum,
3095 SPOOL_NOTIFY_INFO_DATA *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 print_status_struct status;
3102 print_queue_length(snum, &status);
3103 data->notify_data.value[0]=(uint32) status.status;
3104 data->notify_data.value[1] = 0;
3107 /*******************************************************************
3108 * fill a notify_info_data with the number of jobs queued
3109 ********************************************************************/
3111 void spoolss_notify_cjobs(int snum,
3112 SPOOL_NOTIFY_INFO_DATA *data,
3113 print_queue_struct *queue,
3114 NT_PRINTER_INFO_LEVEL *printer,
3115 TALLOC_CTX *mem_ctx)
3117 data->notify_data.value[0] = print_queue_length(snum, NULL);
3118 data->notify_data.value[1] = 0;
3121 /*******************************************************************
3122 * fill a notify_info_data with the average ppm
3123 ********************************************************************/
3125 static void spoolss_notify_average_ppm(int snum,
3126 SPOOL_NOTIFY_INFO_DATA *data,
3127 print_queue_struct *queue,
3128 NT_PRINTER_INFO_LEVEL *printer,
3129 TALLOC_CTX *mem_ctx)
3131 /* always respond 8 pages per minutes */
3132 /* a little hard ! */
3133 data->notify_data.value[0] = printer->info_2->averageppm;
3134 data->notify_data.value[1] = 0;
3137 /*******************************************************************
3138 * fill a notify_info_data with username
3139 ********************************************************************/
3141 static void spoolss_notify_username(int snum,
3142 SPOOL_NOTIFY_INFO_DATA *data,
3143 print_queue_struct *queue,
3144 NT_PRINTER_INFO_LEVEL *printer,
3145 TALLOC_CTX *mem_ctx)
3150 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3152 data->notify_data.data.length = len;
3153 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3155 if (!data->notify_data.data.string) {
3156 data->notify_data.data.length = 0;
3160 memcpy(data->notify_data.data.string, temp, len);
3163 /*******************************************************************
3164 * fill a notify_info_data with job status
3165 ********************************************************************/
3167 static void spoolss_notify_job_status(int snum,
3168 SPOOL_NOTIFY_INFO_DATA *data,
3169 print_queue_struct *queue,
3170 NT_PRINTER_INFO_LEVEL *printer,
3171 TALLOC_CTX *mem_ctx)
3173 data->notify_data.value[0]=nt_printj_status(queue->status);
3174 data->notify_data.value[1] = 0;
3177 /*******************************************************************
3178 * fill a notify_info_data with job name
3179 ********************************************************************/
3181 static void spoolss_notify_job_name(int snum,
3182 SPOOL_NOTIFY_INFO_DATA *data,
3183 print_queue_struct *queue,
3184 NT_PRINTER_INFO_LEVEL *printer,
3185 TALLOC_CTX *mem_ctx)
3190 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3192 data->notify_data.data.length = len;
3193 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3195 if (!data->notify_data.data.string) {
3196 data->notify_data.data.length = 0;
3200 memcpy(data->notify_data.data.string, temp, len);
3203 /*******************************************************************
3204 * fill a notify_info_data with job status
3205 ********************************************************************/
3207 static void spoolss_notify_job_status_string(int snum,
3208 SPOOL_NOTIFY_INFO_DATA *data,
3209 print_queue_struct *queue,
3210 NT_PRINTER_INFO_LEVEL *printer,
3211 TALLOC_CTX *mem_ctx)
3214 * Now we're returning job status codes we just return a "" here. JRA.
3221 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3224 switch (queue->status) {
3229 p = ""; /* NT provides the paused string */
3238 #endif /* NO LONGER NEEDED. */
3240 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3242 data->notify_data.data.length = len;
3243 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3245 if (!data->notify_data.data.string) {
3246 data->notify_data.data.length = 0;
3250 memcpy(data->notify_data.data.string, temp, len);
3253 /*******************************************************************
3254 * fill a notify_info_data with job time
3255 ********************************************************************/
3257 static void spoolss_notify_job_time(int snum,
3258 SPOOL_NOTIFY_INFO_DATA *data,
3259 print_queue_struct *queue,
3260 NT_PRINTER_INFO_LEVEL *printer,
3261 TALLOC_CTX *mem_ctx)
3263 data->notify_data.value[0]=0x0;
3264 data->notify_data.value[1]=0;
3267 /*******************************************************************
3268 * fill a notify_info_data with job size
3269 ********************************************************************/
3271 static void spoolss_notify_job_size(int snum,
3272 SPOOL_NOTIFY_INFO_DATA *data,
3273 print_queue_struct *queue,
3274 NT_PRINTER_INFO_LEVEL *printer,
3275 TALLOC_CTX *mem_ctx)
3277 data->notify_data.value[0]=queue->size;
3278 data->notify_data.value[1]=0;
3281 /*******************************************************************
3282 * fill a notify_info_data with page info
3283 ********************************************************************/
3284 static void spoolss_notify_total_pages(int snum,
3285 SPOOL_NOTIFY_INFO_DATA *data,
3286 print_queue_struct *queue,
3287 NT_PRINTER_INFO_LEVEL *printer,
3288 TALLOC_CTX *mem_ctx)
3290 data->notify_data.value[0]=queue->page_count;
3291 data->notify_data.value[1]=0;
3294 /*******************************************************************
3295 * fill a notify_info_data with pages printed info.
3296 ********************************************************************/
3297 static void spoolss_notify_pages_printed(int snum,
3298 SPOOL_NOTIFY_INFO_DATA *data,
3299 print_queue_struct *queue,
3300 NT_PRINTER_INFO_LEVEL *printer,
3301 TALLOC_CTX *mem_ctx)
3303 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3304 data->notify_data.value[1]=0;
3307 /*******************************************************************
3308 Fill a notify_info_data with job position.
3309 ********************************************************************/
3311 static void spoolss_notify_job_position(int snum,
3312 SPOOL_NOTIFY_INFO_DATA *data,
3313 print_queue_struct *queue,
3314 NT_PRINTER_INFO_LEVEL *printer,
3315 TALLOC_CTX *mem_ctx)
3317 data->notify_data.value[0]=queue->job;
3318 data->notify_data.value[1]=0;
3321 /*******************************************************************
3322 Fill a notify_info_data with submitted time.
3323 ********************************************************************/
3325 static void spoolss_notify_submitted_time(int snum,
3326 SPOOL_NOTIFY_INFO_DATA *data,
3327 print_queue_struct *queue,
3328 NT_PRINTER_INFO_LEVEL *printer,
3329 TALLOC_CTX *mem_ctx)
3336 t=gmtime(&queue->time);
3338 len = sizeof(SYSTEMTIME);
3340 data->notify_data.data.length = len;
3341 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3343 if (!data->notify_data.data.string) {
3344 data->notify_data.data.length = 0;
3348 make_systemtime(&st, t);
3351 * Systemtime must be linearized as a set of UINT16's.
3352 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3355 p = (char *)data->notify_data.data.string;
3356 SSVAL(p, 0, st.year);
3357 SSVAL(p, 2, st.month);
3358 SSVAL(p, 4, st.dayofweek);
3359 SSVAL(p, 6, st.day);
3360 SSVAL(p, 8, st.hour);
3361 SSVAL(p, 10, st.minute);
3362 SSVAL(p, 12, st.second);
3363 SSVAL(p, 14, st.milliseconds);
3366 struct s_notify_info_data_table
3372 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3373 print_queue_struct *queue,
3374 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3377 /* A table describing the various print notification constants and
3378 whether the notification data is a pointer to a variable sized
3379 buffer, a one value uint32 or a two value uint32. */
3381 static const struct s_notify_info_data_table notify_info_data_table[] =
3383 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3409 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3410 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3411 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3432 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3435 /*******************************************************************
3436 Return the size of info_data structure.
3437 ********************************************************************/
3439 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3443 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3444 if ( (notify_info_data_table[i].type == type)
3445 && (notify_info_data_table[i].field == field) ) {
3446 switch(notify_info_data_table[i].size) {
3447 case NOTIFY_ONE_VALUE:
3448 case NOTIFY_TWO_VALUE:
3453 /* The only pointer notify data I have seen on
3454 the wire is the submitted time and this has
3455 the notify size set to 4. -tpot */
3457 case NOTIFY_POINTER:
3460 case NOTIFY_SECDESC:
3466 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3471 /*******************************************************************
3472 Return the type of notify_info_data.
3473 ********************************************************************/
3475 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3479 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3480 if (notify_info_data_table[i].type == type &&
3481 notify_info_data_table[i].field == field)
3482 return notify_info_data_table[i].size;
3488 /****************************************************************************
3489 ****************************************************************************/
3491 static BOOL search_notify(uint16 type, uint16 field, int *value)
3495 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3496 if (notify_info_data_table[i].type == type &&
3497 notify_info_data_table[i].field == field &&
3498 notify_info_data_table[i].fn != NULL) {
3507 /****************************************************************************
3508 ****************************************************************************/
3510 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3512 info_data->type = type;
3513 info_data->field = field;
3514 info_data->reserved = 0;
3516 info_data->size = size_of_notify_info_data(type, field);
3517 info_data->enc_type = type_of_notify_info_data(type, field);
3522 /*******************************************************************
3524 * fill a notify_info struct with info asked
3526 ********************************************************************/
3528 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3529 snum, SPOOL_NOTIFY_OPTION_TYPE
3530 *option_type, uint32 id,
3531 TALLOC_CTX *mem_ctx)
3537 SPOOL_NOTIFY_INFO_DATA *current_data;
3538 NT_PRINTER_INFO_LEVEL *printer = NULL;
3539 print_queue_struct *queue=NULL;
3541 type=option_type->type;
3543 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3544 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3545 option_type->count, lp_servicename(snum)));
3547 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3550 for(field_num=0; field_num<option_type->count; field_num++) {
3551 field = option_type->fields[field_num];
3553 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3555 if (!search_notify(type, field, &j) )
3558 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3559 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3560 free_a_printer(&printer, 2);
3564 current_data = &info->data[info->count];
3566 construct_info_data(current_data, type, field, id);
3568 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3569 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3571 notify_info_data_table[j].fn(snum, current_data, queue,
3577 free_a_printer(&printer, 2);
3581 /*******************************************************************
3583 * fill a notify_info struct with info asked
3585 ********************************************************************/
3587 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3588 SPOOL_NOTIFY_INFO *info,
3589 NT_PRINTER_INFO_LEVEL *printer,
3590 int snum, SPOOL_NOTIFY_OPTION_TYPE
3591 *option_type, uint32 id,
3592 TALLOC_CTX *mem_ctx)
3598 SPOOL_NOTIFY_INFO_DATA *current_data;
3600 DEBUG(4,("construct_notify_jobs_info\n"));
3602 type = option_type->type;
3604 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3605 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3606 option_type->count));
3608 for(field_num=0; field_num<option_type->count; field_num++) {
3609 field = option_type->fields[field_num];
3611 if (!search_notify(type, field, &j) )
3614 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3615 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3619 current_data=&(info->data[info->count]);
3621 construct_info_data(current_data, type, field, id);
3622 notify_info_data_table[j].fn(snum, current_data, queue,
3631 * JFM: The enumeration is not that simple, it's even non obvious.
3633 * let's take an example: I want to monitor the PRINTER SERVER for
3634 * the printer's name and the number of jobs currently queued.
3635 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3636 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3638 * I have 3 printers on the back of my server.
3640 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3643 * 1 printer 1 name 1
3644 * 2 printer 1 cjob 1
3645 * 3 printer 2 name 2
3646 * 4 printer 2 cjob 2
3647 * 5 printer 3 name 3
3648 * 6 printer 3 name 3
3650 * that's the print server case, the printer case is even worse.
3653 /*******************************************************************
3655 * enumerate all printers on the printserver
3656 * fill a notify_info struct with info asked
3658 ********************************************************************/
3660 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3661 SPOOL_NOTIFY_INFO *info,
3662 TALLOC_CTX *mem_ctx)
3665 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3666 int n_services=lp_numservices();
3668 SPOOL_NOTIFY_OPTION *option;
3669 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3671 DEBUG(4,("printserver_notify_info\n"));
3676 option=Printer->notify.option;
3681 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3682 sending a ffpcn() request first */
3687 for (i=0; i<option->count; i++) {
3688 option_type=&(option->ctr.type[i]);
3690 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3693 for (snum=0; snum<n_services; snum++)
3695 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3696 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3702 * Debugging information, don't delete.
3705 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3706 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3707 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3709 for (i=0; i<info->count; i++) {
3710 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3711 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3712 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3719 /*******************************************************************
3721 * fill a notify_info struct with info asked
3723 ********************************************************************/
3725 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3726 TALLOC_CTX *mem_ctx)
3729 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3732 SPOOL_NOTIFY_OPTION *option;
3733 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3735 print_queue_struct *queue=NULL;
3736 print_status_struct status;
3738 DEBUG(4,("printer_notify_info\n"));
3743 option=Printer->notify.option;
3749 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3750 sending a ffpcn() request first */
3755 get_printer_snum(p, hnd, &snum);
3757 for (i=0; i<option->count; i++) {
3758 option_type=&option->ctr.type[i];
3760 switch ( option_type->type ) {
3761 case PRINTER_NOTIFY_TYPE:
3762 if(construct_notify_printer_info(Printer, info, snum,
3768 case JOB_NOTIFY_TYPE: {
3769 NT_PRINTER_INFO_LEVEL *printer = NULL;
3771 count = print_queue_status(snum, &queue, &status);
3773 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3776 for (j=0; j<count; j++) {
3777 construct_notify_jobs_info(&queue[j], info,
3784 free_a_printer(&printer, 2);
3794 * Debugging information, don't delete.
3797 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3798 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3799 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3801 for (i=0; i<info->count; i++) {
3802 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3803 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3804 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3810 /********************************************************************
3812 ********************************************************************/
3814 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3816 POLICY_HND *handle = &q_u->handle;
3817 SPOOL_NOTIFY_INFO *info = &r_u->info;
3819 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3820 WERROR result = WERR_BADFID;
3822 /* we always have a NOTIFY_INFO struct */
3826 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3827 OUR_HANDLE(handle)));
3831 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3834 * We are now using the change value, and
3835 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3836 * I don't have a global notification system, I'm sending back all the
3837 * informations even when _NOTHING_ has changed.
3840 /* We need to keep track of the change value to send back in
3841 RRPCN replies otherwise our updates are ignored. */
3843 Printer->notify.fnpcn = True;
3845 if (Printer->notify.client_connected) {
3846 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3847 Printer->notify.change = q_u->change;
3850 /* just ignore the SPOOL_NOTIFY_OPTION */
3852 switch (Printer->printer_type) {
3854 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3857 case SPLHND_PRINTER:
3858 result = printer_notify_info(p, handle, info, p->mem_ctx);
3862 Printer->notify.fnpcn = False;
3868 /********************************************************************
3869 * construct_printer_info_0
3870 * fill a printer_info_0 struct
3871 ********************************************************************/
3873 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3877 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3878 counter_printer_0 *session_counter;
3879 uint32 global_counter;
3882 print_status_struct status;
3884 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3887 count = print_queue_length(snum, &status);
3889 /* check if we already have a counter for this printer */
3890 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3891 if (session_counter->snum == snum)
3895 /* it's the first time, add it to the list */
3896 if (session_counter==NULL) {
3897 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3898 free_a_printer(&ntprinter, 2);
3901 ZERO_STRUCTP(session_counter);
3902 session_counter->snum=snum;
3903 session_counter->counter=0;
3904 DLIST_ADD(counter_list, session_counter);
3908 session_counter->counter++;
3911 * the global_counter should be stored in a TDB as it's common to all the clients
3912 * and should be zeroed on samba startup
3914 global_counter=session_counter->counter;
3916 pstrcpy(chaine,ntprinter->info_2->printername);
3918 init_unistr(&printer->printername, chaine);
3920 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3921 init_unistr(&printer->servername, chaine);
3923 printer->cjobs = count;
3924 printer->total_jobs = 0;
3925 printer->total_bytes = 0;
3927 setuptime = (time_t)ntprinter->info_2->setuptime;
3928 t=gmtime(&setuptime);
3930 printer->year = t->tm_year+1900;
3931 printer->month = t->tm_mon+1;
3932 printer->dayofweek = t->tm_wday;
3933 printer->day = t->tm_mday;
3934 printer->hour = t->tm_hour;
3935 printer->minute = t->tm_min;
3936 printer->second = t->tm_sec;
3937 printer->milliseconds = 0;
3939 printer->global_counter = global_counter;
3940 printer->total_pages = 0;
3942 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3943 printer->major_version = 0x0005; /* NT 5 */
3944 printer->build_version = 0x0893; /* build 2195 */
3946 printer->unknown7 = 0x1;
3947 printer->unknown8 = 0x0;
3948 printer->unknown9 = 0x0;
3949 printer->session_counter = session_counter->counter;
3950 printer->unknown11 = 0x0;
3951 printer->printer_errors = 0x0; /* number of print failure */
3952 printer->unknown13 = 0x0;
3953 printer->unknown14 = 0x1;
3954 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3955 printer->unknown16 = 0x0;
3956 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3957 printer->unknown18 = 0x0;
3958 printer->status = nt_printq_status(status.status);
3959 printer->unknown20 = 0x0;
3960 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3961 printer->unknown22 = 0x0;
3962 printer->unknown23 = 0x6; /* 6 ???*/
3963 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3964 printer->unknown25 = 0;
3965 printer->unknown26 = 0;
3966 printer->unknown27 = 0;
3967 printer->unknown28 = 0;
3968 printer->unknown29 = 0;
3970 free_a_printer(&ntprinter,2);
3974 /********************************************************************
3975 * construct_printer_info_1
3976 * fill a printer_info_1 struct
3977 ********************************************************************/
3978 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3982 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3984 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3987 printer->flags=flags;
3989 if (*ntprinter->info_2->comment == '\0') {
3990 init_unistr(&printer->comment, lp_comment(snum));
3991 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3992 ntprinter->info_2->drivername, lp_comment(snum));
3995 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3996 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3997 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4000 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4002 init_unistr(&printer->description, chaine);
4003 init_unistr(&printer->name, chaine2);
4005 free_a_printer(&ntprinter,2);
4010 /****************************************************************************
4011 Free a DEVMODE struct.
4012 ****************************************************************************/
4014 static void free_dev_mode(DEVICEMODE *dev)
4019 SAFE_FREE(dev->dev_private);
4024 /****************************************************************************
4025 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4026 should be valid upon entry
4027 ****************************************************************************/
4029 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4031 if ( !devmode || !ntdevmode )
4034 init_unistr(&devmode->devicename, ntdevmode->devicename);
4036 init_unistr(&devmode->formname, ntdevmode->formname);
4038 devmode->specversion = ntdevmode->specversion;
4039 devmode->driverversion = ntdevmode->driverversion;
4040 devmode->size = ntdevmode->size;
4041 devmode->driverextra = ntdevmode->driverextra;
4042 devmode->fields = ntdevmode->fields;
4044 devmode->orientation = ntdevmode->orientation;
4045 devmode->papersize = ntdevmode->papersize;
4046 devmode->paperlength = ntdevmode->paperlength;
4047 devmode->paperwidth = ntdevmode->paperwidth;
4048 devmode->scale = ntdevmode->scale;
4049 devmode->copies = ntdevmode->copies;
4050 devmode->defaultsource = ntdevmode->defaultsource;
4051 devmode->printquality = ntdevmode->printquality;
4052 devmode->color = ntdevmode->color;
4053 devmode->duplex = ntdevmode->duplex;
4054 devmode->yresolution = ntdevmode->yresolution;
4055 devmode->ttoption = ntdevmode->ttoption;
4056 devmode->collate = ntdevmode->collate;
4057 devmode->icmmethod = ntdevmode->icmmethod;
4058 devmode->icmintent = ntdevmode->icmintent;
4059 devmode->mediatype = ntdevmode->mediatype;
4060 devmode->dithertype = ntdevmode->dithertype;
4062 if (ntdevmode->nt_dev_private != NULL) {
4063 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4070 /****************************************************************************
4071 Create a DEVMODE struct. Returns malloced memory.
4072 ****************************************************************************/
4074 DEVICEMODE *construct_dev_mode(const char *servicename)
4076 NT_PRINTER_INFO_LEVEL *printer = NULL;
4077 DEVICEMODE *devmode = NULL;
4079 DEBUG(7,("construct_dev_mode\n"));
4081 DEBUGADD(8,("getting printer characteristics\n"));
4083 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4086 if ( !printer->info_2->devmode ) {
4087 DEBUG(5, ("BONG! There was no device mode!\n"));
4091 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4092 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4096 ZERO_STRUCTP(devmode);
4098 DEBUGADD(8,("loading DEVICEMODE\n"));
4100 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4101 free_dev_mode( devmode );
4106 free_a_printer(&printer,2);
4111 /********************************************************************
4112 * construct_printer_info_2
4113 * fill a printer_info_2 struct
4114 ********************************************************************/
4116 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4119 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4121 print_status_struct status;
4123 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4126 count = print_queue_length(snum, &status);
4128 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4129 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4130 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4131 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4132 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4134 if (*ntprinter->info_2->comment == '\0')
4135 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4137 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4139 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4140 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4141 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4142 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4143 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4145 printer->attributes = ntprinter->info_2->attributes;
4147 printer->priority = ntprinter->info_2->priority; /* priority */
4148 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4149 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4150 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4151 printer->status = nt_printq_status(status.status); /* status */
4152 printer->cjobs = count; /* jobs */
4153 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4155 if ( !(printer->devmode = construct_dev_mode(lp_const_servicename(snum))) )
4156 DEBUG(8, ("Returning NULL Devicemode!\n"));
4158 printer->secdesc = NULL;
4160 if ( ntprinter->info_2->secdesc_buf
4161 && ntprinter->info_2->secdesc_buf->len != 0 )
4163 /* don't use talloc_steal() here unless you do a deep steal of all
4164 the SEC_DESC members */
4166 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4167 ntprinter->info_2->secdesc_buf->sec );
4170 free_a_printer(&ntprinter, 2);
4175 /********************************************************************
4176 * construct_printer_info_3
4177 * fill a printer_info_3 struct
4178 ********************************************************************/
4180 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4182 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4183 PRINTER_INFO_3 *printer = NULL;
4185 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4189 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4190 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4191 free_a_printer(&ntprinter, 2);
4195 ZERO_STRUCTP(printer);
4197 /* These are the components of the SD we are returning. */
4199 printer->flags = 0x4;
4201 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4202 /* don't use talloc_steal() here unless you do a deep steal of all
4203 the SEC_DESC members */
4205 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4206 ntprinter->info_2->secdesc_buf->sec );
4209 free_a_printer(&ntprinter, 2);
4211 *pp_printer = printer;
4215 /********************************************************************
4216 * construct_printer_info_4
4217 * fill a printer_info_4 struct
4218 ********************************************************************/
4220 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4222 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4224 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4227 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4228 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4229 printer->attributes = ntprinter->info_2->attributes;
4231 free_a_printer(&ntprinter, 2);
4235 /********************************************************************
4236 * construct_printer_info_5
4237 * fill a printer_info_5 struct
4238 ********************************************************************/
4240 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4242 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4244 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4247 init_unistr(&printer->printername, ntprinter->info_2->printername);
4248 init_unistr(&printer->portname, ntprinter->info_2->portname);
4249 printer->attributes = ntprinter->info_2->attributes;
4251 /* these two are not used by NT+ according to MSDN */
4253 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4254 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4256 free_a_printer(&ntprinter, 2);
4261 /********************************************************************
4262 * construct_printer_info_7
4263 * fill a printer_info_7 struct
4264 ********************************************************************/
4266 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4268 char *guid_str = NULL;
4271 if (is_printer_published(print_hnd, snum, &guid)) {
4272 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4273 strupper_m(guid_str);
4274 init_unistr(&printer->guid, guid_str);
4275 printer->action = SPOOL_DS_PUBLISH;
4277 init_unistr(&printer->guid, "");
4278 printer->action = SPOOL_DS_UNPUBLISH;
4284 /********************************************************************
4285 Spoolss_enumprinters.
4286 ********************************************************************/
4288 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4292 int n_services=lp_numservices();
4293 PRINTER_INFO_1 *printers=NULL;
4294 PRINTER_INFO_1 current_prt;
4295 WERROR result = WERR_OK;
4297 DEBUG(4,("enum_all_printers_info_1\n"));
4299 for (snum=0; snum<n_services; snum++) {
4300 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4301 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4303 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4304 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4305 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4309 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4311 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4317 /* check the required size. */
4318 for (i=0; i<*returned; i++)
4319 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4321 if (*needed > offered) {
4322 result = WERR_INSUFFICIENT_BUFFER;
4326 if (!rpcbuf_alloc_size(buffer, *needed)) {
4327 result = WERR_NOMEM;
4331 /* fill the buffer with the structures */
4332 for (i=0; i<*returned; i++)
4333 smb_io_printer_info_1("", buffer, &printers[i], 0);
4338 SAFE_FREE(printers);
4340 if ( !W_ERROR_IS_OK(result) )
4346 /********************************************************************
4347 enum_all_printers_info_1_local.
4348 *********************************************************************/
4350 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4352 DEBUG(4,("enum_all_printers_info_1_local\n"));
4354 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4357 /********************************************************************
4358 enum_all_printers_info_1_name.
4359 *********************************************************************/
4361 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4365 DEBUG(4,("enum_all_printers_info_1_name\n"));
4367 if ((name[0] == '\\') && (name[1] == '\\'))
4370 if (is_myname_or_ipaddr(s)) {
4371 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4374 return WERR_INVALID_NAME;
4377 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4378 /********************************************************************
4379 enum_all_printers_info_1_remote.
4380 *********************************************************************/
4382 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4384 PRINTER_INFO_1 *printer;
4385 fstring printername;
4388 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4389 WERROR result = WERR_OK;
4391 /* JFM: currently it's more a place holder than anything else.
4392 * In the spooler world there is a notion of server registration.
4393 * the print servers are registered on the PDC (in the same domain)
4395 * We should have a TDB here. The registration is done thru an
4396 * undocumented RPC call.
4399 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4404 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4405 slprintf(desc, sizeof(desc)-1,"%s", name);
4406 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4408 init_unistr(&printer->description, desc);
4409 init_unistr(&printer->name, printername);
4410 init_unistr(&printer->comment, comment);
4411 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4413 /* check the required size. */
4414 *needed += spoolss_size_printer_info_1(printer);
4416 if (*needed > offered) {
4417 result = WERR_INSUFFICIENT_BUFFER;
4421 if (!rpcbuf_alloc_size(buffer, *needed)) {
4422 result = WERR_NOMEM;
4426 /* fill the buffer with the structures */
4427 smb_io_printer_info_1("", buffer, printer, 0);
4433 if ( !W_ERROR_IS_OK(result) )
4441 /********************************************************************
4442 enum_all_printers_info_1_network.
4443 *********************************************************************/
4445 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4449 DEBUG(4,("enum_all_printers_info_1_network\n"));
4451 /* If we respond to a enum_printers level 1 on our name with flags
4452 set to PRINTER_ENUM_REMOTE with a list of printers then these
4453 printers incorrectly appear in the APW browse list.
4454 Specifically the printers for the server appear at the workgroup
4455 level where all the other servers in the domain are
4456 listed. Windows responds to this call with a
4457 WERR_CAN_NOT_COMPLETE so we should do the same. */
4459 if (name[0] == '\\' && name[1] == '\\')
4462 if (is_myname_or_ipaddr(s))
4463 return WERR_CAN_NOT_COMPLETE;
4465 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4468 /********************************************************************
4469 * api_spoolss_enumprinters
4471 * called from api_spoolss_enumprinters (see this to understand)
4472 ********************************************************************/
4474 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4478 int n_services=lp_numservices();
4479 PRINTER_INFO_2 *printers=NULL;
4480 PRINTER_INFO_2 current_prt;
4481 WERROR result = WERR_OK;
4485 for (snum=0; snum<n_services; snum++) {
4486 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4487 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4489 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4490 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4491 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4496 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4498 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4505 /* check the required size. */
4506 for (i=0; i<*returned; i++)
4507 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4509 if (*needed > offered) {
4510 result = WERR_INSUFFICIENT_BUFFER;
4514 if (!rpcbuf_alloc_size(buffer, *needed)) {
4515 result = WERR_NOMEM;
4519 /* fill the buffer with the structures */
4520 for (i=0; i<*returned; i++)
4521 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4526 for (i=0; i<*returned; i++)
4527 free_devmode(printers[i].devmode);
4529 SAFE_FREE(printers);
4531 if ( !W_ERROR_IS_OK(result) )
4537 /********************************************************************
4538 * handle enumeration of printers at level 1
4539 ********************************************************************/
4541 static WERROR enumprinters_level1( uint32 flags, fstring name,
4542 RPC_BUFFER *buffer, uint32 offered,
4543 uint32 *needed, uint32 *returned)
4545 /* Not all the flags are equals */
4547 if (flags & PRINTER_ENUM_LOCAL)
4548 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4550 if (flags & PRINTER_ENUM_NAME)
4551 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4553 #if 0 /* JERRY - disabled for now */
4554 if (flags & PRINTER_ENUM_REMOTE)
4555 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4558 if (flags & PRINTER_ENUM_NETWORK)
4559 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4561 return WERR_OK; /* NT4sp5 does that */
4564 /********************************************************************
4565 * handle enumeration of printers at level 2
4566 ********************************************************************/
4568 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4569 RPC_BUFFER *buffer, uint32 offered,
4570 uint32 *needed, uint32 *returned)
4572 char *s = servername;
4574 if (flags & PRINTER_ENUM_LOCAL) {
4575 return enum_all_printers_info_2(buffer, offered, needed, returned);
4578 if (flags & PRINTER_ENUM_NAME) {
4579 if ((servername[0] == '\\') && (servername[1] == '\\'))
4581 if (is_myname_or_ipaddr(s))
4582 return enum_all_printers_info_2(buffer, offered, needed, returned);
4584 return WERR_INVALID_NAME;
4587 if (flags & PRINTER_ENUM_REMOTE)
4588 return WERR_UNKNOWN_LEVEL;
4593 /********************************************************************
4594 * handle enumeration of printers at level 5
4595 ********************************************************************/
4597 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4598 RPC_BUFFER *buffer, uint32 offered,
4599 uint32 *needed, uint32 *returned)
4601 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4605 /********************************************************************
4606 * api_spoolss_enumprinters
4608 * called from api_spoolss_enumprinters (see this to understand)
4609 ********************************************************************/
4611 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4613 uint32 flags = q_u->flags;
4614 UNISTR2 *servername = &q_u->servername;
4615 uint32 level = q_u->level;
4616 RPC_BUFFER *buffer = NULL;
4617 uint32 offered = q_u->offered;
4618 uint32 *needed = &r_u->needed;
4619 uint32 *returned = &r_u->returned;
4623 /* that's an [in out] buffer */
4625 if (!q_u->buffer && (offered!=0)) {
4626 return WERR_INVALID_PARAM;
4629 rpcbuf_move(q_u->buffer, &r_u->buffer);
4630 buffer = r_u->buffer;
4632 DEBUG(4,("_spoolss_enumprinters\n"));
4639 * flags==PRINTER_ENUM_NAME
4640 * if name=="" then enumerates all printers
4641 * if name!="" then enumerate the printer
4642 * flags==PRINTER_ENUM_REMOTE
4643 * name is NULL, enumerate printers
4644 * Level 2: name!="" enumerates printers, name can't be NULL
4645 * Level 3: doesn't exist
4646 * Level 4: does a local registry lookup
4647 * Level 5: same as Level 2
4650 unistr2_to_ascii(name, servername, sizeof(name)-1);
4655 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4657 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4659 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4664 return WERR_UNKNOWN_LEVEL;
4667 /****************************************************************************
4668 ****************************************************************************/
4670 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4672 PRINTER_INFO_0 *printer=NULL;
4673 WERROR result = WERR_OK;
4675 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4678 construct_printer_info_0(print_hnd, printer, snum);
4680 /* check the required size. */
4681 *needed += spoolss_size_printer_info_0(printer);
4683 if (*needed > offered) {
4684 result = WERR_INSUFFICIENT_BUFFER;
4688 if (!rpcbuf_alloc_size(buffer, *needed)) {
4689 result = WERR_NOMEM;
4693 /* fill the buffer with the structures */
4694 smb_io_printer_info_0("", buffer, printer, 0);
4704 /****************************************************************************
4705 ****************************************************************************/
4707 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4709 PRINTER_INFO_1 *printer=NULL;
4710 WERROR result = WERR_OK;
4712 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4715 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4717 /* check the required size. */
4718 *needed += spoolss_size_printer_info_1(printer);
4720 if (*needed > offered) {
4721 result = WERR_INSUFFICIENT_BUFFER;
4725 if (!rpcbuf_alloc_size(buffer, *needed)) {
4726 result = WERR_NOMEM;
4730 /* fill the buffer with the structures */
4731 smb_io_printer_info_1("", buffer, printer, 0);
4740 /****************************************************************************
4741 ****************************************************************************/
4743 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4745 PRINTER_INFO_2 *printer=NULL;
4746 WERROR result = WERR_OK;
4748 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4751 construct_printer_info_2(print_hnd, printer, snum);
4753 /* check the required size. */
4754 *needed += spoolss_size_printer_info_2(printer);
4756 if (*needed > offered) {
4757 result = WERR_INSUFFICIENT_BUFFER;
4761 if (!rpcbuf_alloc_size(buffer, *needed)) {
4762 result = WERR_NOMEM;
4766 /* fill the buffer with the structures */
4767 if (!smb_io_printer_info_2("", buffer, printer, 0))
4768 result = WERR_NOMEM;
4772 free_printer_info_2(printer);
4777 /****************************************************************************
4778 ****************************************************************************/
4780 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4782 PRINTER_INFO_3 *printer=NULL;
4783 WERROR result = WERR_OK;
4785 if (!construct_printer_info_3(print_hnd, &printer, snum))
4788 /* check the required size. */
4789 *needed += spoolss_size_printer_info_3(printer);
4791 if (*needed > offered) {
4792 result = WERR_INSUFFICIENT_BUFFER;
4796 if (!rpcbuf_alloc_size(buffer, *needed)) {
4797 result = WERR_NOMEM;
4801 /* fill the buffer with the structures */
4802 smb_io_printer_info_3("", buffer, printer, 0);
4806 free_printer_info_3(printer);
4811 /****************************************************************************
4812 ****************************************************************************/
4814 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4816 PRINTER_INFO_4 *printer=NULL;
4817 WERROR result = WERR_OK;
4819 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4822 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4827 /* check the required size. */
4828 *needed += spoolss_size_printer_info_4(printer);
4830 if (*needed > offered) {
4831 result = WERR_INSUFFICIENT_BUFFER;
4835 if (!rpcbuf_alloc_size(buffer, *needed)) {
4836 result = WERR_NOMEM;
4840 /* fill the buffer with the structures */
4841 smb_io_printer_info_4("", buffer, printer, 0);
4845 free_printer_info_4(printer);
4850 /****************************************************************************
4851 ****************************************************************************/
4853 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4855 PRINTER_INFO_5 *printer=NULL;
4856 WERROR result = WERR_OK;
4858 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4861 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4862 free_printer_info_5(printer);
4866 /* check the required size. */
4867 *needed += spoolss_size_printer_info_5(printer);
4869 if (*needed > offered) {
4870 result = WERR_INSUFFICIENT_BUFFER;
4874 if (!rpcbuf_alloc_size(buffer, *needed)) {
4875 result = WERR_NOMEM;
4879 /* fill the buffer with the structures */
4880 smb_io_printer_info_5("", buffer, printer, 0);
4884 free_printer_info_5(printer);
4889 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4891 PRINTER_INFO_7 *printer=NULL;
4892 WERROR result = WERR_OK;
4894 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4897 if (!construct_printer_info_7(print_hnd, printer, snum))
4900 /* check the required size. */
4901 *needed += spoolss_size_printer_info_7(printer);
4903 if (*needed > offered) {
4904 result = WERR_INSUFFICIENT_BUFFER;
4908 if (!rpcbuf_alloc_size(buffer, *needed)) {
4909 result = WERR_NOMEM;
4914 /* fill the buffer with the structures */
4915 smb_io_printer_info_7("", buffer, printer, 0);
4919 free_printer_info_7(printer);
4924 /****************************************************************************
4925 ****************************************************************************/
4927 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4929 POLICY_HND *handle = &q_u->handle;
4930 uint32 level = q_u->level;
4931 RPC_BUFFER *buffer = NULL;
4932 uint32 offered = q_u->offered;
4933 uint32 *needed = &r_u->needed;
4934 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4938 /* that's an [in out] buffer */
4940 if (!q_u->buffer && (offered!=0)) {
4941 return WERR_INVALID_PARAM;
4944 rpcbuf_move(q_u->buffer, &r_u->buffer);
4945 buffer = r_u->buffer;
4949 if (!get_printer_snum(p, handle, &snum))
4954 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4956 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4958 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4960 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4962 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4964 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4966 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4968 return WERR_UNKNOWN_LEVEL;
4971 /********************************************************************
4972 * fill a DRIVER_INFO_1 struct
4973 ********************************************************************/
4975 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4977 init_unistr( &info->name, driver.info_3->name);
4980 /********************************************************************
4981 * construct_printer_driver_info_1
4982 ********************************************************************/
4984 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4986 NT_PRINTER_INFO_LEVEL *printer = NULL;
4987 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4989 ZERO_STRUCT(driver);
4991 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4992 return WERR_INVALID_PRINTER_NAME;
4994 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
4995 free_a_printer(&printer, 2);
4996 return WERR_UNKNOWN_PRINTER_DRIVER;
4999 fill_printer_driver_info_1(info, driver, servername, architecture);
5001 free_a_printer(&printer,2);
5006 /********************************************************************
5007 * construct_printer_driver_info_2
5008 * fill a printer_info_2 struct
5009 ********************************************************************/
5011 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5015 info->version=driver.info_3->cversion;
5017 init_unistr( &info->name, driver.info_3->name );
5018 init_unistr( &info->architecture, driver.info_3->environment );
5021 if (strlen(driver.info_3->driverpath)) {
5022 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5023 init_unistr( &info->driverpath, temp );
5025 init_unistr( &info->driverpath, "" );
5027 if (strlen(driver.info_3->datafile)) {
5028 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5029 init_unistr( &info->datafile, temp );
5031 init_unistr( &info->datafile, "" );
5033 if (strlen(driver.info_3->configfile)) {
5034 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5035 init_unistr( &info->configfile, temp );
5037 init_unistr( &info->configfile, "" );
5040 /********************************************************************
5041 * construct_printer_driver_info_2
5042 * fill a printer_info_2 struct
5043 ********************************************************************/
5045 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5047 NT_PRINTER_INFO_LEVEL *printer = NULL;
5048 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5050 ZERO_STRUCT(printer);
5051 ZERO_STRUCT(driver);
5053 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5054 return WERR_INVALID_PRINTER_NAME;
5056 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5057 free_a_printer(&printer, 2);
5058 return WERR_UNKNOWN_PRINTER_DRIVER;
5061 fill_printer_driver_info_2(info, driver, servername);
5063 free_a_printer(&printer,2);
5068 /********************************************************************
5069 * copy a strings array and convert to UNICODE
5071 * convert an array of ascii string to a UNICODE string
5072 ********************************************************************/
5074 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5081 DEBUG(6,("init_unistr_array\n"));
5092 v = ""; /* hack to handle null lists */
5095 /* hack to allow this to be used in places other than when generating
5096 the list of dependent files */
5099 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5103 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5105 /* add one extra unit16 for the second terminating NULL */
5107 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5108 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5115 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5120 /* special case for ""; we need to add both NULL's here */
5122 (*uni_array)[j++]=0x0000;
5123 (*uni_array)[j]=0x0000;
5126 DEBUGADD(6,("last one:done\n"));
5128 /* return size of array in uint16's */
5133 /********************************************************************
5134 * construct_printer_info_3
5135 * fill a printer_info_3 struct
5136 ********************************************************************/
5138 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5144 info->version=driver.info_3->cversion;
5146 init_unistr( &info->name, driver.info_3->name );
5147 init_unistr( &info->architecture, driver.info_3->environment );
5149 if (strlen(driver.info_3->driverpath)) {
5150 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5151 init_unistr( &info->driverpath, temp );
5153 init_unistr( &info->driverpath, "" );
5155 if (strlen(driver.info_3->datafile)) {
5156 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5157 init_unistr( &info->datafile, temp );
5159 init_unistr( &info->datafile, "" );
5161 if (strlen(driver.info_3->configfile)) {
5162 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5163 init_unistr( &info->configfile, temp );
5165 init_unistr( &info->configfile, "" );
5167 if (strlen(driver.info_3->helpfile)) {
5168 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5169 init_unistr( &info->helpfile, temp );
5171 init_unistr( &info->helpfile, "" );
5173 init_unistr( &info->monitorname, driver.info_3->monitorname );
5174 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5176 info->dependentfiles=NULL;
5177 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5180 /********************************************************************
5181 * construct_printer_info_3
5182 * fill a printer_info_3 struct
5183 ********************************************************************/
5185 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5187 NT_PRINTER_INFO_LEVEL *printer = NULL;
5188 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5190 ZERO_STRUCT(driver);
5192 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5193 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5194 if (!W_ERROR_IS_OK(status))
5195 return WERR_INVALID_PRINTER_NAME;
5197 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5198 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5203 * I put this code in during testing. Helpful when commenting out the
5204 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5205 * as win2k always queries the driver using an infor level of 6.
5206 * I've left it in (but ifdef'd out) because I'll probably
5207 * use it in experimentation again in the future. --jerry 22/01/2002
5210 if (!W_ERROR_IS_OK(status)) {
5212 * Is this a W2k client ?
5215 /* Yes - try again with a WinNT driver. */
5217 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5218 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5222 if (!W_ERROR_IS_OK(status)) {
5223 free_a_printer(&printer,2);
5224 return WERR_UNKNOWN_PRINTER_DRIVER;
5232 fill_printer_driver_info_3(info, driver, servername);
5234 free_a_printer(&printer,2);
5239 /********************************************************************
5240 * construct_printer_info_6
5241 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5242 ********************************************************************/
5244 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5250 memset(&nullstr, '\0', sizeof(fstring));
5252 info->version=driver.info_3->cversion;
5254 init_unistr( &info->name, driver.info_3->name );
5255 init_unistr( &info->architecture, driver.info_3->environment );
5257 if (strlen(driver.info_3->driverpath)) {
5258 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5259 init_unistr( &info->driverpath, temp );
5261 init_unistr( &info->driverpath, "" );
5263 if (strlen(driver.info_3->datafile)) {
5264 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5265 init_unistr( &info->datafile, temp );
5267 init_unistr( &info->datafile, "" );
5269 if (strlen(driver.info_3->configfile)) {
5270 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5271 init_unistr( &info->configfile, temp );
5273 init_unistr( &info->configfile, "" );
5275 if (strlen(driver.info_3->helpfile)) {
5276 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5277 init_unistr( &info->helpfile, temp );
5279 init_unistr( &info->helpfile, "" );
5281 init_unistr( &info->monitorname, driver.info_3->monitorname );
5282 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5284 info->dependentfiles = NULL;
5285 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5287 info->previousdrivernames=NULL;
5288 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5290 info->driver_date=0;
5293 info->driver_version_low=0;
5294 info->driver_version_high=0;
5296 init_unistr( &info->mfgname, "");
5297 init_unistr( &info->oem_url, "");
5298 init_unistr( &info->hardware_id, "");
5299 init_unistr( &info->provider, "");
5302 /********************************************************************
5303 * construct_printer_info_6
5304 * fill a printer_info_6 struct
5305 ********************************************************************/
5307 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5308 fstring servername, fstring architecture, uint32 version)
5310 NT_PRINTER_INFO_LEVEL *printer = NULL;
5311 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5314 ZERO_STRUCT(driver);
5316 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5318 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5320 if (!W_ERROR_IS_OK(status))
5321 return WERR_INVALID_PRINTER_NAME;
5323 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5325 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5327 if (!W_ERROR_IS_OK(status))
5330 * Is this a W2k client ?
5334 free_a_printer(&printer,2);
5335 return WERR_UNKNOWN_PRINTER_DRIVER;
5338 /* Yes - try again with a WinNT driver. */
5340 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5341 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5342 if (!W_ERROR_IS_OK(status)) {
5343 free_a_printer(&printer,2);
5344 return WERR_UNKNOWN_PRINTER_DRIVER;
5348 fill_printer_driver_info_6(info, driver, servername);
5350 free_a_printer(&printer,2);
5351 free_a_printer_driver(driver, 3);
5356 /****************************************************************************
5357 ****************************************************************************/
5359 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5361 SAFE_FREE(info->dependentfiles);
5364 /****************************************************************************
5365 ****************************************************************************/
5367 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5369 SAFE_FREE(info->dependentfiles);
5372 /****************************************************************************
5373 ****************************************************************************/
5375 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5377 DRIVER_INFO_1 *info=NULL;
5380 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5383 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5384 if (!W_ERROR_IS_OK(result))
5387 /* check the required size. */
5388 *needed += spoolss_size_printer_driver_info_1(info);
5390 if (*needed > offered) {
5391 result = WERR_INSUFFICIENT_BUFFER;
5395 if (!rpcbuf_alloc_size(buffer, *needed)) {
5396 result = WERR_NOMEM;
5400 /* fill the buffer with the structures */
5401 smb_io_printer_driver_info_1("", buffer, info, 0);
5410 /****************************************************************************
5411 ****************************************************************************/
5413 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5415 DRIVER_INFO_2 *info=NULL;
5418 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5421 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5422 if (!W_ERROR_IS_OK(result))
5425 /* check the required size. */
5426 *needed += spoolss_size_printer_driver_info_2(info);
5428 if (*needed > offered) {
5429 result = WERR_INSUFFICIENT_BUFFER;
5433 if (!rpcbuf_alloc_size(buffer, *needed)) {
5434 result = WERR_NOMEM;
5438 /* fill the buffer with the structures */
5439 smb_io_printer_driver_info_2("", buffer, info, 0);
5448 /****************************************************************************
5449 ****************************************************************************/
5451 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5458 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5459 if (!W_ERROR_IS_OK(result))
5462 /* check the required size. */
5463 *needed += spoolss_size_printer_driver_info_3(&info);
5465 if (*needed > offered) {
5466 result = WERR_INSUFFICIENT_BUFFER;
5470 if (!rpcbuf_alloc_size(buffer, *needed)) {
5471 result = WERR_NOMEM;
5475 /* fill the buffer with the structures */
5476 smb_io_printer_driver_info_3("", buffer, &info, 0);
5479 free_printer_driver_info_3(&info);
5484 /****************************************************************************
5485 ****************************************************************************/
5487 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5494 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5495 if (!W_ERROR_IS_OK(result))
5498 /* check the required size. */
5499 *needed += spoolss_size_printer_driver_info_6(&info);
5501 if (*needed > offered) {
5502 result = WERR_INSUFFICIENT_BUFFER;
5506 if (!rpcbuf_alloc_size(buffer, *needed)) {
5507 result = WERR_NOMEM;
5511 /* fill the buffer with the structures */
5512 smb_io_printer_driver_info_6("", buffer, &info, 0);
5515 free_printer_driver_info_6(&info);
5520 /****************************************************************************
5521 ****************************************************************************/
5523 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5525 POLICY_HND *handle = &q_u->handle;
5526 UNISTR2 *uni_arch = &q_u->architecture;
5527 uint32 level = q_u->level;
5528 uint32 clientmajorversion = q_u->clientmajorversion;
5529 RPC_BUFFER *buffer = NULL;
5530 uint32 offered = q_u->offered;
5531 uint32 *needed = &r_u->needed;
5532 uint32 *servermajorversion = &r_u->servermajorversion;
5533 uint32 *serverminorversion = &r_u->serverminorversion;
5534 Printer_entry *printer;
5537 fstring architecture;
5540 /* that's an [in out] buffer */
5542 if (!q_u->buffer && (offered!=0)) {
5543 return WERR_INVALID_PARAM;
5546 rpcbuf_move(q_u->buffer, &r_u->buffer);
5547 buffer = r_u->buffer;
5549 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5551 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5552 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5553 return WERR_INVALID_PRINTER_NAME;
5557 *servermajorversion = 0;
5558 *serverminorversion = 0;
5560 fstrcpy(servername, get_server_name( printer ));
5561 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5563 if (!get_printer_snum(p, handle, &snum))
5568 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5570 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5572 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5574 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5577 /* apparently this call is the equivalent of
5578 EnumPrinterDataEx() for the DsDriver key */
5583 return WERR_UNKNOWN_LEVEL;
5586 /****************************************************************************
5587 ****************************************************************************/
5589 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5591 POLICY_HND *handle = &q_u->handle;
5593 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5596 DEBUG(3,("Error in startpageprinter printer handle\n"));
5600 Printer->page_started=True;
5604 /****************************************************************************
5605 ****************************************************************************/
5607 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5609 POLICY_HND *handle = &q_u->handle;
5612 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5615 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5619 if (!get_printer_snum(p, handle, &snum))
5622 Printer->page_started=False;
5623 print_job_endpage(snum, Printer->jobid);
5628 /********************************************************************
5629 * api_spoolss_getprinter
5630 * called from the spoolss dispatcher
5632 ********************************************************************/
5634 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5636 POLICY_HND *handle = &q_u->handle;
5637 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5638 uint32 *jobid = &r_u->jobid;
5640 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5644 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5647 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5652 * a nice thing with NT is it doesn't listen to what you tell it.
5653 * when asked to send _only_ RAW datas, it tries to send datas
5656 * So I add checks like in NT Server ...
5659 if (info_1->p_datatype != 0) {
5660 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5661 if (strcmp(datatype, "RAW") != 0) {
5663 return WERR_INVALID_DATATYPE;
5667 /* get the share number of the printer */
5668 if (!get_printer_snum(p, handle, &snum)) {
5672 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5674 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5676 /* An error occured in print_job_start() so return an appropriate
5679 if (Printer->jobid == -1) {
5680 return map_werror_from_unix(errno);
5683 Printer->document_started=True;
5684 (*jobid) = Printer->jobid;
5689 /********************************************************************
5690 * api_spoolss_getprinter
5691 * called from the spoolss dispatcher
5693 ********************************************************************/
5695 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5697 POLICY_HND *handle = &q_u->handle;
5699 return _spoolss_enddocprinter_internal(p, handle);
5702 /****************************************************************************
5703 ****************************************************************************/
5705 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5707 POLICY_HND *handle = &q_u->handle;
5708 uint32 buffer_size = q_u->buffer_size;
5709 uint8 *buffer = q_u->buffer;
5710 uint32 *buffer_written = &q_u->buffer_size2;
5712 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5715 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5716 r_u->buffer_written = q_u->buffer_size2;
5720 if (!get_printer_snum(p, handle, &snum))
5723 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5724 (SMB_OFF_T)-1, (size_t)buffer_size);
5725 if (*buffer_written == (uint32)-1) {
5726 r_u->buffer_written = 0;
5727 if (errno == ENOSPC)
5728 return WERR_NO_SPOOL_SPACE;
5730 return WERR_ACCESS_DENIED;
5733 r_u->buffer_written = q_u->buffer_size2;
5738 /********************************************************************
5739 * api_spoolss_getprinter
5740 * called from the spoolss dispatcher
5742 ********************************************************************/
5744 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5748 WERROR errcode = WERR_BADFUNC;
5749 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5752 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5756 if (!get_printer_snum(p, handle, &snum))
5760 case PRINTER_CONTROL_PAUSE:
5761 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5765 case PRINTER_CONTROL_RESUME:
5766 case PRINTER_CONTROL_UNPAUSE:
5767 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5771 case PRINTER_CONTROL_PURGE:
5772 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5777 return WERR_UNKNOWN_LEVEL;
5783 /********************************************************************
5784 * api_spoolss_abortprinter
5785 * From MSDN: "Deletes printer's spool file if printer is configured
5787 ********************************************************************/
5789 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5791 POLICY_HND *handle = &q_u->handle;
5792 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5794 WERROR errcode = WERR_OK;
5797 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5801 if (!get_printer_snum(p, handle, &snum))
5804 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5809 /********************************************************************
5810 * called by spoolss_api_setprinter
5811 * when updating a printer description
5812 ********************************************************************/
5814 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5815 const SPOOL_PRINTER_INFO_LEVEL *info,
5816 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5818 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5822 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5824 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5825 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5826 OUR_HANDLE(handle)));
5828 result = WERR_BADFID;
5832 /* Check the user has permissions to change the security
5833 descriptor. By experimentation with two NT machines, the user
5834 requires Full Access to the printer to change security
5837 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5838 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5839 result = WERR_ACCESS_DENIED;
5843 /* NT seems to like setting the security descriptor even though
5844 nothing may have actually changed. */
5846 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5848 if (DEBUGLEVEL >= 10) {
5852 the_acl = old_secdesc_ctr->sec->dacl;
5853 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5854 PRINTERNAME(snum), the_acl->num_aces));
5856 for (i = 0; i < the_acl->num_aces; i++) {
5859 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5861 DEBUG(10, ("%s 0x%08x\n", sid_str,
5862 the_acl->ace[i].info.mask));
5865 the_acl = secdesc_ctr->sec->dacl;
5868 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5869 PRINTERNAME(snum), the_acl->num_aces));
5871 for (i = 0; i < the_acl->num_aces; i++) {
5874 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5876 DEBUG(10, ("%s 0x%08x\n", sid_str,
5877 the_acl->ace[i].info.mask));
5880 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5884 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5885 if (!new_secdesc_ctr) {
5886 result = WERR_NOMEM;
5890 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5895 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5902 /********************************************************************
5903 Canonicalize printer info from a client
5905 ATTN: It does not matter what we set the servername to hear
5906 since we do the necessary work in get_a_printer() to set it to
5907 the correct value based on what the client sent in the
5908 _spoolss_open_printer_ex().
5909 ********************************************************************/
5911 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5913 fstring printername;
5916 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5917 "portname=%s drivername=%s comment=%s location=%s\n",
5918 info->servername, info->printername, info->sharename,
5919 info->portname, info->drivername, info->comment, info->location));
5921 /* we force some elements to "correct" values */
5922 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5923 fstrcpy(info->sharename, lp_servicename(snum));
5925 /* check to see if we allow printername != sharename */
5927 if ( lp_force_printername(snum) ) {
5928 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5929 global_myname(), info->sharename );
5932 /* make sure printername is in \\server\printername format */
5934 fstrcpy( printername, info->printername );
5936 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5937 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5941 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5942 global_myname(), p );
5945 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5946 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5953 /****************************************************************************
5954 ****************************************************************************/
5956 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5958 char *cmd = lp_addport_cmd();
5962 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5963 BOOL is_print_op = False;
5966 return WERR_ACCESS_DENIED;
5969 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5972 is_print_op = user_has_privileges( token, &se_printop );
5974 DEBUG(10,("Running [%s]\n", command));
5976 /********* BEGIN SePrintOperatorPrivilege **********/
5981 ret = smbrun(command, &fd);
5986 /********* END SePrintOperatorPrivilege **********/
5988 DEBUGADD(10,("returned [%d]\n", ret));
5993 return WERR_ACCESS_DENIED;
5999 /****************************************************************************
6000 ****************************************************************************/
6002 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6004 char *cmd = lp_addprinter_cmd();
6010 fstring remote_machine = "%m";
6011 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6012 BOOL is_print_op = False;
6014 standard_sub_basic(current_user_info.smb_name,
6015 current_user_info.domain,
6016 remote_machine,sizeof(remote_machine));
6018 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6019 cmd, printer->info_2->printername, printer->info_2->sharename,
6020 printer->info_2->portname, printer->info_2->drivername,
6021 printer->info_2->location, printer->info_2->comment, remote_machine);
6024 is_print_op = user_has_privileges( token, &se_printop );
6026 DEBUG(10,("Running [%s]\n", command));
6028 /********* BEGIN SePrintOperatorPrivilege **********/
6033 if ( (ret = smbrun(command, &fd)) == 0 ) {
6034 /* Tell everyone we updated smb.conf. */
6035 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6041 /********* END SePrintOperatorPrivilege **********/
6043 DEBUGADD(10,("returned [%d]\n", ret));
6051 /* reload our services immediately */
6052 reload_services( False );
6055 /* Get lines and convert them back to dos-codepage */
6056 qlines = fd_lines_load(fd, &numlines, 0);
6057 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6060 /* Set the portname to what the script says the portname should be. */
6061 /* but don't require anything to be return from the script exit a good error code */
6064 /* Set the portname to what the script says the portname should be. */
6065 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6066 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6069 file_lines_free(qlines);
6074 /********************************************************************
6075 * Called by spoolss_api_setprinter
6076 * when updating a printer description.
6077 ********************************************************************/
6079 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6080 const SPOOL_PRINTER_INFO_LEVEL *info,
6081 DEVICEMODE *devmode)
6084 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6085 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6090 DEBUG(8,("update_printer\n"));
6095 result = WERR_BADFID;
6099 if (!get_printer_snum(p, handle, &snum)) {
6100 result = WERR_BADFID;
6104 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6105 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6106 result = WERR_BADFID;
6110 DEBUGADD(8,("Converting info_2 struct\n"));
6113 * convert_printer_info converts the incoming
6114 * info from the client and overwrites the info
6115 * just read from the tdb in the pointer 'printer'.
6118 if (!convert_printer_info(info, printer, level)) {
6119 result = WERR_NOMEM;
6124 /* we have a valid devmode
6125 convert it and link it*/
6127 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6128 if (!convert_devicemode(printer->info_2->printername, devmode,
6129 &printer->info_2->devmode)) {
6130 result = WERR_NOMEM;
6135 /* Do sanity check on the requested changes for Samba */
6137 if (!check_printer_ok(printer->info_2, snum)) {
6138 result = WERR_INVALID_PARAM;
6142 /* FIXME!!! If the driver has changed we really should verify that
6143 it is installed before doing much else --jerry */
6145 /* Check calling user has permission to update printer description */
6147 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6148 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6149 result = WERR_ACCESS_DENIED;
6153 /* Call addprinter hook */
6154 /* Check changes to see if this is really needed */
6156 if ( *lp_addprinter_cmd()
6157 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6158 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6159 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6160 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6162 /* add_printer_hook() will call reload_services() */
6164 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6165 result = WERR_ACCESS_DENIED;
6171 * When a *new* driver is bound to a printer, the drivername is used to
6172 * lookup previously saved driver initialization info, which is then
6173 * bound to the printer, simulating what happens in the Windows arch.
6175 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6177 if (!set_driver_init(printer, 2))
6179 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6180 printer->info_2->drivername));
6183 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6184 printer->info_2->drivername));
6186 notify_printer_driver(snum, printer->info_2->drivername);
6190 * flag which changes actually occured. This is a small subset of
6191 * all the possible changes. We also have to update things in the
6195 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6196 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6197 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6198 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6200 notify_printer_comment(snum, printer->info_2->comment);
6203 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6204 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6205 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6206 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6208 notify_printer_sharename(snum, printer->info_2->sharename);
6211 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6214 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6217 pname = printer->info_2->printername;
6220 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6221 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6222 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6224 notify_printer_printername( snum, pname );
6227 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6228 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6229 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6230 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6232 notify_printer_port(snum, printer->info_2->portname);
6235 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6236 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6237 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6238 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6240 notify_printer_location(snum, printer->info_2->location);
6243 /* here we need to update some more DsSpooler keys */
6244 /* uNCName, serverName, shortServerName */
6246 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6247 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6248 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6249 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6250 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6252 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6253 global_myname(), printer->info_2->sharename );
6254 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6255 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6256 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6258 /* Update printer info */
6259 result = mod_a_printer(printer, 2);
6262 free_a_printer(&printer, 2);
6263 free_a_printer(&old_printer, 2);
6269 /****************************************************************************
6270 ****************************************************************************/
6271 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6272 const SPOOL_PRINTER_INFO_LEVEL *info)
6275 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6277 Printer_entry *Printer;
6279 if ( lp_security() != SEC_ADS ) {
6280 return WERR_UNKNOWN_LEVEL;
6283 Printer = find_printer_index_by_hnd(p, handle);
6285 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6290 if (!get_printer_snum(p, handle, &snum))
6293 nt_printer_publish(Printer, snum, info7->action);
6297 return WERR_UNKNOWN_LEVEL;
6300 /****************************************************************************
6301 ****************************************************************************/
6303 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6305 POLICY_HND *handle = &q_u->handle;
6306 uint32 level = q_u->level;
6307 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6308 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6309 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6310 uint32 command = q_u->command;
6313 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6316 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6320 /* check the level */
6323 return control_printer(handle, command, p);
6325 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6326 if (!W_ERROR_IS_OK(result))
6329 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6332 return update_printer_sec(handle, level, info, p,
6335 return publish_or_unpublish_printer(p, handle, info);
6337 return WERR_UNKNOWN_LEVEL;
6341 /****************************************************************************
6342 ****************************************************************************/
6344 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6346 POLICY_HND *handle = &q_u->handle;
6347 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6350 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6354 if (Printer->notify.client_connected==True) {
6357 if ( Printer->printer_type == SPLHND_SERVER)
6359 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6360 !get_printer_snum(p, handle, &snum) )
6363 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6366 Printer->notify.flags=0;
6367 Printer->notify.options=0;
6368 Printer->notify.localmachine[0]='\0';
6369 Printer->notify.printerlocal=0;
6370 if (Printer->notify.option)
6371 free_spool_notify_option(&Printer->notify.option);
6372 Printer->notify.client_connected=False;
6377 /****************************************************************************
6378 ****************************************************************************/
6380 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6382 /* that's an [in out] buffer */
6384 if (!q_u->buffer && (q_u->offered!=0)) {
6385 return WERR_INVALID_PARAM;
6388 rpcbuf_move(q_u->buffer, &r_u->buffer);
6391 return WERR_INVALID_PARAM; /* this is what a NT server
6392 returns for AddJob. AddJob
6393 must fail on non-local
6397 /****************************************************************************
6398 ****************************************************************************/
6400 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6401 int position, int snum,
6402 const NT_PRINTER_INFO_LEVEL *ntprinter)
6406 t=gmtime(&queue->time);
6408 job_info->jobid=queue->job;
6409 init_unistr(&job_info->printername, lp_servicename(snum));
6410 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6411 init_unistr(&job_info->username, queue->fs_user);
6412 init_unistr(&job_info->document, queue->fs_file);
6413 init_unistr(&job_info->datatype, "RAW");
6414 init_unistr(&job_info->text_status, "");
6415 job_info->status=nt_printj_status(queue->status);
6416 job_info->priority=queue->priority;
6417 job_info->position=position;
6418 job_info->totalpages=queue->page_count;
6419 job_info->pagesprinted=0;
6421 make_systemtime(&job_info->submitted, t);
6424 /****************************************************************************
6425 ****************************************************************************/
6427 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6428 int position, int snum,
6429 const NT_PRINTER_INFO_LEVEL *ntprinter,
6430 DEVICEMODE *devmode)
6434 t=gmtime(&queue->time);
6436 job_info->jobid=queue->job;
6438 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6440 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6441 init_unistr(&job_info->username, queue->fs_user);
6442 init_unistr(&job_info->document, queue->fs_file);
6443 init_unistr(&job_info->notifyname, queue->fs_user);
6444 init_unistr(&job_info->datatype, "RAW");
6445 init_unistr(&job_info->printprocessor, "winprint");
6446 init_unistr(&job_info->parameters, "");
6447 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6448 init_unistr(&job_info->text_status, "");
6450 /* and here the security descriptor */
6452 job_info->status=nt_printj_status(queue->status);
6453 job_info->priority=queue->priority;
6454 job_info->position=position;
6455 job_info->starttime=0;
6456 job_info->untiltime=0;
6457 job_info->totalpages=queue->page_count;
6458 job_info->size=queue->size;
6459 make_systemtime(&(job_info->submitted), t);
6460 job_info->timeelapsed=0;
6461 job_info->pagesprinted=0;
6463 job_info->devmode = devmode;
6468 /****************************************************************************
6469 Enumjobs at level 1.
6470 ****************************************************************************/
6472 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6473 const NT_PRINTER_INFO_LEVEL *ntprinter,
6474 RPC_BUFFER *buffer, uint32 offered,
6475 uint32 *needed, uint32 *returned)
6479 WERROR result = WERR_OK;
6481 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6487 for (i=0; i<*returned; i++)
6488 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6490 /* check the required size. */
6491 for (i=0; i<*returned; i++)
6492 (*needed) += spoolss_size_job_info_1(&info[i]);
6494 if (*needed > offered) {
6495 result = WERR_INSUFFICIENT_BUFFER;
6499 if (!rpcbuf_alloc_size(buffer, *needed)) {
6500 result = WERR_NOMEM;
6504 /* fill the buffer with the structures */
6505 for (i=0; i<*returned; i++)
6506 smb_io_job_info_1("", buffer, &info[i], 0);
6512 if ( !W_ERROR_IS_OK(result) )
6518 /****************************************************************************
6519 Enumjobs at level 2.
6520 ****************************************************************************/
6522 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6523 const NT_PRINTER_INFO_LEVEL *ntprinter,
6524 RPC_BUFFER *buffer, uint32 offered,
6525 uint32 *needed, uint32 *returned)
6527 JOB_INFO_2 *info = NULL;
6529 WERROR result = WERR_OK;
6530 DEVICEMODE *devmode = NULL;
6532 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6537 /* this should not be a failure condition if the devmode is NULL */
6539 devmode = construct_dev_mode(lp_const_servicename(snum));
6541 for (i=0; i<*returned; i++)
6542 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6544 /* check the required size. */
6545 for (i=0; i<*returned; i++)
6546 (*needed) += spoolss_size_job_info_2(&info[i]);
6548 if (*needed > offered) {
6549 result = WERR_INSUFFICIENT_BUFFER;
6553 if (!rpcbuf_alloc_size(buffer, *needed)) {
6554 result = WERR_NOMEM;
6558 /* fill the buffer with the structures */
6559 for (i=0; i<*returned; i++)
6560 smb_io_job_info_2("", buffer, &info[i], 0);
6563 free_devmode(devmode);
6566 if ( !W_ERROR_IS_OK(result) )
6573 /****************************************************************************
6575 ****************************************************************************/
6577 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6579 POLICY_HND *handle = &q_u->handle;
6580 uint32 level = q_u->level;
6581 RPC_BUFFER *buffer = NULL;
6582 uint32 offered = q_u->offered;
6583 uint32 *needed = &r_u->needed;
6584 uint32 *returned = &r_u->returned;
6586 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6588 print_status_struct prt_status;
6589 print_queue_struct *queue=NULL;
6591 /* that's an [in out] buffer */
6593 if (!q_u->buffer && (offered!=0)) {
6594 return WERR_INVALID_PARAM;
6597 rpcbuf_move(q_u->buffer, &r_u->buffer);
6598 buffer = r_u->buffer;
6600 DEBUG(4,("_spoolss_enumjobs\n"));
6605 /* lookup the printer snum and tdb entry */
6607 if (!get_printer_snum(p, handle, &snum))
6610 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6611 if ( !W_ERROR_IS_OK(wret) )
6614 *returned = print_queue_status(snum, &queue, &prt_status);
6615 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6617 if (*returned == 0) {
6619 free_a_printer(&ntprinter, 2);
6625 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6628 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6632 wret = WERR_UNKNOWN_LEVEL;
6637 free_a_printer( &ntprinter, 2 );
6641 /****************************************************************************
6642 ****************************************************************************/
6644 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6649 /****************************************************************************
6650 ****************************************************************************/
6652 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6654 POLICY_HND *handle = &q_u->handle;
6655 uint32 jobid = q_u->jobid;
6656 uint32 command = q_u->command;
6659 WERROR errcode = WERR_BADFUNC;
6661 if (!get_printer_snum(p, handle, &snum)) {
6665 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6666 return WERR_INVALID_PRINTER_NAME;
6670 case JOB_CONTROL_CANCEL:
6671 case JOB_CONTROL_DELETE:
6672 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6676 case JOB_CONTROL_PAUSE:
6677 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6681 case JOB_CONTROL_RESTART:
6682 case JOB_CONTROL_RESUME:
6683 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6688 return WERR_UNKNOWN_LEVEL;
6694 /****************************************************************************
6695 Enumerates all printer drivers at level 1.
6696 ****************************************************************************/
6698 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6703 fstring *list = NULL;
6704 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6705 DRIVER_INFO_1 *driver_info_1=NULL;
6706 WERROR result = WERR_OK;
6710 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6712 ndrivers=get_ntdrivers(&list, architecture, version);
6713 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6715 if(ndrivers == -1) {
6716 SAFE_FREE(driver_info_1);
6721 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6722 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6728 for (i=0; i<ndrivers; i++) {
6730 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6731 ZERO_STRUCT(driver);
6732 status = get_a_printer_driver(&driver, 3, list[i],
6733 architecture, version);
6734 if (!W_ERROR_IS_OK(status)) {
6736 SAFE_FREE(driver_info_1);
6739 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6740 free_a_printer_driver(driver, 3);
6743 *returned+=ndrivers;
6747 /* check the required size. */
6748 for (i=0; i<*returned; i++) {
6749 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6750 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6753 if (*needed > offered) {
6754 result = WERR_INSUFFICIENT_BUFFER;
6758 if (!rpcbuf_alloc_size(buffer, *needed)) {
6759 result = WERR_NOMEM;
6763 /* fill the buffer with the driver structures */
6764 for (i=0; i<*returned; i++) {
6765 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6766 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6770 SAFE_FREE(driver_info_1);
6772 if ( !W_ERROR_IS_OK(result) )
6778 /****************************************************************************
6779 Enumerates all printer drivers at level 2.
6780 ****************************************************************************/
6782 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6787 fstring *list = NULL;
6788 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6789 DRIVER_INFO_2 *driver_info_2=NULL;
6790 WERROR result = WERR_OK;
6794 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6796 ndrivers=get_ntdrivers(&list, architecture, version);
6797 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6799 if(ndrivers == -1) {
6800 SAFE_FREE(driver_info_2);
6805 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6806 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6812 for (i=0; i<ndrivers; i++) {
6815 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6816 ZERO_STRUCT(driver);
6817 status = get_a_printer_driver(&driver, 3, list[i],
6818 architecture, version);
6819 if (!W_ERROR_IS_OK(status)) {
6821 SAFE_FREE(driver_info_2);
6824 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6825 free_a_printer_driver(driver, 3);
6828 *returned+=ndrivers;
6832 /* check the required size. */
6833 for (i=0; i<*returned; i++) {
6834 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6835 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6838 if (*needed > offered) {
6839 result = WERR_INSUFFICIENT_BUFFER;
6843 if (!rpcbuf_alloc_size(buffer, *needed)) {
6844 result = WERR_NOMEM;
6848 /* fill the buffer with the form structures */
6849 for (i=0; i<*returned; i++) {
6850 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6851 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6855 SAFE_FREE(driver_info_2);
6857 if ( !W_ERROR_IS_OK(result) )
6863 /****************************************************************************
6864 Enumerates all printer drivers at level 3.
6865 ****************************************************************************/
6867 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6872 fstring *list = NULL;
6873 DRIVER_INFO_3 *driver_info_3=NULL;
6874 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6875 WERROR result = WERR_OK;
6879 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6881 ndrivers=get_ntdrivers(&list, architecture, version);
6882 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6884 if(ndrivers == -1) {
6885 SAFE_FREE(driver_info_3);
6890 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6891 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6897 for (i=0; i<ndrivers; i++) {
6900 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6901 ZERO_STRUCT(driver);
6902 status = get_a_printer_driver(&driver, 3, list[i],
6903 architecture, version);
6904 if (!W_ERROR_IS_OK(status)) {
6906 SAFE_FREE(driver_info_3);
6909 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6910 free_a_printer_driver(driver, 3);
6913 *returned+=ndrivers;
6917 /* check the required size. */
6918 for (i=0; i<*returned; i++) {
6919 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6920 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6923 if (*needed > offered) {
6924 result = WERR_INSUFFICIENT_BUFFER;
6928 if (!rpcbuf_alloc_size(buffer, *needed)) {
6929 result = WERR_NOMEM;
6933 /* fill the buffer with the driver structures */
6934 for (i=0; i<*returned; i++) {
6935 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6936 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6940 for (i=0; i<*returned; i++) {
6941 SAFE_FREE(driver_info_3[i].dependentfiles);
6944 SAFE_FREE(driver_info_3);
6946 if ( !W_ERROR_IS_OK(result) )
6952 /****************************************************************************
6953 Enumerates all printer drivers.
6954 ****************************************************************************/
6956 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6958 uint32 level = q_u->level;
6959 RPC_BUFFER *buffer = NULL;
6960 uint32 offered = q_u->offered;
6961 uint32 *needed = &r_u->needed;
6962 uint32 *returned = &r_u->returned;
6965 fstring architecture;
6967 /* that's an [in out] buffer */
6969 if (!q_u->buffer && (offered!=0)) {
6970 return WERR_INVALID_PARAM;
6973 rpcbuf_move(q_u->buffer, &r_u->buffer);
6974 buffer = r_u->buffer;
6976 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6981 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6982 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6984 if ( !is_myname_or_ipaddr( servername ) )
6985 return WERR_UNKNOWN_PRINTER_DRIVER;
6989 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6991 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6993 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6995 return WERR_UNKNOWN_LEVEL;
6999 /****************************************************************************
7000 ****************************************************************************/
7002 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7004 form->flag=list->flag;
7005 init_unistr(&form->name, list->name);
7006 form->width=list->width;
7007 form->length=list->length;
7008 form->left=list->left;
7009 form->top=list->top;
7010 form->right=list->right;
7011 form->bottom=list->bottom;
7014 /****************************************************************************
7015 ****************************************************************************/
7017 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7019 uint32 level = q_u->level;
7020 RPC_BUFFER *buffer = NULL;
7021 uint32 offered = q_u->offered;
7022 uint32 *needed = &r_u->needed;
7023 uint32 *numofforms = &r_u->numofforms;
7024 uint32 numbuiltinforms;
7026 nt_forms_struct *list=NULL;
7027 nt_forms_struct *builtinlist=NULL;
7032 /* that's an [in out] buffer */
7034 if (!q_u->buffer && (offered!=0) ) {
7035 return WERR_INVALID_PARAM;
7038 rpcbuf_move(q_u->buffer, &r_u->buffer);
7039 buffer = r_u->buffer;
7041 DEBUG(4,("_spoolss_enumforms\n"));
7042 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7043 DEBUGADD(5,("Info level [%d]\n", level));
7045 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7046 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7047 *numofforms = get_ntforms(&list);
7048 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7049 *numofforms += numbuiltinforms;
7051 if (*numofforms == 0) {
7052 SAFE_FREE(builtinlist);
7054 return WERR_NO_MORE_ITEMS;
7059 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7060 SAFE_FREE(builtinlist);
7066 /* construct the list of form structures */
7067 for (i=0; i<numbuiltinforms; i++) {
7068 DEBUGADD(6,("Filling form number [%d]\n",i));
7069 fill_form_1(&forms_1[i], &builtinlist[i]);
7072 SAFE_FREE(builtinlist);
7074 for (; i<*numofforms; i++) {
7075 DEBUGADD(6,("Filling form number [%d]\n",i));
7076 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7081 /* check the required size. */
7082 for (i=0; i<numbuiltinforms; i++) {
7083 DEBUGADD(6,("adding form [%d]'s size\n",i));
7084 buffer_size += spoolss_size_form_1(&forms_1[i]);
7086 for (; i<*numofforms; i++) {
7087 DEBUGADD(6,("adding form [%d]'s size\n",i));
7088 buffer_size += spoolss_size_form_1(&forms_1[i]);
7091 *needed=buffer_size;
7093 if (*needed > offered) {
7096 return WERR_INSUFFICIENT_BUFFER;
7099 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7105 /* fill the buffer with the form structures */
7106 for (i=0; i<numbuiltinforms; i++) {
7107 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7108 smb_io_form_1("", buffer, &forms_1[i], 0);
7110 for (; i<*numofforms; i++) {
7111 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7112 smb_io_form_1("", buffer, &forms_1[i], 0);
7121 SAFE_FREE(builtinlist);
7122 return WERR_UNKNOWN_LEVEL;
7126 /****************************************************************************
7127 ****************************************************************************/
7129 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7131 uint32 level = q_u->level;
7132 UNISTR2 *uni_formname = &q_u->formname;
7133 RPC_BUFFER *buffer = NULL;
7134 uint32 offered = q_u->offered;
7135 uint32 *needed = &r_u->needed;
7137 nt_forms_struct *list=NULL;
7138 nt_forms_struct builtin_form;
7143 int numofforms=0, i=0;
7145 /* that's an [in out] buffer */
7147 if (!q_u->buffer && (offered!=0)) {
7148 return WERR_INVALID_PARAM;
7151 rpcbuf_move(q_u->buffer, &r_u->buffer);
7152 buffer = r_u->buffer;
7154 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7156 DEBUG(4,("_spoolss_getform\n"));
7157 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7158 DEBUGADD(5,("Info level [%d]\n", level));
7160 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7161 if (!foundBuiltin) {
7162 numofforms = get_ntforms(&list);
7163 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7165 if (numofforms == 0)
7172 fill_form_1(&form_1, &builtin_form);
7175 /* Check if the requested name is in the list of form structures */
7176 for (i=0; i<numofforms; i++) {
7178 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7180 if (strequal(form_name, list[i].name)) {
7181 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7182 fill_form_1(&form_1, &list[i]);
7188 if (i == numofforms) {
7192 /* check the required size. */
7194 *needed=spoolss_size_form_1(&form_1);
7196 if (*needed > offered)
7197 return WERR_INSUFFICIENT_BUFFER;
7199 if (!rpcbuf_alloc_size(buffer, buffer_size))
7202 /* fill the buffer with the form structures */
7203 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7204 smb_io_form_1("", buffer, &form_1, 0);
7210 return WERR_UNKNOWN_LEVEL;
7214 /****************************************************************************
7215 ****************************************************************************/
7217 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7219 init_unistr(&port->port_name, name);
7222 /****************************************************************************
7223 TODO: This probably needs distinguish between TCP/IP and Local ports
7225 ****************************************************************************/
7227 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7229 init_unistr(&port->port_name, name);
7230 init_unistr(&port->monitor_name, "Local Monitor");
7231 init_unistr(&port->description, SPL_LOCAL_PORT );
7232 port->port_type=PORT_TYPE_WRITE;
7237 /****************************************************************************
7238 wrapper around the enumer ports command
7239 ****************************************************************************/
7241 WERROR enumports_hook( int *count, char ***lines )
7243 char *cmd = lp_enumports_cmd();
7253 /* if no hook then just fill in the default port */
7256 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7257 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7262 /* we have a valid enumport command */
7264 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7266 DEBUG(10,("Running [%s]\n", command));
7267 ret = smbrun(command, &fd);
7268 DEBUG(10,("Returned [%d]\n", ret));
7273 return WERR_ACCESS_DENIED;
7277 qlines = fd_lines_load(fd, &numlines, 0);
7278 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7288 /****************************************************************************
7290 ****************************************************************************/
7292 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7294 PORT_INFO_1 *ports=NULL;
7296 WERROR result = WERR_OK;
7297 char **qlines = NULL;
7300 result = enumports_hook( &numlines, &qlines );
7301 if (!W_ERROR_IS_OK(result)) {
7302 file_lines_free(qlines);
7307 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7308 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7309 dos_errstr(WERR_NOMEM)));
7310 file_lines_free(qlines);
7314 for (i=0; i<numlines; i++) {
7315 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7316 fill_port_1(&ports[i], qlines[i]);
7319 file_lines_free(qlines);
7321 *returned = numlines;
7323 /* check the required size. */
7324 for (i=0; i<*returned; i++) {
7325 DEBUGADD(6,("adding port [%d]'s size\n", i));
7326 *needed += spoolss_size_port_info_1(&ports[i]);
7329 if (*needed > offered) {
7330 result = WERR_INSUFFICIENT_BUFFER;
7334 if (!rpcbuf_alloc_size(buffer, *needed)) {
7335 result = WERR_NOMEM;
7339 /* fill the buffer with the ports structures */
7340 for (i=0; i<*returned; i++) {
7341 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7342 smb_io_port_1("", buffer, &ports[i], 0);
7348 if ( !W_ERROR_IS_OK(result) )
7354 /****************************************************************************
7356 ****************************************************************************/
7358 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7360 PORT_INFO_2 *ports=NULL;
7362 WERROR result = WERR_OK;
7363 char **qlines = NULL;
7366 result = enumports_hook( &numlines, &qlines );
7367 if ( !W_ERROR_IS_OK(result)) {
7368 file_lines_free(qlines);
7373 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7374 file_lines_free(qlines);
7378 for (i=0; i<numlines; i++) {
7379 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7380 fill_port_2(&(ports[i]), qlines[i]);
7384 file_lines_free(qlines);
7386 *returned = numlines;
7388 /* check the required size. */
7389 for (i=0; i<*returned; i++) {
7390 DEBUGADD(6,("adding port [%d]'s size\n", i));
7391 *needed += spoolss_size_port_info_2(&ports[i]);
7394 if (*needed > offered) {
7395 result = WERR_INSUFFICIENT_BUFFER;
7399 if (!rpcbuf_alloc_size(buffer, *needed)) {
7400 result = WERR_NOMEM;
7404 /* fill the buffer with the ports structures */
7405 for (i=0; i<*returned; i++) {
7406 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7407 smb_io_port_2("", buffer, &ports[i], 0);
7413 if ( !W_ERROR_IS_OK(result) )
7419 /****************************************************************************
7421 ****************************************************************************/
7423 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7425 uint32 level = q_u->level;
7426 RPC_BUFFER *buffer = NULL;
7427 uint32 offered = q_u->offered;
7428 uint32 *needed = &r_u->needed;
7429 uint32 *returned = &r_u->returned;
7431 /* that's an [in out] buffer */
7433 if (!q_u->buffer && (offered!=0)) {
7434 return WERR_INVALID_PARAM;
7437 rpcbuf_move(q_u->buffer, &r_u->buffer);
7438 buffer = r_u->buffer;
7440 DEBUG(4,("_spoolss_enumports\n"));
7447 return enumports_level_1(buffer, offered, needed, returned);
7449 return enumports_level_2(buffer, offered, needed, returned);
7451 return WERR_UNKNOWN_LEVEL;
7455 /****************************************************************************
7456 ****************************************************************************/
7458 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7459 const SPOOL_PRINTER_INFO_LEVEL *info,
7460 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7461 uint32 user_switch, const SPOOL_USER_CTR *user,
7464 NT_PRINTER_INFO_LEVEL *printer = NULL;
7467 WERROR err = WERR_OK;
7469 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7470 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7474 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7475 if (!convert_printer_info(info, printer, 2)) {
7476 free_a_printer(&printer, 2);
7480 /* check to see if the printer already exists */
7482 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7483 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7484 printer->info_2->sharename));
7485 free_a_printer(&printer, 2);
7486 return WERR_PRINTER_ALREADY_EXISTS;
7489 /* FIXME!!! smbd should check to see if the driver is installed before
7490 trying to add a printer like this --jerry */
7492 if (*lp_addprinter_cmd() ) {
7493 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7494 free_a_printer(&printer,2);
7495 return WERR_ACCESS_DENIED;
7498 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7499 "smb.conf parameter \"addprinter command\" is defined. This"
7500 "parameter must exist for this call to succeed\n",
7501 printer->info_2->sharename ));
7504 /* use our primary netbios name since get_a_printer() will convert
7505 it to what the client expects on a case by case basis */
7507 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7508 printer->info_2->sharename);
7511 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7512 free_a_printer(&printer,2);
7513 return WERR_ACCESS_DENIED;
7516 /* you must be a printer admin to add a new printer */
7517 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7518 free_a_printer(&printer,2);
7519 return WERR_ACCESS_DENIED;
7523 * Do sanity check on the requested changes for Samba.
7526 if (!check_printer_ok(printer->info_2, snum)) {
7527 free_a_printer(&printer,2);
7528 return WERR_INVALID_PARAM;
7532 * When a printer is created, the drivername bound to the printer is used
7533 * to lookup previously saved driver initialization info, which is then
7534 * bound to the new printer, simulating what happens in the Windows arch.
7539 set_driver_init(printer, 2);
7543 /* A valid devmode was included, convert and link it
7545 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7547 if (!convert_devicemode(printer->info_2->printername, devmode,
7548 &printer->info_2->devmode))
7552 /* write the ASCII on disk */
7553 err = mod_a_printer(printer, 2);
7554 if (!W_ERROR_IS_OK(err)) {
7555 free_a_printer(&printer,2);
7559 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7560 /* Handle open failed - remove addition. */
7561 del_a_printer(printer->info_2->sharename);
7562 free_a_printer(&printer,2);
7563 return WERR_ACCESS_DENIED;
7566 update_c_setprinter(False);
7567 free_a_printer(&printer,2);
7572 /****************************************************************************
7573 ****************************************************************************/
7575 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7577 UNISTR2 *uni_srv_name = q_u->server_name;
7578 uint32 level = q_u->level;
7579 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7580 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7581 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7582 uint32 user_switch = q_u->user_switch;
7583 SPOOL_USER_CTR *user = &q_u->user_ctr;
7584 POLICY_HND *handle = &r_u->handle;
7588 /* we don't handle yet */
7589 /* but I know what to do ... */
7590 return WERR_UNKNOWN_LEVEL;
7592 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7594 user_switch, user, handle);
7596 return WERR_UNKNOWN_LEVEL;
7600 /****************************************************************************
7601 ****************************************************************************/
7603 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7605 uint32 level = q_u->level;
7606 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7607 WERROR err = WERR_OK;
7608 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7609 fstring driver_name;
7612 ZERO_STRUCT(driver);
7614 if (!convert_printer_driver_info(info, &driver, level)) {
7619 DEBUG(5,("Cleaning driver's information\n"));
7620 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7621 if (!W_ERROR_IS_OK(err))
7624 DEBUG(5,("Moving driver to final destination\n"));
7625 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7629 if (add_a_printer_driver(driver, level)!=0) {
7630 err = WERR_ACCESS_DENIED;
7635 * I think this is where he DrvUpgradePrinter() hook would be
7636 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7637 * server. Right now, we just need to send ourselves a message
7638 * to update each printer bound to this driver. --jerry
7641 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7642 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7647 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7648 * decide if the driver init data should be deleted. The rules are:
7649 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7650 * 2) delete init data only if there is no 2k/Xp driver
7651 * 3) always delete init data
7652 * The generalized rule is always use init data from the highest order driver.
7653 * It is necessary to follow the driver install by an initialization step to
7654 * finish off this process.
7657 version = driver.info_3->cversion;
7658 else if (level == 6)
7659 version = driver.info_6->version;
7664 * 9x printer driver - never delete init data
7667 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7672 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7673 * there is no 2k/Xp driver init data for this driver name.
7677 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7679 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7681 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7683 if (!del_driver_init(driver_name))
7684 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7687 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7689 free_a_printer_driver(driver1,3);
7690 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7697 * 2k or Xp printer driver - always delete init data
7700 if (!del_driver_init(driver_name))
7701 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7705 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7711 free_a_printer_driver(driver, level);
7715 /********************************************************************
7716 * spoolss_addprinterdriverex
7717 ********************************************************************/
7719 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7721 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7722 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7725 * we only support the semantics of AddPrinterDriver()
7726 * i.e. only copy files that are newer than existing ones
7729 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7730 return WERR_ACCESS_DENIED;
7732 ZERO_STRUCT(q_u_local);
7733 ZERO_STRUCT(r_u_local);
7735 /* just pass the information off to _spoolss_addprinterdriver() */
7736 q_u_local.server_name_ptr = q_u->server_name_ptr;
7737 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7738 q_u_local.level = q_u->level;
7739 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7741 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7744 /****************************************************************************
7745 ****************************************************************************/
7747 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7749 init_unistr(&info->name, name);
7752 /****************************************************************************
7753 ****************************************************************************/
7755 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7761 const char *short_archi;
7762 DRIVER_DIRECTORY_1 *info=NULL;
7763 WERROR result = WERR_OK;
7765 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7766 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7768 /* check for beginning double '\'s and that the server
7771 pservername = servername;
7772 if ( *pservername == '\\' && strlen(servername)>2 ) {
7776 if ( !is_myname_or_ipaddr( pservername ) )
7777 return WERR_INVALID_PARAM;
7779 if (!(short_archi = get_short_archi(long_archi)))
7780 return WERR_INVALID_ENVIRONMENT;
7782 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7785 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7787 DEBUG(4,("printer driver directory: [%s]\n", path));
7789 fill_driverdir_1(info, path);
7791 *needed += spoolss_size_driverdir_info_1(info);
7793 if (*needed > offered) {
7794 result = WERR_INSUFFICIENT_BUFFER;
7798 if (!rpcbuf_alloc_size(buffer, *needed)) {
7799 result = WERR_NOMEM;
7803 smb_io_driverdir_1("", buffer, info, 0);
7811 /****************************************************************************
7812 ****************************************************************************/
7814 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7816 UNISTR2 *name = &q_u->name;
7817 UNISTR2 *uni_environment = &q_u->environment;
7818 uint32 level = q_u->level;
7819 RPC_BUFFER *buffer = NULL;
7820 uint32 offered = q_u->offered;
7821 uint32 *needed = &r_u->needed;
7823 /* that's an [in out] buffer */
7825 if (!q_u->buffer && (offered!=0)) {
7826 return WERR_INVALID_PARAM;
7829 rpcbuf_move(q_u->buffer, &r_u->buffer);
7830 buffer = r_u->buffer;
7832 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7838 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7840 return WERR_UNKNOWN_LEVEL;
7844 /****************************************************************************
7845 ****************************************************************************/
7847 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7849 POLICY_HND *handle = &q_u->handle;
7850 uint32 idx = q_u->index;
7851 uint32 in_value_len = q_u->valuesize;
7852 uint32 in_data_len = q_u->datasize;
7853 uint32 *out_max_value_len = &r_u->valuesize;
7854 uint16 **out_value = &r_u->value;
7855 uint32 *out_value_len = &r_u->realvaluesize;
7856 uint32 *out_type = &r_u->type;
7857 uint32 *out_max_data_len = &r_u->datasize;
7858 uint8 **data_out = &r_u->data;
7859 uint32 *out_data_len = &r_u->realdatasize;
7861 NT_PRINTER_INFO_LEVEL *printer = NULL;
7863 uint32 biggest_valuesize;
7864 uint32 biggest_datasize;
7866 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7869 REGISTRY_VALUE *val = NULL;
7870 NT_PRINTER_DATA *p_data;
7871 int i, key_index, num_values;
7876 *out_max_data_len = 0;
7880 DEBUG(5,("spoolss_enumprinterdata\n"));
7883 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7887 if (!get_printer_snum(p,handle, &snum))
7890 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7891 if (!W_ERROR_IS_OK(result))
7894 p_data = printer->info_2->data;
7895 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7900 * The NT machine wants to know the biggest size of value and data
7902 * cf: MSDN EnumPrinterData remark section
7905 if ( !in_value_len && !in_data_len && (key_index != -1) )
7907 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7909 biggest_valuesize = 0;
7910 biggest_datasize = 0;
7912 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7914 for ( i=0; i<num_values; i++ )
7916 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7918 name_length = strlen(val->valuename);
7919 if ( strlen(val->valuename) > biggest_valuesize )
7920 biggest_valuesize = name_length;
7922 if ( val->size > biggest_datasize )
7923 biggest_datasize = val->size;
7925 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7929 /* the value is an UNICODE string but real_value_size is the length
7930 in bytes including the trailing 0 */
7932 *out_value_len = 2 * (1+biggest_valuesize);
7933 *out_data_len = biggest_datasize;
7935 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7941 * the value len is wrong in NT sp3
7942 * that's the number of bytes not the number of unicode chars
7945 if ( key_index != -1 )
7946 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7951 /* out_value should default to "" or else NT4 has
7952 problems unmarshalling the response */
7954 *out_max_value_len=(in_value_len/sizeof(uint16));
7956 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7958 result = WERR_NOMEM;
7962 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7964 /* the data is counted in bytes */
7966 *out_max_data_len = in_data_len;
7967 *out_data_len = in_data_len;
7969 /* only allocate when given a non-zero data_len */
7971 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7973 result = WERR_NOMEM;
7977 result = WERR_NO_MORE_ITEMS;
7983 * - counted in bytes in the request
7984 * - counted in UNICODE chars in the max reply
7985 * - counted in bytes in the real size
7987 * take a pause *before* coding not *during* coding
7991 *out_max_value_len=(in_value_len/sizeof(uint16));
7992 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7994 result = WERR_NOMEM;
7998 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8002 *out_type = regval_type( val );
8004 /* data - counted in bytes */
8006 *out_max_data_len = in_data_len;
8007 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8009 result = WERR_NOMEM;
8012 data_len = regval_size(val);
8014 memcpy( *data_out, regval_data_p(val), data_len );
8015 *out_data_len = data_len;
8019 free_a_printer(&printer, 2);
8023 /****************************************************************************
8024 ****************************************************************************/
8026 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8028 POLICY_HND *handle = &q_u->handle;
8029 UNISTR2 *value = &q_u->value;
8030 uint32 type = q_u->type;
8031 uint8 *data = q_u->data;
8032 uint32 real_len = q_u->real_len;
8034 NT_PRINTER_INFO_LEVEL *printer = NULL;
8036 WERROR status = WERR_OK;
8037 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8040 DEBUG(5,("spoolss_setprinterdata\n"));
8043 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8047 if ( Printer->printer_type == SPLHND_SERVER ) {
8048 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8049 return WERR_INVALID_PARAM;
8052 if (!get_printer_snum(p,handle, &snum))
8056 * Access check : NT returns "access denied" if you make a
8057 * SetPrinterData call without the necessary privildge.
8058 * we were originally returning OK if nothing changed
8059 * which made Win2k issue **a lot** of SetPrinterData
8060 * when connecting to a printer --jerry
8063 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8065 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8066 status = WERR_ACCESS_DENIED;
8070 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8071 if (!W_ERROR_IS_OK(status))
8074 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8077 * When client side code sets a magic printer data key, detect it and save
8078 * the current printer data and the magic key's data (its the DEVMODE) for
8079 * future printer/driver initializations.
8081 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8083 /* Set devmode and printer initialization info */
8084 status = save_driver_init( printer, 2, data, real_len );
8086 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8090 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8091 type, data, real_len );
8092 if ( W_ERROR_IS_OK(status) )
8093 status = mod_a_printer(printer, 2);
8097 free_a_printer(&printer, 2);
8102 /****************************************************************************
8103 ****************************************************************************/
8105 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8107 POLICY_HND *handle = &q_u->handle;
8108 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8111 DEBUG(5,("_spoolss_resetprinter\n"));
8114 * All we do is to check to see if the handle and queue is valid.
8115 * This call really doesn't mean anything to us because we only
8116 * support RAW printing. --jerry
8120 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8124 if (!get_printer_snum(p,handle, &snum))
8128 /* blindly return success */
8133 /****************************************************************************
8134 ****************************************************************************/
8136 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8138 POLICY_HND *handle = &q_u->handle;
8139 UNISTR2 *value = &q_u->valuename;
8141 NT_PRINTER_INFO_LEVEL *printer = NULL;
8143 WERROR status = WERR_OK;
8144 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8147 DEBUG(5,("spoolss_deleteprinterdata\n"));
8150 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8154 if (!get_printer_snum(p, handle, &snum))
8157 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8158 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8159 return WERR_ACCESS_DENIED;
8162 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8163 if (!W_ERROR_IS_OK(status))
8166 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8168 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8170 if ( W_ERROR_IS_OK(status) )
8171 mod_a_printer( printer, 2 );
8173 free_a_printer(&printer, 2);
8178 /****************************************************************************
8179 ****************************************************************************/
8181 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8183 POLICY_HND *handle = &q_u->handle;
8184 FORM *form = &q_u->form;
8185 nt_forms_struct tmpForm;
8187 WERROR status = WERR_OK;
8188 NT_PRINTER_INFO_LEVEL *printer = NULL;
8191 nt_forms_struct *list=NULL;
8192 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8194 DEBUG(5,("spoolss_addform\n"));
8197 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8202 /* forms can be added on printer of on the print server handle */
8204 if ( Printer->printer_type == SPLHND_PRINTER )
8206 if (!get_printer_snum(p,handle, &snum))
8209 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8210 if (!W_ERROR_IS_OK(status))
8214 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8215 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8216 status = WERR_ACCESS_DENIED;
8220 /* can't add if builtin */
8222 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8223 status = WERR_ALREADY_EXISTS;
8227 count = get_ntforms(&list);
8229 if(!add_a_form(&list, form, &count)) {
8230 status = WERR_NOMEM;
8234 write_ntforms(&list, count);
8237 * ChangeID must always be set if this is a printer
8240 if ( Printer->printer_type == SPLHND_PRINTER )
8241 status = mod_a_printer(printer, 2);
8245 free_a_printer(&printer, 2);
8251 /****************************************************************************
8252 ****************************************************************************/
8254 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8256 POLICY_HND *handle = &q_u->handle;
8257 UNISTR2 *form_name = &q_u->name;
8258 nt_forms_struct tmpForm;
8260 nt_forms_struct *list=NULL;
8261 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8263 WERROR status = WERR_OK;
8264 NT_PRINTER_INFO_LEVEL *printer = NULL;
8266 DEBUG(5,("spoolss_deleteform\n"));
8269 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8273 /* forms can be deleted on printer of on the print server handle */
8275 if ( Printer->printer_type == SPLHND_PRINTER )
8277 if (!get_printer_snum(p,handle, &snum))
8280 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8281 if (!W_ERROR_IS_OK(status))
8285 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8286 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8287 status = WERR_ACCESS_DENIED;
8291 /* can't delete if builtin */
8293 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8294 status = WERR_INVALID_PARAM;
8298 count = get_ntforms(&list);
8300 if ( !delete_a_form(&list, form_name, &count, &status ))
8304 * ChangeID must always be set if this is a printer
8307 if ( Printer->printer_type == SPLHND_PRINTER )
8308 status = mod_a_printer(printer, 2);
8312 free_a_printer(&printer, 2);
8318 /****************************************************************************
8319 ****************************************************************************/
8321 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8323 POLICY_HND *handle = &q_u->handle;
8324 FORM *form = &q_u->form;
8325 nt_forms_struct tmpForm;
8327 WERROR status = WERR_OK;
8328 NT_PRINTER_INFO_LEVEL *printer = NULL;
8331 nt_forms_struct *list=NULL;
8332 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8334 DEBUG(5,("spoolss_setform\n"));
8337 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8341 /* forms can be modified on printer of on the print server handle */
8343 if ( Printer->printer_type == SPLHND_PRINTER )
8345 if (!get_printer_snum(p,handle, &snum))
8348 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8349 if (!W_ERROR_IS_OK(status))
8353 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8354 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8355 status = WERR_ACCESS_DENIED;
8359 /* can't set if builtin */
8360 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8361 status = WERR_INVALID_PARAM;
8365 count = get_ntforms(&list);
8366 update_a_form(&list, form, count);
8367 write_ntforms(&list, count);
8370 * ChangeID must always be set if this is a printer
8373 if ( Printer->printer_type == SPLHND_PRINTER )
8374 status = mod_a_printer(printer, 2);
8379 free_a_printer(&printer, 2);
8385 /****************************************************************************
8386 enumprintprocessors level 1.
8387 ****************************************************************************/
8389 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8391 PRINTPROCESSOR_1 *info_1=NULL;
8392 WERROR result = WERR_OK;
8394 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8399 init_unistr(&info_1->name, "winprint");
8401 *needed += spoolss_size_printprocessor_info_1(info_1);
8403 if (*needed > offered) {
8404 result = WERR_INSUFFICIENT_BUFFER;
8408 if (!rpcbuf_alloc_size(buffer, *needed)) {
8409 result = WERR_NOMEM;
8413 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8418 if ( !W_ERROR_IS_OK(result) )
8424 /****************************************************************************
8425 ****************************************************************************/
8427 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8429 uint32 level = q_u->level;
8430 RPC_BUFFER *buffer = NULL;
8431 uint32 offered = q_u->offered;
8432 uint32 *needed = &r_u->needed;
8433 uint32 *returned = &r_u->returned;
8435 /* that's an [in out] buffer */
8437 if (!q_u->buffer && (offered!=0)) {
8438 return WERR_INVALID_PARAM;
8441 rpcbuf_move(q_u->buffer, &r_u->buffer);
8442 buffer = r_u->buffer;
8444 DEBUG(5,("spoolss_enumprintprocessors\n"));
8447 * Enumerate the print processors ...
8449 * Just reply with "winprint", to keep NT happy
8450 * and I can use my nice printer checker.
8458 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8460 return WERR_UNKNOWN_LEVEL;
8464 /****************************************************************************
8465 enumprintprocdatatypes level 1.
8466 ****************************************************************************/
8468 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8470 PRINTPROCDATATYPE_1 *info_1=NULL;
8471 WERROR result = WERR_NOMEM;
8473 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8478 init_unistr(&info_1->name, "RAW");
8480 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8482 if (*needed > offered) {
8483 result = WERR_INSUFFICIENT_BUFFER;
8487 if (!rpcbuf_alloc_size(buffer, *needed)) {
8488 result = WERR_NOMEM;
8492 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8497 if ( !W_ERROR_IS_OK(result) )
8503 /****************************************************************************
8504 ****************************************************************************/
8506 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8508 uint32 level = q_u->level;
8509 RPC_BUFFER *buffer = NULL;
8510 uint32 offered = q_u->offered;
8511 uint32 *needed = &r_u->needed;
8512 uint32 *returned = &r_u->returned;
8514 /* that's an [in out] buffer */
8516 if (!q_u->buffer && (offered!=0)) {
8517 return WERR_INVALID_PARAM;
8520 rpcbuf_move(q_u->buffer, &r_u->buffer);
8521 buffer = r_u->buffer;
8523 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8530 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8532 return WERR_UNKNOWN_LEVEL;
8536 /****************************************************************************
8537 enumprintmonitors level 1.
8538 ****************************************************************************/
8540 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8542 PRINTMONITOR_1 *info_1;
8543 WERROR result = WERR_OK;
8546 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8551 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8552 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8554 for ( i=0; i<*returned; i++ ) {
8555 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8558 if (*needed > offered) {
8559 result = WERR_INSUFFICIENT_BUFFER;
8563 if (!rpcbuf_alloc_size(buffer, *needed)) {
8564 result = WERR_NOMEM;
8568 for ( i=0; i<*returned; i++ ) {
8569 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8575 if ( !W_ERROR_IS_OK(result) )
8581 /****************************************************************************
8582 enumprintmonitors level 2.
8583 ****************************************************************************/
8585 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8587 PRINTMONITOR_2 *info_2;
8588 WERROR result = WERR_OK;
8591 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8596 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8597 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8598 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8600 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8601 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8602 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8604 for ( i=0; i<*returned; i++ ) {
8605 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8608 if (*needed > offered) {
8609 result = WERR_INSUFFICIENT_BUFFER;
8613 if (!rpcbuf_alloc_size(buffer, *needed)) {
8614 result = WERR_NOMEM;
8618 for ( i=0; i<*returned; i++ ) {
8619 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8625 if ( !W_ERROR_IS_OK(result) )
8631 /****************************************************************************
8632 ****************************************************************************/
8634 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8636 uint32 level = q_u->level;
8637 RPC_BUFFER *buffer = NULL;
8638 uint32 offered = q_u->offered;
8639 uint32 *needed = &r_u->needed;
8640 uint32 *returned = &r_u->returned;
8642 /* that's an [in out] buffer */
8644 if (!q_u->buffer && (offered!=0)) {
8645 return WERR_INVALID_PARAM;
8648 rpcbuf_move(q_u->buffer, &r_u->buffer);
8649 buffer = r_u->buffer;
8651 DEBUG(5,("spoolss_enumprintmonitors\n"));
8654 * Enumerate the print monitors ...
8656 * Just reply with "Local Port", to keep NT happy
8657 * and I can use my nice printer checker.
8665 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8667 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8669 return WERR_UNKNOWN_LEVEL;
8673 /****************************************************************************
8674 ****************************************************************************/
8676 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8677 NT_PRINTER_INFO_LEVEL *ntprinter,
8678 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8683 JOB_INFO_1 *info_1=NULL;
8684 WERROR result = WERR_OK;
8686 info_1=SMB_MALLOC_P(JOB_INFO_1);
8688 if (info_1 == NULL) {
8692 for (i=0; i<count && found==False; i++) {
8693 if ((*queue)[i].job==(int)jobid)
8699 /* NT treats not found as bad param... yet another bad choice */
8700 return WERR_INVALID_PARAM;
8703 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8705 *needed += spoolss_size_job_info_1(info_1);
8707 if (*needed > offered) {
8708 result = WERR_INSUFFICIENT_BUFFER;
8712 if (!rpcbuf_alloc_size(buffer, *needed)) {
8713 result = WERR_NOMEM;
8717 smb_io_job_info_1("", buffer, info_1, 0);
8725 /****************************************************************************
8726 ****************************************************************************/
8728 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8729 NT_PRINTER_INFO_LEVEL *ntprinter,
8730 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8737 DEVICEMODE *devmode = NULL;
8738 NT_DEVICEMODE *nt_devmode = NULL;
8740 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8743 ZERO_STRUCTP(info_2);
8745 for ( i=0; i<count && found==False; i++ )
8747 if ((*queue)[i].job == (int)jobid)
8752 /* NT treats not found as bad param... yet another bad
8754 result = WERR_INVALID_PARAM;
8759 * if the print job does not have a DEVMODE associated with it,
8760 * just use the one for the printer. A NULL devicemode is not
8761 * a failure condition
8764 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8765 devmode = construct_dev_mode(lp_const_servicename(snum));
8767 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8768 ZERO_STRUCTP( devmode );
8769 convert_nt_devicemode( devmode, nt_devmode );
8773 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8775 *needed += spoolss_size_job_info_2(info_2);
8777 if (*needed > offered) {
8778 result = WERR_INSUFFICIENT_BUFFER;
8782 if (!rpcbuf_alloc_size(buffer, *needed)) {
8783 result = WERR_NOMEM;
8787 smb_io_job_info_2("", buffer, info_2, 0);
8792 /* Cleanup allocated memory */
8794 free_job_info_2(info_2); /* Also frees devmode */
8800 /****************************************************************************
8801 ****************************************************************************/
8803 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8805 POLICY_HND *handle = &q_u->handle;
8806 uint32 jobid = q_u->jobid;
8807 uint32 level = q_u->level;
8808 RPC_BUFFER *buffer = NULL;
8809 uint32 offered = q_u->offered;
8810 uint32 *needed = &r_u->needed;
8811 WERROR wstatus = WERR_OK;
8812 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8815 print_queue_struct *queue = NULL;
8816 print_status_struct prt_status;
8818 /* that's an [in out] buffer */
8820 if (!q_u->buffer && (offered!=0)) {
8821 return WERR_INVALID_PARAM;
8824 rpcbuf_move(q_u->buffer, &r_u->buffer);
8825 buffer = r_u->buffer;
8827 DEBUG(5,("spoolss_getjob\n"));
8831 if (!get_printer_snum(p, handle, &snum))
8834 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8835 if ( !W_ERROR_IS_OK(wstatus) )
8838 count = print_queue_status(snum, &queue, &prt_status);
8840 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8841 count, prt_status.status, prt_status.message));
8845 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8846 buffer, offered, needed);
8849 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8850 buffer, offered, needed);
8853 wstatus = WERR_UNKNOWN_LEVEL;
8858 free_a_printer( &ntprinter, 2 );
8863 /********************************************************************
8864 spoolss_getprinterdataex
8866 From MSDN documentation of GetPrinterDataEx: pass request
8867 to GetPrinterData if key is "PrinterDriverData".
8868 ********************************************************************/
8870 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8872 POLICY_HND *handle = &q_u->handle;
8873 uint32 in_size = q_u->size;
8874 uint32 *type = &r_u->type;
8875 uint32 *out_size = &r_u->size;
8876 uint8 **data = &r_u->data;
8877 uint32 *needed = &r_u->needed;
8878 fstring keyname, valuename;
8880 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8882 NT_PRINTER_INFO_LEVEL *printer = NULL;
8884 WERROR status = WERR_OK;
8886 DEBUG(4,("_spoolss_getprinterdataex\n"));
8888 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8889 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8891 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8892 keyname, valuename));
8894 /* in case of problem, return some default values */
8898 *out_size = in_size;
8901 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8902 status = WERR_BADFID;
8906 /* Is the handle to a printer or to the server? */
8908 if (Printer->printer_type == SPLHND_SERVER) {
8909 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8910 status = WERR_INVALID_PARAM;
8914 if ( !get_printer_snum(p,handle, &snum) )
8917 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8918 if ( !W_ERROR_IS_OK(status) )
8921 /* check to see if the keyname is valid */
8922 if ( !strlen(keyname) ) {
8923 status = WERR_INVALID_PARAM;
8927 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8928 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8929 free_a_printer( &printer, 2 );
8930 status = WERR_BADFILE;
8934 /* When given a new keyname, we should just create it */
8936 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8938 if (*needed > *out_size)
8939 status = WERR_MORE_DATA;
8942 if ( !W_ERROR_IS_OK(status) )
8944 DEBUG(5, ("error: allocating %d\n", *out_size));
8946 /* reply this param doesn't exist */
8950 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8951 status = WERR_NOMEM;
8961 free_a_printer( &printer, 2 );
8966 /********************************************************************
8967 * spoolss_setprinterdataex
8968 ********************************************************************/
8970 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8972 POLICY_HND *handle = &q_u->handle;
8973 uint32 type = q_u->type;
8974 uint8 *data = q_u->data;
8975 uint32 real_len = q_u->real_len;
8977 NT_PRINTER_INFO_LEVEL *printer = NULL;
8979 WERROR status = WERR_OK;
8980 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8985 DEBUG(4,("_spoolss_setprinterdataex\n"));
8987 /* From MSDN documentation of SetPrinterDataEx: pass request to
8988 SetPrinterData if key is "PrinterDriverData" */
8991 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8995 if ( Printer->printer_type == SPLHND_SERVER ) {
8996 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8997 return WERR_INVALID_PARAM;
9000 if ( !get_printer_snum(p,handle, &snum) )
9004 * Access check : NT returns "access denied" if you make a
9005 * SetPrinterData call without the necessary privildge.
9006 * we were originally returning OK if nothing changed
9007 * which made Win2k issue **a lot** of SetPrinterData
9008 * when connecting to a printer --jerry
9011 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9013 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9014 return WERR_ACCESS_DENIED;
9017 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9018 if (!W_ERROR_IS_OK(status))
9021 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9022 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9024 /* check for OID in valuename */
9026 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9032 /* save the registry data */
9034 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9036 if ( W_ERROR_IS_OK(status) )
9038 /* save the OID if one was specified */
9040 fstrcat( keyname, "\\" );
9041 fstrcat( keyname, SPOOL_OID_KEY );
9044 * I'm not checking the status here on purpose. Don't know
9045 * if this is right, but I'm returning the status from the
9046 * previous set_printer_dataex() call. I have no idea if
9047 * this is right. --jerry
9050 set_printer_dataex( printer, keyname, valuename,
9051 REG_SZ, (uint8 *)oid_string,
9052 strlen(oid_string)+1 );
9055 status = mod_a_printer(printer, 2);
9058 free_a_printer(&printer, 2);
9064 /********************************************************************
9065 * spoolss_deleteprinterdataex
9066 ********************************************************************/
9068 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9070 POLICY_HND *handle = &q_u->handle;
9071 UNISTR2 *value = &q_u->valuename;
9072 UNISTR2 *key = &q_u->keyname;
9074 NT_PRINTER_INFO_LEVEL *printer = NULL;
9076 WERROR status = WERR_OK;
9077 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9078 pstring valuename, keyname;
9080 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9083 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9087 if (!get_printer_snum(p, handle, &snum))
9090 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9091 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9092 return WERR_ACCESS_DENIED;
9095 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9096 if (!W_ERROR_IS_OK(status))
9099 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9100 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9102 status = delete_printer_dataex( printer, keyname, valuename );
9104 if ( W_ERROR_IS_OK(status) )
9105 mod_a_printer( printer, 2 );
9107 free_a_printer(&printer, 2);
9112 /********************************************************************
9113 * spoolss_enumprinterkey
9114 ********************************************************************/
9117 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9120 fstring *keynames = NULL;
9121 uint16 *enumkeys = NULL;
9124 POLICY_HND *handle = &q_u->handle;
9125 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9126 NT_PRINTER_DATA *data;
9127 NT_PRINTER_INFO_LEVEL *printer = NULL;
9129 WERROR status = WERR_BADFILE;
9132 DEBUG(4,("_spoolss_enumprinterkey\n"));
9135 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9139 if ( !get_printer_snum(p,handle, &snum) )
9142 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9143 if (!W_ERROR_IS_OK(status))
9146 /* get the list of subkey names */
9148 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9149 data = printer->info_2->data;
9151 num_keys = get_printer_subkeys( data, key, &keynames );
9153 if ( num_keys == -1 ) {
9154 status = WERR_BADFILE;
9158 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9160 r_u->needed = printerkey_len*2;
9162 if ( q_u->size < r_u->needed ) {
9163 status = WERR_MORE_DATA;
9167 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9168 status = WERR_NOMEM;
9174 if ( q_u->size < r_u->needed )
9175 status = WERR_MORE_DATA;
9178 free_a_printer( &printer, 2 );
9179 SAFE_FREE( keynames );
9184 /********************************************************************
9185 * spoolss_deleteprinterkey
9186 ********************************************************************/
9188 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9190 POLICY_HND *handle = &q_u->handle;
9191 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9193 NT_PRINTER_INFO_LEVEL *printer = NULL;
9197 DEBUG(5,("spoolss_deleteprinterkey\n"));
9200 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9204 /* if keyname == NULL, return error */
9206 if ( !q_u->keyname.buffer )
9207 return WERR_INVALID_PARAM;
9209 if (!get_printer_snum(p, handle, &snum))
9212 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9213 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9214 return WERR_ACCESS_DENIED;
9217 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9218 if (!W_ERROR_IS_OK(status))
9221 /* delete the key and all subneys */
9223 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9225 status = delete_all_printer_data( printer->info_2, key );
9227 if ( W_ERROR_IS_OK(status) )
9228 status = mod_a_printer(printer, 2);
9230 free_a_printer( &printer, 2 );
9236 /********************************************************************
9237 * spoolss_enumprinterdataex
9238 ********************************************************************/
9240 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9242 POLICY_HND *handle = &q_u->handle;
9243 uint32 in_size = q_u->size;
9246 NT_PRINTER_INFO_LEVEL *printer = NULL;
9247 PRINTER_ENUM_VALUES *enum_values = NULL;
9248 NT_PRINTER_DATA *p_data;
9250 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9255 REGISTRY_VALUE *val;
9260 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9263 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9268 * first check for a keyname of NULL or "". Win2k seems to send
9269 * this a lot and we should send back WERR_INVALID_PARAM
9270 * no need to spend time looking up the printer in this case.
9274 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9275 if ( !strlen(key) ) {
9276 result = WERR_INVALID_PARAM;
9280 /* get the printer off of disk */
9282 if (!get_printer_snum(p,handle, &snum))
9285 ZERO_STRUCT(printer);
9286 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9287 if (!W_ERROR_IS_OK(result))
9290 /* now look for a match on the key name */
9292 p_data = printer->info_2->data;
9294 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9295 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9297 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9298 result = WERR_INVALID_PARAM;
9305 /* allocate the memory for the array of pointers -- if necessary */
9307 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9310 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9312 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9313 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9314 result = WERR_NOMEM;
9318 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9322 * loop through all params and build the array to pass
9323 * back to the client
9326 for ( i=0; i<num_entries; i++ )
9328 /* lookup the registry value */
9330 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9331 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9335 value_name = regval_name( val );
9336 init_unistr( &enum_values[i].valuename, value_name );
9337 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9338 enum_values[i].type = regval_type( val );
9340 data_len = regval_size( val );
9342 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9344 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9346 result = WERR_NOMEM;
9350 enum_values[i].data_len = data_len;
9352 /* keep track of the size of the array in bytes */
9354 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9357 /* housekeeping information in the reply */
9359 r_u->needed = needed;
9360 r_u->returned = num_entries;
9362 if (needed > in_size) {
9363 result = WERR_MORE_DATA;
9367 /* copy data into the reply */
9369 r_u->ctr.size = r_u->needed;
9370 r_u->ctr.size_of_array = r_u->returned;
9371 r_u->ctr.values = enum_values;
9377 free_a_printer(&printer, 2);
9382 /****************************************************************************
9383 ****************************************************************************/
9385 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9387 init_unistr(&info->name, name);
9390 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9391 UNISTR2 *environment,
9398 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9399 WERROR result = WERR_OK;
9401 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9403 if (!get_short_archi(long_archi))
9404 return WERR_INVALID_ENVIRONMENT;
9406 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9409 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9411 fill_printprocessordirectory_1(info, path);
9413 *needed += spoolss_size_printprocessordirectory_info_1(info);
9415 if (*needed > offered) {
9416 result = WERR_INSUFFICIENT_BUFFER;
9420 if (!rpcbuf_alloc_size(buffer, *needed)) {
9421 result = WERR_INSUFFICIENT_BUFFER;
9425 smb_io_printprocessordirectory_1("", buffer, info, 0);
9433 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9435 uint32 level = q_u->level;
9436 RPC_BUFFER *buffer = NULL;
9437 uint32 offered = q_u->offered;
9438 uint32 *needed = &r_u->needed;
9441 /* that's an [in out] buffer */
9443 if (!q_u->buffer && (offered!=0)) {
9444 return WERR_INVALID_PARAM;
9447 rpcbuf_move(q_u->buffer, &r_u->buffer);
9448 buffer = r_u->buffer;
9450 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9456 result = getprintprocessordirectory_level_1
9457 (&q_u->name, &q_u->environment, buffer, offered, needed);
9460 result = WERR_UNKNOWN_LEVEL;
9466 /*******************************************************************
9467 Streams the monitor UI DLL name in UNICODE
9468 *******************************************************************/
9470 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9471 RPC_BUFFER *out, uint32 *needed )
9473 const char *dllname = "tcpmonui.dll";
9475 *needed = (strlen(dllname)+1) * 2;
9477 if ( rpcbuf_get_size(out) < *needed ) {
9478 return WERR_INSUFFICIENT_BUFFER;
9481 if ( !make_monitorui_buf( out, dllname ) ) {
9488 /*******************************************************************
9489 Create a new TCP/IP port
9490 *******************************************************************/
9492 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9493 RPC_BUFFER *out, uint32 *needed )
9495 NT_PORT_DATA_1 port1;
9498 ZERO_STRUCT( port1 );
9500 /* convert to our internal port data structure */
9502 if ( !convert_port_data_1( &port1, in ) ) {
9506 /* create the device URI and call the add_port_hook() */
9508 switch ( port1.protocol ) {
9509 case PORT_PROTOCOL_DIRECT:
9510 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9513 case PORT_PROTOCOL_LPR:
9514 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9518 return WERR_UNKNOWN_PORT;
9521 return add_port_hook( token, port1.name, device_uri );
9524 /*******************************************************************
9525 *******************************************************************/
9527 struct xcv_api_table xcvtcp_cmds[] = {
9528 { "MonitorUI", xcvtcp_monitorui },
9529 { "AddPort", xcvtcp_addport},
9533 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9534 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9539 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9541 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9542 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9543 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9546 return WERR_BADFUNC;
9549 /*******************************************************************
9550 *******************************************************************/
9551 #if 0 /* don't support management using the "Local Port" monitor */
9553 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9554 RPC_BUFFER *out, uint32 *needed )
9556 const char *dllname = "localui.dll";
9558 *needed = (strlen(dllname)+1) * 2;
9560 if ( rpcbuf_get_size(out) < *needed ) {
9561 return WERR_INSUFFICIENT_BUFFER;
9564 if ( !make_monitorui_buf( out, dllname )) {
9571 /*******************************************************************
9572 *******************************************************************/
9574 struct xcv_api_table xcvlocal_cmds[] = {
9575 { "MonitorUI", xcvlocal_monitorui },
9579 struct xcv_api_table xcvlocal_cmds[] = {
9586 /*******************************************************************
9587 *******************************************************************/
9589 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9590 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9595 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9597 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9598 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9599 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9601 return WERR_BADFUNC;
9604 /*******************************************************************
9605 *******************************************************************/
9607 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9609 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9613 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9617 /* Has to be a handle to the TCP/IP port monitor */
9619 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9620 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9624 /* requires administrative access to the server */
9626 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9627 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9628 return WERR_ACCESS_DENIED;
9631 /* Get the command name. There's numerous commands supported by the
9632 TCPMON interface. */
9634 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9635 q_u->dataname.uni_str_len*2, 0);
9637 /* Allocate the outgoing buffer */
9639 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9641 switch ( Printer->printer_type ) {
9642 case SPLHND_PORTMON_TCP:
9643 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9644 &q_u->indata, &r_u->outdata, &r_u->needed );
9645 case SPLHND_PORTMON_LOCAL:
9646 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9647 &q_u->indata, &r_u->outdata, &r_u->needed );
9650 return WERR_INVALID_PRINT_MONITOR;