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.low=0;
5291 info->driver_date.high=0;
5294 info->driver_version_low=0;
5295 info->driver_version_high=0;
5297 init_unistr( &info->mfgname, "");
5298 init_unistr( &info->oem_url, "");
5299 init_unistr( &info->hardware_id, "");
5300 init_unistr( &info->provider, "");
5303 /********************************************************************
5304 * construct_printer_info_6
5305 * fill a printer_info_6 struct
5306 ********************************************************************/
5308 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5309 fstring servername, fstring architecture, uint32 version)
5311 NT_PRINTER_INFO_LEVEL *printer = NULL;
5312 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5315 ZERO_STRUCT(driver);
5317 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5319 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5321 if (!W_ERROR_IS_OK(status))
5322 return WERR_INVALID_PRINTER_NAME;
5324 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5326 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5328 if (!W_ERROR_IS_OK(status))
5331 * Is this a W2k client ?
5335 free_a_printer(&printer,2);
5336 return WERR_UNKNOWN_PRINTER_DRIVER;
5339 /* Yes - try again with a WinNT driver. */
5341 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5342 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5343 if (!W_ERROR_IS_OK(status)) {
5344 free_a_printer(&printer,2);
5345 return WERR_UNKNOWN_PRINTER_DRIVER;
5349 fill_printer_driver_info_6(info, driver, servername);
5351 free_a_printer(&printer,2);
5352 free_a_printer_driver(driver, 3);
5357 /****************************************************************************
5358 ****************************************************************************/
5360 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5362 SAFE_FREE(info->dependentfiles);
5365 /****************************************************************************
5366 ****************************************************************************/
5368 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5370 SAFE_FREE(info->dependentfiles);
5373 /****************************************************************************
5374 ****************************************************************************/
5376 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5378 DRIVER_INFO_1 *info=NULL;
5381 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5384 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5385 if (!W_ERROR_IS_OK(result))
5388 /* check the required size. */
5389 *needed += spoolss_size_printer_driver_info_1(info);
5391 if (*needed > offered) {
5392 result = WERR_INSUFFICIENT_BUFFER;
5396 if (!rpcbuf_alloc_size(buffer, *needed)) {
5397 result = WERR_NOMEM;
5401 /* fill the buffer with the structures */
5402 smb_io_printer_driver_info_1("", buffer, info, 0);
5411 /****************************************************************************
5412 ****************************************************************************/
5414 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5416 DRIVER_INFO_2 *info=NULL;
5419 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5422 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5423 if (!W_ERROR_IS_OK(result))
5426 /* check the required size. */
5427 *needed += spoolss_size_printer_driver_info_2(info);
5429 if (*needed > offered) {
5430 result = WERR_INSUFFICIENT_BUFFER;
5434 if (!rpcbuf_alloc_size(buffer, *needed)) {
5435 result = WERR_NOMEM;
5439 /* fill the buffer with the structures */
5440 smb_io_printer_driver_info_2("", buffer, info, 0);
5449 /****************************************************************************
5450 ****************************************************************************/
5452 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5459 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5460 if (!W_ERROR_IS_OK(result))
5463 /* check the required size. */
5464 *needed += spoolss_size_printer_driver_info_3(&info);
5466 if (*needed > offered) {
5467 result = WERR_INSUFFICIENT_BUFFER;
5471 if (!rpcbuf_alloc_size(buffer, *needed)) {
5472 result = WERR_NOMEM;
5476 /* fill the buffer with the structures */
5477 smb_io_printer_driver_info_3("", buffer, &info, 0);
5480 free_printer_driver_info_3(&info);
5485 /****************************************************************************
5486 ****************************************************************************/
5488 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5495 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5496 if (!W_ERROR_IS_OK(result))
5499 /* check the required size. */
5500 *needed += spoolss_size_printer_driver_info_6(&info);
5502 if (*needed > offered) {
5503 result = WERR_INSUFFICIENT_BUFFER;
5507 if (!rpcbuf_alloc_size(buffer, *needed)) {
5508 result = WERR_NOMEM;
5512 /* fill the buffer with the structures */
5513 smb_io_printer_driver_info_6("", buffer, &info, 0);
5516 free_printer_driver_info_6(&info);
5521 /****************************************************************************
5522 ****************************************************************************/
5524 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5526 POLICY_HND *handle = &q_u->handle;
5527 UNISTR2 *uni_arch = &q_u->architecture;
5528 uint32 level = q_u->level;
5529 uint32 clientmajorversion = q_u->clientmajorversion;
5530 RPC_BUFFER *buffer = NULL;
5531 uint32 offered = q_u->offered;
5532 uint32 *needed = &r_u->needed;
5533 uint32 *servermajorversion = &r_u->servermajorversion;
5534 uint32 *serverminorversion = &r_u->serverminorversion;
5535 Printer_entry *printer;
5538 fstring architecture;
5541 /* that's an [in out] buffer */
5543 if (!q_u->buffer && (offered!=0)) {
5544 return WERR_INVALID_PARAM;
5547 rpcbuf_move(q_u->buffer, &r_u->buffer);
5548 buffer = r_u->buffer;
5550 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5552 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5553 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5554 return WERR_INVALID_PRINTER_NAME;
5558 *servermajorversion = 0;
5559 *serverminorversion = 0;
5561 fstrcpy(servername, get_server_name( printer ));
5562 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5564 if (!get_printer_snum(p, handle, &snum))
5569 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5571 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5573 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5575 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5578 /* apparently this call is the equivalent of
5579 EnumPrinterDataEx() for the DsDriver key */
5584 return WERR_UNKNOWN_LEVEL;
5587 /****************************************************************************
5588 ****************************************************************************/
5590 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5592 POLICY_HND *handle = &q_u->handle;
5594 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5597 DEBUG(3,("Error in startpageprinter printer handle\n"));
5601 Printer->page_started=True;
5605 /****************************************************************************
5606 ****************************************************************************/
5608 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5610 POLICY_HND *handle = &q_u->handle;
5613 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5616 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5620 if (!get_printer_snum(p, handle, &snum))
5623 Printer->page_started=False;
5624 print_job_endpage(snum, Printer->jobid);
5629 /********************************************************************
5630 * api_spoolss_getprinter
5631 * called from the spoolss dispatcher
5633 ********************************************************************/
5635 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5637 POLICY_HND *handle = &q_u->handle;
5638 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5639 uint32 *jobid = &r_u->jobid;
5641 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5645 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5648 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5653 * a nice thing with NT is it doesn't listen to what you tell it.
5654 * when asked to send _only_ RAW datas, it tries to send datas
5657 * So I add checks like in NT Server ...
5660 if (info_1->p_datatype != 0) {
5661 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5662 if (strcmp(datatype, "RAW") != 0) {
5664 return WERR_INVALID_DATATYPE;
5668 /* get the share number of the printer */
5669 if (!get_printer_snum(p, handle, &snum)) {
5673 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5675 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5677 /* An error occured in print_job_start() so return an appropriate
5680 if (Printer->jobid == -1) {
5681 return map_werror_from_unix(errno);
5684 Printer->document_started=True;
5685 (*jobid) = Printer->jobid;
5690 /********************************************************************
5691 * api_spoolss_getprinter
5692 * called from the spoolss dispatcher
5694 ********************************************************************/
5696 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5698 POLICY_HND *handle = &q_u->handle;
5700 return _spoolss_enddocprinter_internal(p, handle);
5703 /****************************************************************************
5704 ****************************************************************************/
5706 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5708 POLICY_HND *handle = &q_u->handle;
5709 uint32 buffer_size = q_u->buffer_size;
5710 uint8 *buffer = q_u->buffer;
5711 uint32 *buffer_written = &q_u->buffer_size2;
5713 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5716 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5717 r_u->buffer_written = q_u->buffer_size2;
5721 if (!get_printer_snum(p, handle, &snum))
5724 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5725 (SMB_OFF_T)-1, (size_t)buffer_size);
5726 if (*buffer_written == (uint32)-1) {
5727 r_u->buffer_written = 0;
5728 if (errno == ENOSPC)
5729 return WERR_NO_SPOOL_SPACE;
5731 return WERR_ACCESS_DENIED;
5734 r_u->buffer_written = q_u->buffer_size2;
5739 /********************************************************************
5740 * api_spoolss_getprinter
5741 * called from the spoolss dispatcher
5743 ********************************************************************/
5745 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5749 WERROR errcode = WERR_BADFUNC;
5750 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5753 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5757 if (!get_printer_snum(p, handle, &snum))
5761 case PRINTER_CONTROL_PAUSE:
5762 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5766 case PRINTER_CONTROL_RESUME:
5767 case PRINTER_CONTROL_UNPAUSE:
5768 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5772 case PRINTER_CONTROL_PURGE:
5773 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5778 return WERR_UNKNOWN_LEVEL;
5784 /********************************************************************
5785 * api_spoolss_abortprinter
5786 * From MSDN: "Deletes printer's spool file if printer is configured
5788 ********************************************************************/
5790 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5792 POLICY_HND *handle = &q_u->handle;
5793 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5795 WERROR errcode = WERR_OK;
5798 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5802 if (!get_printer_snum(p, handle, &snum))
5805 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5810 /********************************************************************
5811 * called by spoolss_api_setprinter
5812 * when updating a printer description
5813 ********************************************************************/
5815 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5816 const SPOOL_PRINTER_INFO_LEVEL *info,
5817 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5819 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5823 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5825 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5826 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5827 OUR_HANDLE(handle)));
5829 result = WERR_BADFID;
5833 /* Check the user has permissions to change the security
5834 descriptor. By experimentation with two NT machines, the user
5835 requires Full Access to the printer to change security
5838 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5839 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5840 result = WERR_ACCESS_DENIED;
5844 /* NT seems to like setting the security descriptor even though
5845 nothing may have actually changed. */
5847 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5849 if (DEBUGLEVEL >= 10) {
5853 the_acl = old_secdesc_ctr->sec->dacl;
5854 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5855 PRINTERNAME(snum), the_acl->num_aces));
5857 for (i = 0; i < the_acl->num_aces; i++) {
5860 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5862 DEBUG(10, ("%s 0x%08x\n", sid_str,
5863 the_acl->ace[i].info.mask));
5866 the_acl = secdesc_ctr->sec->dacl;
5869 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5870 PRINTERNAME(snum), the_acl->num_aces));
5872 for (i = 0; i < the_acl->num_aces; i++) {
5875 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5877 DEBUG(10, ("%s 0x%08x\n", sid_str,
5878 the_acl->ace[i].info.mask));
5881 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5885 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5886 if (!new_secdesc_ctr) {
5887 result = WERR_NOMEM;
5891 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5896 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5903 /********************************************************************
5904 Canonicalize printer info from a client
5906 ATTN: It does not matter what we set the servername to hear
5907 since we do the necessary work in get_a_printer() to set it to
5908 the correct value based on what the client sent in the
5909 _spoolss_open_printer_ex().
5910 ********************************************************************/
5912 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5914 fstring printername;
5917 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5918 "portname=%s drivername=%s comment=%s location=%s\n",
5919 info->servername, info->printername, info->sharename,
5920 info->portname, info->drivername, info->comment, info->location));
5922 /* we force some elements to "correct" values */
5923 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5924 fstrcpy(info->sharename, lp_servicename(snum));
5926 /* check to see if we allow printername != sharename */
5928 if ( lp_force_printername(snum) ) {
5929 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5930 global_myname(), info->sharename );
5933 /* make sure printername is in \\server\printername format */
5935 fstrcpy( printername, info->printername );
5937 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5938 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5942 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5943 global_myname(), p );
5946 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5947 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5954 /****************************************************************************
5955 ****************************************************************************/
5957 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5959 char *cmd = lp_addport_cmd();
5963 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5964 BOOL is_print_op = False;
5967 return WERR_ACCESS_DENIED;
5970 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5973 is_print_op = user_has_privileges( token, &se_printop );
5975 DEBUG(10,("Running [%s]\n", command));
5977 /********* BEGIN SePrintOperatorPrivilege **********/
5982 ret = smbrun(command, &fd);
5987 /********* END SePrintOperatorPrivilege **********/
5989 DEBUGADD(10,("returned [%d]\n", ret));
5994 return WERR_ACCESS_DENIED;
6000 /****************************************************************************
6001 ****************************************************************************/
6003 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6005 char *cmd = lp_addprinter_cmd();
6011 fstring remote_machine = "%m";
6012 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6013 BOOL is_print_op = False;
6015 standard_sub_basic(current_user_info.smb_name,
6016 current_user_info.domain,
6017 remote_machine,sizeof(remote_machine));
6019 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6020 cmd, printer->info_2->printername, printer->info_2->sharename,
6021 printer->info_2->portname, printer->info_2->drivername,
6022 printer->info_2->location, printer->info_2->comment, remote_machine);
6025 is_print_op = user_has_privileges( token, &se_printop );
6027 DEBUG(10,("Running [%s]\n", command));
6029 /********* BEGIN SePrintOperatorPrivilege **********/
6034 if ( (ret = smbrun(command, &fd)) == 0 ) {
6035 /* Tell everyone we updated smb.conf. */
6036 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6042 /********* END SePrintOperatorPrivilege **********/
6044 DEBUGADD(10,("returned [%d]\n", ret));
6052 /* reload our services immediately */
6053 reload_services( False );
6056 /* Get lines and convert them back to dos-codepage */
6057 qlines = fd_lines_load(fd, &numlines, 0);
6058 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6061 /* Set the portname to what the script says the portname should be. */
6062 /* but don't require anything to be return from the script exit a good error code */
6065 /* Set the portname to what the script says the portname should be. */
6066 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6067 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6070 file_lines_free(qlines);
6075 /********************************************************************
6076 * Called by spoolss_api_setprinter
6077 * when updating a printer description.
6078 ********************************************************************/
6080 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6081 const SPOOL_PRINTER_INFO_LEVEL *info,
6082 DEVICEMODE *devmode)
6085 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6086 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6091 DEBUG(8,("update_printer\n"));
6096 result = WERR_BADFID;
6100 if (!get_printer_snum(p, handle, &snum)) {
6101 result = WERR_BADFID;
6105 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6106 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6107 result = WERR_BADFID;
6111 DEBUGADD(8,("Converting info_2 struct\n"));
6114 * convert_printer_info converts the incoming
6115 * info from the client and overwrites the info
6116 * just read from the tdb in the pointer 'printer'.
6119 if (!convert_printer_info(info, printer, level)) {
6120 result = WERR_NOMEM;
6125 /* we have a valid devmode
6126 convert it and link it*/
6128 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6129 if (!convert_devicemode(printer->info_2->printername, devmode,
6130 &printer->info_2->devmode)) {
6131 result = WERR_NOMEM;
6136 /* Do sanity check on the requested changes for Samba */
6138 if (!check_printer_ok(printer->info_2, snum)) {
6139 result = WERR_INVALID_PARAM;
6143 /* FIXME!!! If the driver has changed we really should verify that
6144 it is installed before doing much else --jerry */
6146 /* Check calling user has permission to update printer description */
6148 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6149 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6150 result = WERR_ACCESS_DENIED;
6154 /* Call addprinter hook */
6155 /* Check changes to see if this is really needed */
6157 if ( *lp_addprinter_cmd()
6158 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6159 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6160 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6161 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6163 /* add_printer_hook() will call reload_services() */
6165 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6166 result = WERR_ACCESS_DENIED;
6172 * When a *new* driver is bound to a printer, the drivername is used to
6173 * lookup previously saved driver initialization info, which is then
6174 * bound to the printer, simulating what happens in the Windows arch.
6176 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6178 if (!set_driver_init(printer, 2))
6180 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6181 printer->info_2->drivername));
6184 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6185 printer->info_2->drivername));
6187 notify_printer_driver(snum, printer->info_2->drivername);
6191 * flag which changes actually occured. This is a small subset of
6192 * all the possible changes. We also have to update things in the
6196 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6197 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6198 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6199 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6201 notify_printer_comment(snum, printer->info_2->comment);
6204 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6205 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6206 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6207 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6209 notify_printer_sharename(snum, printer->info_2->sharename);
6212 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6215 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6218 pname = printer->info_2->printername;
6221 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6222 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6223 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6225 notify_printer_printername( snum, pname );
6228 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6229 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6230 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6231 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6233 notify_printer_port(snum, printer->info_2->portname);
6236 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6237 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6238 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6239 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6241 notify_printer_location(snum, printer->info_2->location);
6244 /* here we need to update some more DsSpooler keys */
6245 /* uNCName, serverName, shortServerName */
6247 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6248 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6249 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6250 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6251 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6253 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6254 global_myname(), printer->info_2->sharename );
6255 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6256 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6257 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6259 /* Update printer info */
6260 result = mod_a_printer(printer, 2);
6263 free_a_printer(&printer, 2);
6264 free_a_printer(&old_printer, 2);
6270 /****************************************************************************
6271 ****************************************************************************/
6272 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6273 const SPOOL_PRINTER_INFO_LEVEL *info)
6276 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6278 Printer_entry *Printer;
6280 if ( lp_security() != SEC_ADS ) {
6281 return WERR_UNKNOWN_LEVEL;
6284 Printer = find_printer_index_by_hnd(p, handle);
6286 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6291 if (!get_printer_snum(p, handle, &snum))
6294 nt_printer_publish(Printer, snum, info7->action);
6298 return WERR_UNKNOWN_LEVEL;
6301 /****************************************************************************
6302 ****************************************************************************/
6304 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6306 POLICY_HND *handle = &q_u->handle;
6307 uint32 level = q_u->level;
6308 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6309 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6310 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6311 uint32 command = q_u->command;
6314 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6317 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6321 /* check the level */
6324 return control_printer(handle, command, p);
6326 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6327 if (!W_ERROR_IS_OK(result))
6330 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6333 return update_printer_sec(handle, level, info, p,
6336 return publish_or_unpublish_printer(p, handle, info);
6338 return WERR_UNKNOWN_LEVEL;
6342 /****************************************************************************
6343 ****************************************************************************/
6345 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6347 POLICY_HND *handle = &q_u->handle;
6348 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6351 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6355 if (Printer->notify.client_connected==True) {
6358 if ( Printer->printer_type == SPLHND_SERVER)
6360 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6361 !get_printer_snum(p, handle, &snum) )
6364 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6367 Printer->notify.flags=0;
6368 Printer->notify.options=0;
6369 Printer->notify.localmachine[0]='\0';
6370 Printer->notify.printerlocal=0;
6371 if (Printer->notify.option)
6372 free_spool_notify_option(&Printer->notify.option);
6373 Printer->notify.client_connected=False;
6378 /****************************************************************************
6379 ****************************************************************************/
6381 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6383 /* that's an [in out] buffer */
6385 if (!q_u->buffer && (q_u->offered!=0)) {
6386 return WERR_INVALID_PARAM;
6389 rpcbuf_move(q_u->buffer, &r_u->buffer);
6392 return WERR_INVALID_PARAM; /* this is what a NT server
6393 returns for AddJob. AddJob
6394 must fail on non-local
6398 /****************************************************************************
6399 ****************************************************************************/
6401 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6402 int position, int snum,
6403 const NT_PRINTER_INFO_LEVEL *ntprinter)
6407 t=gmtime(&queue->time);
6409 job_info->jobid=queue->job;
6410 init_unistr(&job_info->printername, lp_servicename(snum));
6411 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6412 init_unistr(&job_info->username, queue->fs_user);
6413 init_unistr(&job_info->document, queue->fs_file);
6414 init_unistr(&job_info->datatype, "RAW");
6415 init_unistr(&job_info->text_status, "");
6416 job_info->status=nt_printj_status(queue->status);
6417 job_info->priority=queue->priority;
6418 job_info->position=position;
6419 job_info->totalpages=queue->page_count;
6420 job_info->pagesprinted=0;
6422 make_systemtime(&job_info->submitted, t);
6425 /****************************************************************************
6426 ****************************************************************************/
6428 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6429 int position, int snum,
6430 const NT_PRINTER_INFO_LEVEL *ntprinter,
6431 DEVICEMODE *devmode)
6435 t=gmtime(&queue->time);
6437 job_info->jobid=queue->job;
6439 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6441 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6442 init_unistr(&job_info->username, queue->fs_user);
6443 init_unistr(&job_info->document, queue->fs_file);
6444 init_unistr(&job_info->notifyname, queue->fs_user);
6445 init_unistr(&job_info->datatype, "RAW");
6446 init_unistr(&job_info->printprocessor, "winprint");
6447 init_unistr(&job_info->parameters, "");
6448 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6449 init_unistr(&job_info->text_status, "");
6451 /* and here the security descriptor */
6453 job_info->status=nt_printj_status(queue->status);
6454 job_info->priority=queue->priority;
6455 job_info->position=position;
6456 job_info->starttime=0;
6457 job_info->untiltime=0;
6458 job_info->totalpages=queue->page_count;
6459 job_info->size=queue->size;
6460 make_systemtime(&(job_info->submitted), t);
6461 job_info->timeelapsed=0;
6462 job_info->pagesprinted=0;
6464 job_info->devmode = devmode;
6469 /****************************************************************************
6470 Enumjobs at level 1.
6471 ****************************************************************************/
6473 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6474 const NT_PRINTER_INFO_LEVEL *ntprinter,
6475 RPC_BUFFER *buffer, uint32 offered,
6476 uint32 *needed, uint32 *returned)
6480 WERROR result = WERR_OK;
6482 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6488 for (i=0; i<*returned; i++)
6489 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6491 /* check the required size. */
6492 for (i=0; i<*returned; i++)
6493 (*needed) += spoolss_size_job_info_1(&info[i]);
6495 if (*needed > offered) {
6496 result = WERR_INSUFFICIENT_BUFFER;
6500 if (!rpcbuf_alloc_size(buffer, *needed)) {
6501 result = WERR_NOMEM;
6505 /* fill the buffer with the structures */
6506 for (i=0; i<*returned; i++)
6507 smb_io_job_info_1("", buffer, &info[i], 0);
6513 if ( !W_ERROR_IS_OK(result) )
6519 /****************************************************************************
6520 Enumjobs at level 2.
6521 ****************************************************************************/
6523 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6524 const NT_PRINTER_INFO_LEVEL *ntprinter,
6525 RPC_BUFFER *buffer, uint32 offered,
6526 uint32 *needed, uint32 *returned)
6528 JOB_INFO_2 *info = NULL;
6530 WERROR result = WERR_OK;
6531 DEVICEMODE *devmode = NULL;
6533 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6538 /* this should not be a failure condition if the devmode is NULL */
6540 devmode = construct_dev_mode(lp_const_servicename(snum));
6542 for (i=0; i<*returned; i++)
6543 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6545 /* check the required size. */
6546 for (i=0; i<*returned; i++)
6547 (*needed) += spoolss_size_job_info_2(&info[i]);
6549 if (*needed > offered) {
6550 result = WERR_INSUFFICIENT_BUFFER;
6554 if (!rpcbuf_alloc_size(buffer, *needed)) {
6555 result = WERR_NOMEM;
6559 /* fill the buffer with the structures */
6560 for (i=0; i<*returned; i++)
6561 smb_io_job_info_2("", buffer, &info[i], 0);
6564 free_devmode(devmode);
6567 if ( !W_ERROR_IS_OK(result) )
6574 /****************************************************************************
6576 ****************************************************************************/
6578 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6580 POLICY_HND *handle = &q_u->handle;
6581 uint32 level = q_u->level;
6582 RPC_BUFFER *buffer = NULL;
6583 uint32 offered = q_u->offered;
6584 uint32 *needed = &r_u->needed;
6585 uint32 *returned = &r_u->returned;
6587 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6589 print_status_struct prt_status;
6590 print_queue_struct *queue=NULL;
6592 /* that's an [in out] buffer */
6594 if (!q_u->buffer && (offered!=0)) {
6595 return WERR_INVALID_PARAM;
6598 rpcbuf_move(q_u->buffer, &r_u->buffer);
6599 buffer = r_u->buffer;
6601 DEBUG(4,("_spoolss_enumjobs\n"));
6606 /* lookup the printer snum and tdb entry */
6608 if (!get_printer_snum(p, handle, &snum))
6611 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6612 if ( !W_ERROR_IS_OK(wret) )
6615 *returned = print_queue_status(snum, &queue, &prt_status);
6616 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6618 if (*returned == 0) {
6620 free_a_printer(&ntprinter, 2);
6626 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6629 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6633 wret = WERR_UNKNOWN_LEVEL;
6638 free_a_printer( &ntprinter, 2 );
6642 /****************************************************************************
6643 ****************************************************************************/
6645 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6650 /****************************************************************************
6651 ****************************************************************************/
6653 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6655 POLICY_HND *handle = &q_u->handle;
6656 uint32 jobid = q_u->jobid;
6657 uint32 command = q_u->command;
6660 WERROR errcode = WERR_BADFUNC;
6662 if (!get_printer_snum(p, handle, &snum)) {
6666 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6667 return WERR_INVALID_PRINTER_NAME;
6671 case JOB_CONTROL_CANCEL:
6672 case JOB_CONTROL_DELETE:
6673 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6677 case JOB_CONTROL_PAUSE:
6678 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6682 case JOB_CONTROL_RESTART:
6683 case JOB_CONTROL_RESUME:
6684 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6689 return WERR_UNKNOWN_LEVEL;
6695 /****************************************************************************
6696 Enumerates all printer drivers at level 1.
6697 ****************************************************************************/
6699 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6704 fstring *list = NULL;
6705 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6706 DRIVER_INFO_1 *driver_info_1=NULL;
6707 WERROR result = WERR_OK;
6711 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6713 ndrivers=get_ntdrivers(&list, architecture, version);
6714 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6716 if(ndrivers == -1) {
6717 SAFE_FREE(driver_info_1);
6722 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6723 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6729 for (i=0; i<ndrivers; i++) {
6731 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6732 ZERO_STRUCT(driver);
6733 status = get_a_printer_driver(&driver, 3, list[i],
6734 architecture, version);
6735 if (!W_ERROR_IS_OK(status)) {
6737 SAFE_FREE(driver_info_1);
6740 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6741 free_a_printer_driver(driver, 3);
6744 *returned+=ndrivers;
6748 /* check the required size. */
6749 for (i=0; i<*returned; i++) {
6750 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6751 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6754 if (*needed > offered) {
6755 result = WERR_INSUFFICIENT_BUFFER;
6759 if (!rpcbuf_alloc_size(buffer, *needed)) {
6760 result = WERR_NOMEM;
6764 /* fill the buffer with the driver structures */
6765 for (i=0; i<*returned; i++) {
6766 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6767 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6771 SAFE_FREE(driver_info_1);
6773 if ( !W_ERROR_IS_OK(result) )
6779 /****************************************************************************
6780 Enumerates all printer drivers at level 2.
6781 ****************************************************************************/
6783 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6788 fstring *list = NULL;
6789 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6790 DRIVER_INFO_2 *driver_info_2=NULL;
6791 WERROR result = WERR_OK;
6795 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6797 ndrivers=get_ntdrivers(&list, architecture, version);
6798 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6800 if(ndrivers == -1) {
6801 SAFE_FREE(driver_info_2);
6806 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6807 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6813 for (i=0; i<ndrivers; i++) {
6816 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6817 ZERO_STRUCT(driver);
6818 status = get_a_printer_driver(&driver, 3, list[i],
6819 architecture, version);
6820 if (!W_ERROR_IS_OK(status)) {
6822 SAFE_FREE(driver_info_2);
6825 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6826 free_a_printer_driver(driver, 3);
6829 *returned+=ndrivers;
6833 /* check the required size. */
6834 for (i=0; i<*returned; i++) {
6835 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6836 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6839 if (*needed > offered) {
6840 result = WERR_INSUFFICIENT_BUFFER;
6844 if (!rpcbuf_alloc_size(buffer, *needed)) {
6845 result = WERR_NOMEM;
6849 /* fill the buffer with the form structures */
6850 for (i=0; i<*returned; i++) {
6851 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6852 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6856 SAFE_FREE(driver_info_2);
6858 if ( !W_ERROR_IS_OK(result) )
6864 /****************************************************************************
6865 Enumerates all printer drivers at level 3.
6866 ****************************************************************************/
6868 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6873 fstring *list = NULL;
6874 DRIVER_INFO_3 *driver_info_3=NULL;
6875 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6876 WERROR result = WERR_OK;
6880 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6882 ndrivers=get_ntdrivers(&list, architecture, version);
6883 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6885 if(ndrivers == -1) {
6886 SAFE_FREE(driver_info_3);
6891 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6892 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6898 for (i=0; i<ndrivers; i++) {
6901 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6902 ZERO_STRUCT(driver);
6903 status = get_a_printer_driver(&driver, 3, list[i],
6904 architecture, version);
6905 if (!W_ERROR_IS_OK(status)) {
6907 SAFE_FREE(driver_info_3);
6910 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6911 free_a_printer_driver(driver, 3);
6914 *returned+=ndrivers;
6918 /* check the required size. */
6919 for (i=0; i<*returned; i++) {
6920 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6921 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6924 if (*needed > offered) {
6925 result = WERR_INSUFFICIENT_BUFFER;
6929 if (!rpcbuf_alloc_size(buffer, *needed)) {
6930 result = WERR_NOMEM;
6934 /* fill the buffer with the driver structures */
6935 for (i=0; i<*returned; i++) {
6936 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6937 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6941 for (i=0; i<*returned; i++) {
6942 SAFE_FREE(driver_info_3[i].dependentfiles);
6945 SAFE_FREE(driver_info_3);
6947 if ( !W_ERROR_IS_OK(result) )
6953 /****************************************************************************
6954 Enumerates all printer drivers.
6955 ****************************************************************************/
6957 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6959 uint32 level = q_u->level;
6960 RPC_BUFFER *buffer = NULL;
6961 uint32 offered = q_u->offered;
6962 uint32 *needed = &r_u->needed;
6963 uint32 *returned = &r_u->returned;
6966 fstring architecture;
6968 /* that's an [in out] buffer */
6970 if (!q_u->buffer && (offered!=0)) {
6971 return WERR_INVALID_PARAM;
6974 rpcbuf_move(q_u->buffer, &r_u->buffer);
6975 buffer = r_u->buffer;
6977 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6982 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6983 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6985 if ( !is_myname_or_ipaddr( servername ) )
6986 return WERR_UNKNOWN_PRINTER_DRIVER;
6990 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6992 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6994 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6996 return WERR_UNKNOWN_LEVEL;
7000 /****************************************************************************
7001 ****************************************************************************/
7003 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7005 form->flag=list->flag;
7006 init_unistr(&form->name, list->name);
7007 form->width=list->width;
7008 form->length=list->length;
7009 form->left=list->left;
7010 form->top=list->top;
7011 form->right=list->right;
7012 form->bottom=list->bottom;
7015 /****************************************************************************
7016 ****************************************************************************/
7018 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7020 uint32 level = q_u->level;
7021 RPC_BUFFER *buffer = NULL;
7022 uint32 offered = q_u->offered;
7023 uint32 *needed = &r_u->needed;
7024 uint32 *numofforms = &r_u->numofforms;
7025 uint32 numbuiltinforms;
7027 nt_forms_struct *list=NULL;
7028 nt_forms_struct *builtinlist=NULL;
7033 /* that's an [in out] buffer */
7035 if (!q_u->buffer && (offered!=0) ) {
7036 return WERR_INVALID_PARAM;
7039 rpcbuf_move(q_u->buffer, &r_u->buffer);
7040 buffer = r_u->buffer;
7042 DEBUG(4,("_spoolss_enumforms\n"));
7043 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7044 DEBUGADD(5,("Info level [%d]\n", level));
7046 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7047 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7048 *numofforms = get_ntforms(&list);
7049 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7050 *numofforms += numbuiltinforms;
7052 if (*numofforms == 0) {
7053 SAFE_FREE(builtinlist);
7055 return WERR_NO_MORE_ITEMS;
7060 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7061 SAFE_FREE(builtinlist);
7067 /* construct the list of form structures */
7068 for (i=0; i<numbuiltinforms; i++) {
7069 DEBUGADD(6,("Filling form number [%d]\n",i));
7070 fill_form_1(&forms_1[i], &builtinlist[i]);
7073 SAFE_FREE(builtinlist);
7075 for (; i<*numofforms; i++) {
7076 DEBUGADD(6,("Filling form number [%d]\n",i));
7077 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7082 /* check the required size. */
7083 for (i=0; i<numbuiltinforms; i++) {
7084 DEBUGADD(6,("adding form [%d]'s size\n",i));
7085 buffer_size += spoolss_size_form_1(&forms_1[i]);
7087 for (; i<*numofforms; i++) {
7088 DEBUGADD(6,("adding form [%d]'s size\n",i));
7089 buffer_size += spoolss_size_form_1(&forms_1[i]);
7092 *needed=buffer_size;
7094 if (*needed > offered) {
7097 return WERR_INSUFFICIENT_BUFFER;
7100 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7106 /* fill the buffer with the form structures */
7107 for (i=0; i<numbuiltinforms; i++) {
7108 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7109 smb_io_form_1("", buffer, &forms_1[i], 0);
7111 for (; i<*numofforms; i++) {
7112 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7113 smb_io_form_1("", buffer, &forms_1[i], 0);
7122 SAFE_FREE(builtinlist);
7123 return WERR_UNKNOWN_LEVEL;
7127 /****************************************************************************
7128 ****************************************************************************/
7130 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7132 uint32 level = q_u->level;
7133 UNISTR2 *uni_formname = &q_u->formname;
7134 RPC_BUFFER *buffer = NULL;
7135 uint32 offered = q_u->offered;
7136 uint32 *needed = &r_u->needed;
7138 nt_forms_struct *list=NULL;
7139 nt_forms_struct builtin_form;
7144 int numofforms=0, i=0;
7146 /* that's an [in out] buffer */
7148 if (!q_u->buffer && (offered!=0)) {
7149 return WERR_INVALID_PARAM;
7152 rpcbuf_move(q_u->buffer, &r_u->buffer);
7153 buffer = r_u->buffer;
7155 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7157 DEBUG(4,("_spoolss_getform\n"));
7158 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7159 DEBUGADD(5,("Info level [%d]\n", level));
7161 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7162 if (!foundBuiltin) {
7163 numofforms = get_ntforms(&list);
7164 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7166 if (numofforms == 0)
7173 fill_form_1(&form_1, &builtin_form);
7176 /* Check if the requested name is in the list of form structures */
7177 for (i=0; i<numofforms; i++) {
7179 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7181 if (strequal(form_name, list[i].name)) {
7182 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7183 fill_form_1(&form_1, &list[i]);
7189 if (i == numofforms) {
7193 /* check the required size. */
7195 *needed=spoolss_size_form_1(&form_1);
7197 if (*needed > offered)
7198 return WERR_INSUFFICIENT_BUFFER;
7200 if (!rpcbuf_alloc_size(buffer, buffer_size))
7203 /* fill the buffer with the form structures */
7204 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7205 smb_io_form_1("", buffer, &form_1, 0);
7211 return WERR_UNKNOWN_LEVEL;
7215 /****************************************************************************
7216 ****************************************************************************/
7218 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7220 init_unistr(&port->port_name, name);
7223 /****************************************************************************
7224 TODO: This probably needs distinguish between TCP/IP and Local ports
7226 ****************************************************************************/
7228 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7230 init_unistr(&port->port_name, name);
7231 init_unistr(&port->monitor_name, "Local Monitor");
7232 init_unistr(&port->description, SPL_LOCAL_PORT );
7233 port->port_type=PORT_TYPE_WRITE;
7238 /****************************************************************************
7239 wrapper around the enumer ports command
7240 ****************************************************************************/
7242 WERROR enumports_hook( int *count, char ***lines )
7244 char *cmd = lp_enumports_cmd();
7254 /* if no hook then just fill in the default port */
7257 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7258 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7263 /* we have a valid enumport command */
7265 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7267 DEBUG(10,("Running [%s]\n", command));
7268 ret = smbrun(command, &fd);
7269 DEBUG(10,("Returned [%d]\n", ret));
7274 return WERR_ACCESS_DENIED;
7278 qlines = fd_lines_load(fd, &numlines, 0);
7279 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7289 /****************************************************************************
7291 ****************************************************************************/
7293 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7295 PORT_INFO_1 *ports=NULL;
7297 WERROR result = WERR_OK;
7298 char **qlines = NULL;
7301 result = enumports_hook( &numlines, &qlines );
7302 if (!W_ERROR_IS_OK(result)) {
7303 file_lines_free(qlines);
7308 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7309 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7310 dos_errstr(WERR_NOMEM)));
7311 file_lines_free(qlines);
7315 for (i=0; i<numlines; i++) {
7316 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7317 fill_port_1(&ports[i], qlines[i]);
7320 file_lines_free(qlines);
7322 *returned = numlines;
7324 /* check the required size. */
7325 for (i=0; i<*returned; i++) {
7326 DEBUGADD(6,("adding port [%d]'s size\n", i));
7327 *needed += spoolss_size_port_info_1(&ports[i]);
7330 if (*needed > offered) {
7331 result = WERR_INSUFFICIENT_BUFFER;
7335 if (!rpcbuf_alloc_size(buffer, *needed)) {
7336 result = WERR_NOMEM;
7340 /* fill the buffer with the ports structures */
7341 for (i=0; i<*returned; i++) {
7342 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7343 smb_io_port_1("", buffer, &ports[i], 0);
7349 if ( !W_ERROR_IS_OK(result) )
7355 /****************************************************************************
7357 ****************************************************************************/
7359 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7361 PORT_INFO_2 *ports=NULL;
7363 WERROR result = WERR_OK;
7364 char **qlines = NULL;
7367 result = enumports_hook( &numlines, &qlines );
7368 if ( !W_ERROR_IS_OK(result)) {
7369 file_lines_free(qlines);
7374 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7375 file_lines_free(qlines);
7379 for (i=0; i<numlines; i++) {
7380 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7381 fill_port_2(&(ports[i]), qlines[i]);
7385 file_lines_free(qlines);
7387 *returned = numlines;
7389 /* check the required size. */
7390 for (i=0; i<*returned; i++) {
7391 DEBUGADD(6,("adding port [%d]'s size\n", i));
7392 *needed += spoolss_size_port_info_2(&ports[i]);
7395 if (*needed > offered) {
7396 result = WERR_INSUFFICIENT_BUFFER;
7400 if (!rpcbuf_alloc_size(buffer, *needed)) {
7401 result = WERR_NOMEM;
7405 /* fill the buffer with the ports structures */
7406 for (i=0; i<*returned; i++) {
7407 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7408 smb_io_port_2("", buffer, &ports[i], 0);
7414 if ( !W_ERROR_IS_OK(result) )
7420 /****************************************************************************
7422 ****************************************************************************/
7424 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7426 uint32 level = q_u->level;
7427 RPC_BUFFER *buffer = NULL;
7428 uint32 offered = q_u->offered;
7429 uint32 *needed = &r_u->needed;
7430 uint32 *returned = &r_u->returned;
7432 /* that's an [in out] buffer */
7434 if (!q_u->buffer && (offered!=0)) {
7435 return WERR_INVALID_PARAM;
7438 rpcbuf_move(q_u->buffer, &r_u->buffer);
7439 buffer = r_u->buffer;
7441 DEBUG(4,("_spoolss_enumports\n"));
7448 return enumports_level_1(buffer, offered, needed, returned);
7450 return enumports_level_2(buffer, offered, needed, returned);
7452 return WERR_UNKNOWN_LEVEL;
7456 /****************************************************************************
7457 ****************************************************************************/
7459 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7460 const SPOOL_PRINTER_INFO_LEVEL *info,
7461 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7462 uint32 user_switch, const SPOOL_USER_CTR *user,
7465 NT_PRINTER_INFO_LEVEL *printer = NULL;
7468 WERROR err = WERR_OK;
7470 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7471 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7475 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7476 if (!convert_printer_info(info, printer, 2)) {
7477 free_a_printer(&printer, 2);
7481 /* check to see if the printer already exists */
7483 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7484 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7485 printer->info_2->sharename));
7486 free_a_printer(&printer, 2);
7487 return WERR_PRINTER_ALREADY_EXISTS;
7490 /* FIXME!!! smbd should check to see if the driver is installed before
7491 trying to add a printer like this --jerry */
7493 if (*lp_addprinter_cmd() ) {
7494 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7495 free_a_printer(&printer,2);
7496 return WERR_ACCESS_DENIED;
7499 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7500 "smb.conf parameter \"addprinter command\" is defined. This"
7501 "parameter must exist for this call to succeed\n",
7502 printer->info_2->sharename ));
7505 /* use our primary netbios name since get_a_printer() will convert
7506 it to what the client expects on a case by case basis */
7508 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7509 printer->info_2->sharename);
7512 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7513 free_a_printer(&printer,2);
7514 return WERR_ACCESS_DENIED;
7517 /* you must be a printer admin to add a new printer */
7518 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7519 free_a_printer(&printer,2);
7520 return WERR_ACCESS_DENIED;
7524 * Do sanity check on the requested changes for Samba.
7527 if (!check_printer_ok(printer->info_2, snum)) {
7528 free_a_printer(&printer,2);
7529 return WERR_INVALID_PARAM;
7533 * When a printer is created, the drivername bound to the printer is used
7534 * to lookup previously saved driver initialization info, which is then
7535 * bound to the new printer, simulating what happens in the Windows arch.
7540 set_driver_init(printer, 2);
7544 /* A valid devmode was included, convert and link it
7546 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7548 if (!convert_devicemode(printer->info_2->printername, devmode,
7549 &printer->info_2->devmode))
7553 /* write the ASCII on disk */
7554 err = mod_a_printer(printer, 2);
7555 if (!W_ERROR_IS_OK(err)) {
7556 free_a_printer(&printer,2);
7560 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7561 /* Handle open failed - remove addition. */
7562 del_a_printer(printer->info_2->sharename);
7563 free_a_printer(&printer,2);
7564 return WERR_ACCESS_DENIED;
7567 update_c_setprinter(False);
7568 free_a_printer(&printer,2);
7573 /****************************************************************************
7574 ****************************************************************************/
7576 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7578 UNISTR2 *uni_srv_name = q_u->server_name;
7579 uint32 level = q_u->level;
7580 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7581 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7582 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7583 uint32 user_switch = q_u->user_switch;
7584 SPOOL_USER_CTR *user = &q_u->user_ctr;
7585 POLICY_HND *handle = &r_u->handle;
7589 /* we don't handle yet */
7590 /* but I know what to do ... */
7591 return WERR_UNKNOWN_LEVEL;
7593 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7595 user_switch, user, handle);
7597 return WERR_UNKNOWN_LEVEL;
7601 /****************************************************************************
7602 ****************************************************************************/
7604 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7606 uint32 level = q_u->level;
7607 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7608 WERROR err = WERR_OK;
7609 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7610 fstring driver_name;
7613 ZERO_STRUCT(driver);
7615 if (!convert_printer_driver_info(info, &driver, level)) {
7620 DEBUG(5,("Cleaning driver's information\n"));
7621 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7622 if (!W_ERROR_IS_OK(err))
7625 DEBUG(5,("Moving driver to final destination\n"));
7626 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7630 if (add_a_printer_driver(driver, level)!=0) {
7631 err = WERR_ACCESS_DENIED;
7636 * I think this is where he DrvUpgradePrinter() hook would be
7637 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7638 * server. Right now, we just need to send ourselves a message
7639 * to update each printer bound to this driver. --jerry
7642 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7643 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7648 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7649 * decide if the driver init data should be deleted. The rules are:
7650 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7651 * 2) delete init data only if there is no 2k/Xp driver
7652 * 3) always delete init data
7653 * The generalized rule is always use init data from the highest order driver.
7654 * It is necessary to follow the driver install by an initialization step to
7655 * finish off this process.
7658 version = driver.info_3->cversion;
7659 else if (level == 6)
7660 version = driver.info_6->version;
7665 * 9x printer driver - never delete init data
7668 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7673 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7674 * there is no 2k/Xp driver init data for this driver name.
7678 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7680 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7682 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7684 if (!del_driver_init(driver_name))
7685 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7688 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7690 free_a_printer_driver(driver1,3);
7691 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7698 * 2k or Xp printer driver - always delete init data
7701 if (!del_driver_init(driver_name))
7702 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7706 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7712 free_a_printer_driver(driver, level);
7716 /********************************************************************
7717 * spoolss_addprinterdriverex
7718 ********************************************************************/
7720 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7722 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7723 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7726 * we only support the semantics of AddPrinterDriver()
7727 * i.e. only copy files that are newer than existing ones
7730 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7731 return WERR_ACCESS_DENIED;
7733 ZERO_STRUCT(q_u_local);
7734 ZERO_STRUCT(r_u_local);
7736 /* just pass the information off to _spoolss_addprinterdriver() */
7737 q_u_local.server_name_ptr = q_u->server_name_ptr;
7738 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7739 q_u_local.level = q_u->level;
7740 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7742 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7745 /****************************************************************************
7746 ****************************************************************************/
7748 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7750 init_unistr(&info->name, name);
7753 /****************************************************************************
7754 ****************************************************************************/
7756 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7762 const char *short_archi;
7763 DRIVER_DIRECTORY_1 *info=NULL;
7764 WERROR result = WERR_OK;
7766 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7767 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7769 /* check for beginning double '\'s and that the server
7772 pservername = servername;
7773 if ( *pservername == '\\' && strlen(servername)>2 ) {
7777 if ( !is_myname_or_ipaddr( pservername ) )
7778 return WERR_INVALID_PARAM;
7780 if (!(short_archi = get_short_archi(long_archi)))
7781 return WERR_INVALID_ENVIRONMENT;
7783 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7786 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7788 DEBUG(4,("printer driver directory: [%s]\n", path));
7790 fill_driverdir_1(info, path);
7792 *needed += spoolss_size_driverdir_info_1(info);
7794 if (*needed > offered) {
7795 result = WERR_INSUFFICIENT_BUFFER;
7799 if (!rpcbuf_alloc_size(buffer, *needed)) {
7800 result = WERR_NOMEM;
7804 smb_io_driverdir_1("", buffer, info, 0);
7812 /****************************************************************************
7813 ****************************************************************************/
7815 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7817 UNISTR2 *name = &q_u->name;
7818 UNISTR2 *uni_environment = &q_u->environment;
7819 uint32 level = q_u->level;
7820 RPC_BUFFER *buffer = NULL;
7821 uint32 offered = q_u->offered;
7822 uint32 *needed = &r_u->needed;
7824 /* that's an [in out] buffer */
7826 if (!q_u->buffer && (offered!=0)) {
7827 return WERR_INVALID_PARAM;
7830 rpcbuf_move(q_u->buffer, &r_u->buffer);
7831 buffer = r_u->buffer;
7833 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7839 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7841 return WERR_UNKNOWN_LEVEL;
7845 /****************************************************************************
7846 ****************************************************************************/
7848 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7850 POLICY_HND *handle = &q_u->handle;
7851 uint32 idx = q_u->index;
7852 uint32 in_value_len = q_u->valuesize;
7853 uint32 in_data_len = q_u->datasize;
7854 uint32 *out_max_value_len = &r_u->valuesize;
7855 uint16 **out_value = &r_u->value;
7856 uint32 *out_value_len = &r_u->realvaluesize;
7857 uint32 *out_type = &r_u->type;
7858 uint32 *out_max_data_len = &r_u->datasize;
7859 uint8 **data_out = &r_u->data;
7860 uint32 *out_data_len = &r_u->realdatasize;
7862 NT_PRINTER_INFO_LEVEL *printer = NULL;
7864 uint32 biggest_valuesize;
7865 uint32 biggest_datasize;
7867 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7870 REGISTRY_VALUE *val = NULL;
7871 NT_PRINTER_DATA *p_data;
7872 int i, key_index, num_values;
7877 *out_max_data_len = 0;
7881 DEBUG(5,("spoolss_enumprinterdata\n"));
7884 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7888 if (!get_printer_snum(p,handle, &snum))
7891 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7892 if (!W_ERROR_IS_OK(result))
7895 p_data = printer->info_2->data;
7896 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7901 * The NT machine wants to know the biggest size of value and data
7903 * cf: MSDN EnumPrinterData remark section
7906 if ( !in_value_len && !in_data_len && (key_index != -1) )
7908 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7910 biggest_valuesize = 0;
7911 biggest_datasize = 0;
7913 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7915 for ( i=0; i<num_values; i++ )
7917 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7919 name_length = strlen(val->valuename);
7920 if ( strlen(val->valuename) > biggest_valuesize )
7921 biggest_valuesize = name_length;
7923 if ( val->size > biggest_datasize )
7924 biggest_datasize = val->size;
7926 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7930 /* the value is an UNICODE string but real_value_size is the length
7931 in bytes including the trailing 0 */
7933 *out_value_len = 2 * (1+biggest_valuesize);
7934 *out_data_len = biggest_datasize;
7936 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7942 * the value len is wrong in NT sp3
7943 * that's the number of bytes not the number of unicode chars
7946 if ( key_index != -1 )
7947 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7952 /* out_value should default to "" or else NT4 has
7953 problems unmarshalling the response */
7955 *out_max_value_len=(in_value_len/sizeof(uint16));
7957 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7959 result = WERR_NOMEM;
7963 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7965 /* the data is counted in bytes */
7967 *out_max_data_len = in_data_len;
7968 *out_data_len = in_data_len;
7970 /* only allocate when given a non-zero data_len */
7972 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7974 result = WERR_NOMEM;
7978 result = WERR_NO_MORE_ITEMS;
7984 * - counted in bytes in the request
7985 * - counted in UNICODE chars in the max reply
7986 * - counted in bytes in the real size
7988 * take a pause *before* coding not *during* coding
7992 *out_max_value_len=(in_value_len/sizeof(uint16));
7993 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7995 result = WERR_NOMEM;
7999 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8003 *out_type = regval_type( val );
8005 /* data - counted in bytes */
8007 *out_max_data_len = in_data_len;
8008 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8010 result = WERR_NOMEM;
8013 data_len = regval_size(val);
8015 memcpy( *data_out, regval_data_p(val), data_len );
8016 *out_data_len = data_len;
8020 free_a_printer(&printer, 2);
8024 /****************************************************************************
8025 ****************************************************************************/
8027 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8029 POLICY_HND *handle = &q_u->handle;
8030 UNISTR2 *value = &q_u->value;
8031 uint32 type = q_u->type;
8032 uint8 *data = q_u->data;
8033 uint32 real_len = q_u->real_len;
8035 NT_PRINTER_INFO_LEVEL *printer = NULL;
8037 WERROR status = WERR_OK;
8038 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8041 DEBUG(5,("spoolss_setprinterdata\n"));
8044 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8048 if ( Printer->printer_type == SPLHND_SERVER ) {
8049 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8050 return WERR_INVALID_PARAM;
8053 if (!get_printer_snum(p,handle, &snum))
8057 * Access check : NT returns "access denied" if you make a
8058 * SetPrinterData call without the necessary privildge.
8059 * we were originally returning OK if nothing changed
8060 * which made Win2k issue **a lot** of SetPrinterData
8061 * when connecting to a printer --jerry
8064 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8066 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8067 status = WERR_ACCESS_DENIED;
8071 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8072 if (!W_ERROR_IS_OK(status))
8075 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8078 * When client side code sets a magic printer data key, detect it and save
8079 * the current printer data and the magic key's data (its the DEVMODE) for
8080 * future printer/driver initializations.
8082 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8084 /* Set devmode and printer initialization info */
8085 status = save_driver_init( printer, 2, data, real_len );
8087 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8091 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8092 type, data, real_len );
8093 if ( W_ERROR_IS_OK(status) )
8094 status = mod_a_printer(printer, 2);
8098 free_a_printer(&printer, 2);
8103 /****************************************************************************
8104 ****************************************************************************/
8106 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8108 POLICY_HND *handle = &q_u->handle;
8109 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8112 DEBUG(5,("_spoolss_resetprinter\n"));
8115 * All we do is to check to see if the handle and queue is valid.
8116 * This call really doesn't mean anything to us because we only
8117 * support RAW printing. --jerry
8121 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8125 if (!get_printer_snum(p,handle, &snum))
8129 /* blindly return success */
8134 /****************************************************************************
8135 ****************************************************************************/
8137 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8139 POLICY_HND *handle = &q_u->handle;
8140 UNISTR2 *value = &q_u->valuename;
8142 NT_PRINTER_INFO_LEVEL *printer = NULL;
8144 WERROR status = WERR_OK;
8145 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8148 DEBUG(5,("spoolss_deleteprinterdata\n"));
8151 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8155 if (!get_printer_snum(p, handle, &snum))
8158 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8159 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8160 return WERR_ACCESS_DENIED;
8163 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8164 if (!W_ERROR_IS_OK(status))
8167 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8169 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8171 if ( W_ERROR_IS_OK(status) )
8172 mod_a_printer( printer, 2 );
8174 free_a_printer(&printer, 2);
8179 /****************************************************************************
8180 ****************************************************************************/
8182 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8184 POLICY_HND *handle = &q_u->handle;
8185 FORM *form = &q_u->form;
8186 nt_forms_struct tmpForm;
8188 WERROR status = WERR_OK;
8189 NT_PRINTER_INFO_LEVEL *printer = NULL;
8192 nt_forms_struct *list=NULL;
8193 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8195 DEBUG(5,("spoolss_addform\n"));
8198 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8203 /* forms can be added on printer of on the print server handle */
8205 if ( Printer->printer_type == SPLHND_PRINTER )
8207 if (!get_printer_snum(p,handle, &snum))
8210 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8211 if (!W_ERROR_IS_OK(status))
8215 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8216 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8217 status = WERR_ACCESS_DENIED;
8221 /* can't add if builtin */
8223 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8224 status = WERR_ALREADY_EXISTS;
8228 count = get_ntforms(&list);
8230 if(!add_a_form(&list, form, &count)) {
8231 status = WERR_NOMEM;
8235 write_ntforms(&list, count);
8238 * ChangeID must always be set if this is a printer
8241 if ( Printer->printer_type == SPLHND_PRINTER )
8242 status = mod_a_printer(printer, 2);
8246 free_a_printer(&printer, 2);
8252 /****************************************************************************
8253 ****************************************************************************/
8255 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8257 POLICY_HND *handle = &q_u->handle;
8258 UNISTR2 *form_name = &q_u->name;
8259 nt_forms_struct tmpForm;
8261 nt_forms_struct *list=NULL;
8262 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8264 WERROR status = WERR_OK;
8265 NT_PRINTER_INFO_LEVEL *printer = NULL;
8267 DEBUG(5,("spoolss_deleteform\n"));
8270 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8274 /* forms can be deleted on printer of on the print server handle */
8276 if ( Printer->printer_type == SPLHND_PRINTER )
8278 if (!get_printer_snum(p,handle, &snum))
8281 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8282 if (!W_ERROR_IS_OK(status))
8286 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8287 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8288 status = WERR_ACCESS_DENIED;
8292 /* can't delete if builtin */
8294 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8295 status = WERR_INVALID_PARAM;
8299 count = get_ntforms(&list);
8301 if ( !delete_a_form(&list, form_name, &count, &status ))
8305 * ChangeID must always be set if this is a printer
8308 if ( Printer->printer_type == SPLHND_PRINTER )
8309 status = mod_a_printer(printer, 2);
8313 free_a_printer(&printer, 2);
8319 /****************************************************************************
8320 ****************************************************************************/
8322 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8324 POLICY_HND *handle = &q_u->handle;
8325 FORM *form = &q_u->form;
8326 nt_forms_struct tmpForm;
8328 WERROR status = WERR_OK;
8329 NT_PRINTER_INFO_LEVEL *printer = NULL;
8332 nt_forms_struct *list=NULL;
8333 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8335 DEBUG(5,("spoolss_setform\n"));
8338 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8342 /* forms can be modified on printer of on the print server handle */
8344 if ( Printer->printer_type == SPLHND_PRINTER )
8346 if (!get_printer_snum(p,handle, &snum))
8349 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8350 if (!W_ERROR_IS_OK(status))
8354 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8355 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8356 status = WERR_ACCESS_DENIED;
8360 /* can't set if builtin */
8361 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8362 status = WERR_INVALID_PARAM;
8366 count = get_ntforms(&list);
8367 update_a_form(&list, form, count);
8368 write_ntforms(&list, count);
8371 * ChangeID must always be set if this is a printer
8374 if ( Printer->printer_type == SPLHND_PRINTER )
8375 status = mod_a_printer(printer, 2);
8380 free_a_printer(&printer, 2);
8386 /****************************************************************************
8387 enumprintprocessors level 1.
8388 ****************************************************************************/
8390 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8392 PRINTPROCESSOR_1 *info_1=NULL;
8393 WERROR result = WERR_OK;
8395 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8400 init_unistr(&info_1->name, "winprint");
8402 *needed += spoolss_size_printprocessor_info_1(info_1);
8404 if (*needed > offered) {
8405 result = WERR_INSUFFICIENT_BUFFER;
8409 if (!rpcbuf_alloc_size(buffer, *needed)) {
8410 result = WERR_NOMEM;
8414 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8419 if ( !W_ERROR_IS_OK(result) )
8425 /****************************************************************************
8426 ****************************************************************************/
8428 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8430 uint32 level = q_u->level;
8431 RPC_BUFFER *buffer = NULL;
8432 uint32 offered = q_u->offered;
8433 uint32 *needed = &r_u->needed;
8434 uint32 *returned = &r_u->returned;
8436 /* that's an [in out] buffer */
8438 if (!q_u->buffer && (offered!=0)) {
8439 return WERR_INVALID_PARAM;
8442 rpcbuf_move(q_u->buffer, &r_u->buffer);
8443 buffer = r_u->buffer;
8445 DEBUG(5,("spoolss_enumprintprocessors\n"));
8448 * Enumerate the print processors ...
8450 * Just reply with "winprint", to keep NT happy
8451 * and I can use my nice printer checker.
8459 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8461 return WERR_UNKNOWN_LEVEL;
8465 /****************************************************************************
8466 enumprintprocdatatypes level 1.
8467 ****************************************************************************/
8469 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8471 PRINTPROCDATATYPE_1 *info_1=NULL;
8472 WERROR result = WERR_NOMEM;
8474 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8479 init_unistr(&info_1->name, "RAW");
8481 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8483 if (*needed > offered) {
8484 result = WERR_INSUFFICIENT_BUFFER;
8488 if (!rpcbuf_alloc_size(buffer, *needed)) {
8489 result = WERR_NOMEM;
8493 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8498 if ( !W_ERROR_IS_OK(result) )
8504 /****************************************************************************
8505 ****************************************************************************/
8507 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8509 uint32 level = q_u->level;
8510 RPC_BUFFER *buffer = NULL;
8511 uint32 offered = q_u->offered;
8512 uint32 *needed = &r_u->needed;
8513 uint32 *returned = &r_u->returned;
8515 /* that's an [in out] buffer */
8517 if (!q_u->buffer && (offered!=0)) {
8518 return WERR_INVALID_PARAM;
8521 rpcbuf_move(q_u->buffer, &r_u->buffer);
8522 buffer = r_u->buffer;
8524 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8531 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8533 return WERR_UNKNOWN_LEVEL;
8537 /****************************************************************************
8538 enumprintmonitors level 1.
8539 ****************************************************************************/
8541 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8543 PRINTMONITOR_1 *info_1;
8544 WERROR result = WERR_OK;
8547 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8552 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8553 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8555 for ( i=0; i<*returned; i++ ) {
8556 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8559 if (*needed > offered) {
8560 result = WERR_INSUFFICIENT_BUFFER;
8564 if (!rpcbuf_alloc_size(buffer, *needed)) {
8565 result = WERR_NOMEM;
8569 for ( i=0; i<*returned; i++ ) {
8570 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8576 if ( !W_ERROR_IS_OK(result) )
8582 /****************************************************************************
8583 enumprintmonitors level 2.
8584 ****************************************************************************/
8586 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8588 PRINTMONITOR_2 *info_2;
8589 WERROR result = WERR_OK;
8592 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8597 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8598 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8599 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8601 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8602 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8603 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8605 for ( i=0; i<*returned; i++ ) {
8606 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8609 if (*needed > offered) {
8610 result = WERR_INSUFFICIENT_BUFFER;
8614 if (!rpcbuf_alloc_size(buffer, *needed)) {
8615 result = WERR_NOMEM;
8619 for ( i=0; i<*returned; i++ ) {
8620 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8626 if ( !W_ERROR_IS_OK(result) )
8632 /****************************************************************************
8633 ****************************************************************************/
8635 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8637 uint32 level = q_u->level;
8638 RPC_BUFFER *buffer = NULL;
8639 uint32 offered = q_u->offered;
8640 uint32 *needed = &r_u->needed;
8641 uint32 *returned = &r_u->returned;
8643 /* that's an [in out] buffer */
8645 if (!q_u->buffer && (offered!=0)) {
8646 return WERR_INVALID_PARAM;
8649 rpcbuf_move(q_u->buffer, &r_u->buffer);
8650 buffer = r_u->buffer;
8652 DEBUG(5,("spoolss_enumprintmonitors\n"));
8655 * Enumerate the print monitors ...
8657 * Just reply with "Local Port", to keep NT happy
8658 * and I can use my nice printer checker.
8666 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8668 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8670 return WERR_UNKNOWN_LEVEL;
8674 /****************************************************************************
8675 ****************************************************************************/
8677 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8678 NT_PRINTER_INFO_LEVEL *ntprinter,
8679 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8684 JOB_INFO_1 *info_1=NULL;
8685 WERROR result = WERR_OK;
8687 info_1=SMB_MALLOC_P(JOB_INFO_1);
8689 if (info_1 == NULL) {
8693 for (i=0; i<count && found==False; i++) {
8694 if ((*queue)[i].job==(int)jobid)
8700 /* NT treats not found as bad param... yet another bad choice */
8701 return WERR_INVALID_PARAM;
8704 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8706 *needed += spoolss_size_job_info_1(info_1);
8708 if (*needed > offered) {
8709 result = WERR_INSUFFICIENT_BUFFER;
8713 if (!rpcbuf_alloc_size(buffer, *needed)) {
8714 result = WERR_NOMEM;
8718 smb_io_job_info_1("", buffer, info_1, 0);
8726 /****************************************************************************
8727 ****************************************************************************/
8729 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8730 NT_PRINTER_INFO_LEVEL *ntprinter,
8731 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8738 DEVICEMODE *devmode = NULL;
8739 NT_DEVICEMODE *nt_devmode = NULL;
8741 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8744 ZERO_STRUCTP(info_2);
8746 for ( i=0; i<count && found==False; i++ )
8748 if ((*queue)[i].job == (int)jobid)
8753 /* NT treats not found as bad param... yet another bad
8755 result = WERR_INVALID_PARAM;
8760 * if the print job does not have a DEVMODE associated with it,
8761 * just use the one for the printer. A NULL devicemode is not
8762 * a failure condition
8765 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8766 devmode = construct_dev_mode(lp_const_servicename(snum));
8768 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8769 ZERO_STRUCTP( devmode );
8770 convert_nt_devicemode( devmode, nt_devmode );
8774 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8776 *needed += spoolss_size_job_info_2(info_2);
8778 if (*needed > offered) {
8779 result = WERR_INSUFFICIENT_BUFFER;
8783 if (!rpcbuf_alloc_size(buffer, *needed)) {
8784 result = WERR_NOMEM;
8788 smb_io_job_info_2("", buffer, info_2, 0);
8793 /* Cleanup allocated memory */
8795 free_job_info_2(info_2); /* Also frees devmode */
8801 /****************************************************************************
8802 ****************************************************************************/
8804 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8806 POLICY_HND *handle = &q_u->handle;
8807 uint32 jobid = q_u->jobid;
8808 uint32 level = q_u->level;
8809 RPC_BUFFER *buffer = NULL;
8810 uint32 offered = q_u->offered;
8811 uint32 *needed = &r_u->needed;
8812 WERROR wstatus = WERR_OK;
8813 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8816 print_queue_struct *queue = NULL;
8817 print_status_struct prt_status;
8819 /* that's an [in out] buffer */
8821 if (!q_u->buffer && (offered!=0)) {
8822 return WERR_INVALID_PARAM;
8825 rpcbuf_move(q_u->buffer, &r_u->buffer);
8826 buffer = r_u->buffer;
8828 DEBUG(5,("spoolss_getjob\n"));
8832 if (!get_printer_snum(p, handle, &snum))
8835 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8836 if ( !W_ERROR_IS_OK(wstatus) )
8839 count = print_queue_status(snum, &queue, &prt_status);
8841 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8842 count, prt_status.status, prt_status.message));
8846 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8847 buffer, offered, needed);
8850 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8851 buffer, offered, needed);
8854 wstatus = WERR_UNKNOWN_LEVEL;
8859 free_a_printer( &ntprinter, 2 );
8864 /********************************************************************
8865 spoolss_getprinterdataex
8867 From MSDN documentation of GetPrinterDataEx: pass request
8868 to GetPrinterData if key is "PrinterDriverData".
8869 ********************************************************************/
8871 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8873 POLICY_HND *handle = &q_u->handle;
8874 uint32 in_size = q_u->size;
8875 uint32 *type = &r_u->type;
8876 uint32 *out_size = &r_u->size;
8877 uint8 **data = &r_u->data;
8878 uint32 *needed = &r_u->needed;
8879 fstring keyname, valuename;
8881 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8883 NT_PRINTER_INFO_LEVEL *printer = NULL;
8885 WERROR status = WERR_OK;
8887 DEBUG(4,("_spoolss_getprinterdataex\n"));
8889 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8890 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8892 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8893 keyname, valuename));
8895 /* in case of problem, return some default values */
8899 *out_size = in_size;
8902 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8903 status = WERR_BADFID;
8907 /* Is the handle to a printer or to the server? */
8909 if (Printer->printer_type == SPLHND_SERVER) {
8910 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8911 status = WERR_INVALID_PARAM;
8915 if ( !get_printer_snum(p,handle, &snum) )
8918 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8919 if ( !W_ERROR_IS_OK(status) )
8922 /* check to see if the keyname is valid */
8923 if ( !strlen(keyname) ) {
8924 status = WERR_INVALID_PARAM;
8928 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8929 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8930 free_a_printer( &printer, 2 );
8931 status = WERR_BADFILE;
8935 /* When given a new keyname, we should just create it */
8937 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8939 if (*needed > *out_size)
8940 status = WERR_MORE_DATA;
8943 if ( !W_ERROR_IS_OK(status) )
8945 DEBUG(5, ("error: allocating %d\n", *out_size));
8947 /* reply this param doesn't exist */
8951 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8952 status = WERR_NOMEM;
8962 free_a_printer( &printer, 2 );
8967 /********************************************************************
8968 * spoolss_setprinterdataex
8969 ********************************************************************/
8971 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8973 POLICY_HND *handle = &q_u->handle;
8974 uint32 type = q_u->type;
8975 uint8 *data = q_u->data;
8976 uint32 real_len = q_u->real_len;
8978 NT_PRINTER_INFO_LEVEL *printer = NULL;
8980 WERROR status = WERR_OK;
8981 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8986 DEBUG(4,("_spoolss_setprinterdataex\n"));
8988 /* From MSDN documentation of SetPrinterDataEx: pass request to
8989 SetPrinterData if key is "PrinterDriverData" */
8992 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8996 if ( Printer->printer_type == SPLHND_SERVER ) {
8997 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8998 return WERR_INVALID_PARAM;
9001 if ( !get_printer_snum(p,handle, &snum) )
9005 * Access check : NT returns "access denied" if you make a
9006 * SetPrinterData call without the necessary privildge.
9007 * we were originally returning OK if nothing changed
9008 * which made Win2k issue **a lot** of SetPrinterData
9009 * when connecting to a printer --jerry
9012 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9014 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9015 return WERR_ACCESS_DENIED;
9018 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9019 if (!W_ERROR_IS_OK(status))
9022 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9023 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9025 /* check for OID in valuename */
9027 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9033 /* save the registry data */
9035 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9037 if ( W_ERROR_IS_OK(status) )
9039 /* save the OID if one was specified */
9041 fstrcat( keyname, "\\" );
9042 fstrcat( keyname, SPOOL_OID_KEY );
9045 * I'm not checking the status here on purpose. Don't know
9046 * if this is right, but I'm returning the status from the
9047 * previous set_printer_dataex() call. I have no idea if
9048 * this is right. --jerry
9051 set_printer_dataex( printer, keyname, valuename,
9052 REG_SZ, (uint8 *)oid_string,
9053 strlen(oid_string)+1 );
9056 status = mod_a_printer(printer, 2);
9059 free_a_printer(&printer, 2);
9065 /********************************************************************
9066 * spoolss_deleteprinterdataex
9067 ********************************************************************/
9069 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9071 POLICY_HND *handle = &q_u->handle;
9072 UNISTR2 *value = &q_u->valuename;
9073 UNISTR2 *key = &q_u->keyname;
9075 NT_PRINTER_INFO_LEVEL *printer = NULL;
9077 WERROR status = WERR_OK;
9078 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9079 pstring valuename, keyname;
9081 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9084 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9088 if (!get_printer_snum(p, handle, &snum))
9091 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9092 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9093 return WERR_ACCESS_DENIED;
9096 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9097 if (!W_ERROR_IS_OK(status))
9100 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9101 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9103 status = delete_printer_dataex( printer, keyname, valuename );
9105 if ( W_ERROR_IS_OK(status) )
9106 mod_a_printer( printer, 2 );
9108 free_a_printer(&printer, 2);
9113 /********************************************************************
9114 * spoolss_enumprinterkey
9115 ********************************************************************/
9118 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9121 fstring *keynames = NULL;
9122 uint16 *enumkeys = NULL;
9125 POLICY_HND *handle = &q_u->handle;
9126 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9127 NT_PRINTER_DATA *data;
9128 NT_PRINTER_INFO_LEVEL *printer = NULL;
9130 WERROR status = WERR_BADFILE;
9133 DEBUG(4,("_spoolss_enumprinterkey\n"));
9136 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9140 if ( !get_printer_snum(p,handle, &snum) )
9143 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9144 if (!W_ERROR_IS_OK(status))
9147 /* get the list of subkey names */
9149 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9150 data = printer->info_2->data;
9152 num_keys = get_printer_subkeys( data, key, &keynames );
9154 if ( num_keys == -1 ) {
9155 status = WERR_BADFILE;
9159 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9161 r_u->needed = printerkey_len*2;
9163 if ( q_u->size < r_u->needed ) {
9164 status = WERR_MORE_DATA;
9168 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9169 status = WERR_NOMEM;
9175 if ( q_u->size < r_u->needed )
9176 status = WERR_MORE_DATA;
9179 free_a_printer( &printer, 2 );
9180 SAFE_FREE( keynames );
9185 /********************************************************************
9186 * spoolss_deleteprinterkey
9187 ********************************************************************/
9189 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9191 POLICY_HND *handle = &q_u->handle;
9192 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9194 NT_PRINTER_INFO_LEVEL *printer = NULL;
9198 DEBUG(5,("spoolss_deleteprinterkey\n"));
9201 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9205 /* if keyname == NULL, return error */
9207 if ( !q_u->keyname.buffer )
9208 return WERR_INVALID_PARAM;
9210 if (!get_printer_snum(p, handle, &snum))
9213 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9214 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9215 return WERR_ACCESS_DENIED;
9218 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9219 if (!W_ERROR_IS_OK(status))
9222 /* delete the key and all subneys */
9224 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9226 status = delete_all_printer_data( printer->info_2, key );
9228 if ( W_ERROR_IS_OK(status) )
9229 status = mod_a_printer(printer, 2);
9231 free_a_printer( &printer, 2 );
9237 /********************************************************************
9238 * spoolss_enumprinterdataex
9239 ********************************************************************/
9241 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9243 POLICY_HND *handle = &q_u->handle;
9244 uint32 in_size = q_u->size;
9247 NT_PRINTER_INFO_LEVEL *printer = NULL;
9248 PRINTER_ENUM_VALUES *enum_values = NULL;
9249 NT_PRINTER_DATA *p_data;
9251 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9256 REGISTRY_VALUE *val;
9261 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9264 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9269 * first check for a keyname of NULL or "". Win2k seems to send
9270 * this a lot and we should send back WERR_INVALID_PARAM
9271 * no need to spend time looking up the printer in this case.
9275 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9276 if ( !strlen(key) ) {
9277 result = WERR_INVALID_PARAM;
9281 /* get the printer off of disk */
9283 if (!get_printer_snum(p,handle, &snum))
9286 ZERO_STRUCT(printer);
9287 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9288 if (!W_ERROR_IS_OK(result))
9291 /* now look for a match on the key name */
9293 p_data = printer->info_2->data;
9295 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9296 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9298 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9299 result = WERR_INVALID_PARAM;
9306 /* allocate the memory for the array of pointers -- if necessary */
9308 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9311 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9313 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9314 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9315 result = WERR_NOMEM;
9319 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9323 * loop through all params and build the array to pass
9324 * back to the client
9327 for ( i=0; i<num_entries; i++ )
9329 /* lookup the registry value */
9331 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9332 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9336 value_name = regval_name( val );
9337 init_unistr( &enum_values[i].valuename, value_name );
9338 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9339 enum_values[i].type = regval_type( val );
9341 data_len = regval_size( val );
9343 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9345 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9347 result = WERR_NOMEM;
9351 enum_values[i].data_len = data_len;
9353 /* keep track of the size of the array in bytes */
9355 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9358 /* housekeeping information in the reply */
9360 r_u->needed = needed;
9361 r_u->returned = num_entries;
9363 if (needed > in_size) {
9364 result = WERR_MORE_DATA;
9368 /* copy data into the reply */
9370 r_u->ctr.size = r_u->needed;
9371 r_u->ctr.size_of_array = r_u->returned;
9372 r_u->ctr.values = enum_values;
9378 free_a_printer(&printer, 2);
9383 /****************************************************************************
9384 ****************************************************************************/
9386 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9388 init_unistr(&info->name, name);
9391 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9392 UNISTR2 *environment,
9399 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9400 WERROR result = WERR_OK;
9402 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9404 if (!get_short_archi(long_archi))
9405 return WERR_INVALID_ENVIRONMENT;
9407 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9410 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9412 fill_printprocessordirectory_1(info, path);
9414 *needed += spoolss_size_printprocessordirectory_info_1(info);
9416 if (*needed > offered) {
9417 result = WERR_INSUFFICIENT_BUFFER;
9421 if (!rpcbuf_alloc_size(buffer, *needed)) {
9422 result = WERR_INSUFFICIENT_BUFFER;
9426 smb_io_printprocessordirectory_1("", buffer, info, 0);
9434 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9436 uint32 level = q_u->level;
9437 RPC_BUFFER *buffer = NULL;
9438 uint32 offered = q_u->offered;
9439 uint32 *needed = &r_u->needed;
9442 /* that's an [in out] buffer */
9444 if (!q_u->buffer && (offered!=0)) {
9445 return WERR_INVALID_PARAM;
9448 rpcbuf_move(q_u->buffer, &r_u->buffer);
9449 buffer = r_u->buffer;
9451 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9457 result = getprintprocessordirectory_level_1
9458 (&q_u->name, &q_u->environment, buffer, offered, needed);
9461 result = WERR_UNKNOWN_LEVEL;
9467 /*******************************************************************
9468 Streams the monitor UI DLL name in UNICODE
9469 *******************************************************************/
9471 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9472 RPC_BUFFER *out, uint32 *needed )
9474 const char *dllname = "tcpmonui.dll";
9476 *needed = (strlen(dllname)+1) * 2;
9478 if ( rpcbuf_get_size(out) < *needed ) {
9479 return WERR_INSUFFICIENT_BUFFER;
9482 if ( !make_monitorui_buf( out, dllname ) ) {
9489 /*******************************************************************
9490 Create a new TCP/IP port
9491 *******************************************************************/
9493 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9494 RPC_BUFFER *out, uint32 *needed )
9496 NT_PORT_DATA_1 port1;
9499 ZERO_STRUCT( port1 );
9501 /* convert to our internal port data structure */
9503 if ( !convert_port_data_1( &port1, in ) ) {
9507 /* create the device URI and call the add_port_hook() */
9509 switch ( port1.protocol ) {
9510 case PORT_PROTOCOL_DIRECT:
9511 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9514 case PORT_PROTOCOL_LPR:
9515 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9519 return WERR_UNKNOWN_PORT;
9522 return add_port_hook( token, port1.name, device_uri );
9525 /*******************************************************************
9526 *******************************************************************/
9528 struct xcv_api_table xcvtcp_cmds[] = {
9529 { "MonitorUI", xcvtcp_monitorui },
9530 { "AddPort", xcvtcp_addport},
9534 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9535 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9540 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9542 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9543 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9544 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9547 return WERR_BADFUNC;
9550 /*******************************************************************
9551 *******************************************************************/
9552 #if 0 /* don't support management using the "Local Port" monitor */
9554 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9555 RPC_BUFFER *out, uint32 *needed )
9557 const char *dllname = "localui.dll";
9559 *needed = (strlen(dllname)+1) * 2;
9561 if ( rpcbuf_get_size(out) < *needed ) {
9562 return WERR_INSUFFICIENT_BUFFER;
9565 if ( !make_monitorui_buf( out, dllname )) {
9572 /*******************************************************************
9573 *******************************************************************/
9575 struct xcv_api_table xcvlocal_cmds[] = {
9576 { "MonitorUI", xcvlocal_monitorui },
9580 struct xcv_api_table xcvlocal_cmds[] = {
9587 /*******************************************************************
9588 *******************************************************************/
9590 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9591 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9596 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9598 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9599 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9600 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9602 return WERR_BADFUNC;
9605 /*******************************************************************
9606 *******************************************************************/
9608 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9610 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9614 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9618 /* Has to be a handle to the TCP/IP port monitor */
9620 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9621 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9625 /* requires administrative access to the server */
9627 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9628 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9629 return WERR_ACCESS_DENIED;
9632 /* Get the command name. There's numerous commands supported by the
9633 TCPMON interface. */
9635 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9636 q_u->dataname.uni_str_len*2, 0);
9638 /* Allocate the outgoing buffer */
9640 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9642 switch ( Printer->printer_type ) {
9643 case SPLHND_PORTMON_TCP:
9644 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9645 &q_u->indata, &r_u->outdata, &r_u->needed );
9646 case SPLHND_PORTMON_LOCAL:
9647 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9648 &q_u->indata, &r_u->outdata, &r_u->needed );
9651 return WERR_INVALID_PRINT_MONITOR;