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 /* Table to map the driver version */
46 static const char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 static const char *get_drv_ver_to_os(int ver)
55 if (ver < 0 || ver > 3)
57 return drv_ver_to_os[ver];
61 const char *long_archi;
62 const char *short_archi;
66 static Printer_entry *printers_list;
68 typedef struct _counter_printer_0 {
69 struct _counter_printer_0 *next;
70 struct _counter_printer_0 *prev;
76 static counter_printer_0 *counter_list;
78 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
79 static uint32 smb_connections=0;
82 /* in printing/nt_printing.c */
84 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
96 return JOB_STATUS_PAUSED;
98 return JOB_STATUS_SPOOLING;
100 return JOB_STATUS_PRINTING;
102 return JOB_STATUS_ERROR;
104 return JOB_STATUS_DELETING;
106 return JOB_STATUS_OFFLINE;
108 return JOB_STATUS_PAPEROUT;
110 return JOB_STATUS_PRINTED;
112 return JOB_STATUS_DELETED;
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
121 static int nt_printq_status(int v)
125 return PRINTER_STATUS_PAUSED;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
143 SAFE_FREE((*pp)->ctr.type);
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
171 if (!W_ERROR_IS_OK(result))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 dos_errstr(result)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections==1) {
178 cli_shutdown( notify_cli_pipe->cli );
179 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
181 message_deregister(MSG_PRINTER_NOTIFY2);
183 /* Tell the connections db we're no longer interested in
184 * printer notify messages. */
186 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
192 /****************************************************************************
193 Functions to free a printer entry datastruct.
194 ****************************************************************************/
196 static void free_printer_entry(void *ptr)
198 Printer_entry *Printer = (Printer_entry *)ptr;
200 if (Printer->notify.client_connected==True) {
203 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
205 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
206 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
207 snum = print_queue_snum(Printer->sharename);
209 srv_spoolss_replycloseprinter(snum,
210 &Printer->notify.client_hnd);
214 Printer->notify.flags=0;
215 Printer->notify.options=0;
216 Printer->notify.localmachine[0]='\0';
217 Printer->notify.printerlocal=0;
218 free_spool_notify_option(&Printer->notify.option);
219 Printer->notify.option=NULL;
220 Printer->notify.client_connected=False;
222 free_nt_devicemode( &Printer->nt_devmode );
223 free_a_printer( &Printer->printer_info, 2 );
225 talloc_destroy( Printer->ctx );
227 /* Remove from the internal list. */
228 DLIST_REMOVE(printers_list, Printer);
233 /****************************************************************************
234 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
235 ****************************************************************************/
237 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
239 SPOOL_NOTIFY_OPTION *new_sp = NULL;
244 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
251 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
253 if (!new_sp->ctr.type) {
262 /****************************************************************************
263 find printer index by handle
264 ****************************************************************************/
266 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
268 Printer_entry *find_printer = NULL;
270 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
271 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
278 /****************************************************************************
279 Close printer index by handle.
280 ****************************************************************************/
282 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
284 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
287 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
291 close_policy_hnd(p, hnd);
296 /****************************************************************************
297 Delete a printer given a handle.
298 ****************************************************************************/
299 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
301 char *cmd = lp_deleteprinter_cmd();
304 SE_PRIV se_printop = SE_PRINT_OPERATOR;
305 BOOL is_print_op = False;
307 /* can't fail if we don't try */
312 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
315 is_print_op = user_has_privileges( token, &se_printop );
317 DEBUG(10,("Running [%s]\n", command));
319 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
324 if ( (ret = smbrun(command, NULL)) == 0 ) {
325 /* Tell everyone we updated smb.conf. */
326 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
332 /********** END SePrintOperatorPrivlege BLOCK **********/
334 DEBUGADD(10,("returned [%d]\n", ret));
337 return WERR_BADFID; /* What to return here? */
339 /* go ahead and re-read the services immediately */
340 reload_services( False );
342 if ( lp_servicenumber( sharename ) < 0 )
343 return WERR_ACCESS_DENIED;
348 /****************************************************************************
349 Delete a printer given a handle.
350 ****************************************************************************/
352 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
354 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
357 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
362 * It turns out that Windows allows delete printer on a handle
363 * opened by an admin user, then used on a pipe handle created
364 * by an anonymous user..... but they're working on security.... riiight !
368 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
369 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
370 return WERR_ACCESS_DENIED;
373 /* this does not need a become root since the access check has been
374 done on the handle already */
376 if (del_a_printer( Printer->sharename ) != 0) {
377 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
381 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
384 /****************************************************************************
385 Return the snum of a printer corresponding to an handle.
386 ****************************************************************************/
388 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
390 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
393 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
397 switch (Printer->printer_type) {
398 case PRINTER_HANDLE_IS_PRINTER:
399 DEBUG(4,("short name:%s\n", Printer->sharename));
400 *number = print_queue_snum(Printer->sharename);
401 return (*number != -1);
402 case PRINTER_HANDLE_IS_PRINTSERVER:
409 /****************************************************************************
410 Set printer handle type.
411 Check if it's \\server or \\server\printer
412 ****************************************************************************/
414 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
416 DEBUG(3,("Setting printer type=%s\n", handlename));
418 if ( strlen(handlename) < 3 ) {
419 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
423 /* it's a print server */
424 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
425 DEBUGADD(4,("Printer is a print server\n"));
426 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
430 DEBUGADD(4,("Printer is a printer\n"));
431 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
437 /****************************************************************************
438 Set printer handle name.. Accept names like \\server, \\server\printer,
439 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
440 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
441 XcvDataPort() interface.
442 ****************************************************************************/
444 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
447 int n_services=lp_numservices();
448 char *aprinter, *printername;
449 const char *servername;
452 NT_PRINTER_INFO_LEVEL *printer;
455 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
457 aprinter = handlename;
458 if ( *handlename == '\\' ) {
459 servername = handlename + 2;
460 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
469 /* save the servername to fill in replies on this handle */
471 if ( !is_myname_or_ipaddr( servername ) )
474 fstrcpy( Printer->servername, servername );
476 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
479 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
482 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
484 /* check for the TCPMON interface */
486 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
487 Printer->printer_type = PRINTER_HANDLE_IS_TCPMON;
488 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
492 /* Search all sharenames first as this is easier than pulling
493 the printer_info_2 off of disk. Don't use find_service() since
494 that calls out to map_username() */
496 /* do another loop to look for printernames */
498 for (snum=0; !found && snum<n_services; snum++) {
500 /* no point going on if this is not a printer */
502 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
505 fstrcpy(sname, lp_servicename(snum));
506 if ( strequal( aprinter, sname ) ) {
511 /* no point looking up the printer object if
512 we aren't allowing printername != sharename */
514 if ( lp_force_printername(snum) )
517 fstrcpy(sname, lp_servicename(snum));
520 result = get_a_printer( NULL, &printer, 2, sname );
521 if ( !W_ERROR_IS_OK(result) ) {
522 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
523 sname, dos_errstr(result)));
527 /* printername is always returned as \\server\printername */
528 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
529 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
530 printer->info_2->printername));
531 free_a_printer( &printer, 2);
537 if ( strequal(printername, aprinter) ) {
542 DEBUGADD(10, ("printername: %s\n", printername));
544 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"));
715 if (!spoolss_io_system_time("", &ps, 0, &systime))
718 data->notify_data.data.length = prs_offset(&ps);
719 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
721 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
726 struct notify2_message_table {
728 void (*fn)(struct spoolss_notify_msg *msg,
729 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
732 static struct notify2_message_table printer_notify_table[] = {
733 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
734 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
735 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
736 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
737 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
738 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
739 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
740 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
741 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
742 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
743 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
744 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
745 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
746 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
747 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
748 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
749 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
750 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
751 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
754 static struct notify2_message_table job_notify_table[] = {
755 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
756 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
757 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
758 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
759 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
760 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
761 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
762 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
763 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
764 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
765 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
766 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
767 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
768 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
769 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
770 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
771 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
772 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
773 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
774 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
775 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
776 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
777 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
778 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
782 /***********************************************************************
783 Allocate talloc context for container object
784 **********************************************************************/
786 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
791 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
796 /***********************************************************************
797 release all allocated memory and zero out structure
798 **********************************************************************/
800 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
806 talloc_destroy(ctr->ctx);
813 /***********************************************************************
814 **********************************************************************/
816 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
824 /***********************************************************************
825 **********************************************************************/
827 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
829 if ( !ctr || !ctr->msg_groups )
832 if ( idx >= ctr->num_groups )
835 return &ctr->msg_groups[idx];
839 /***********************************************************************
840 How many groups of change messages do we have ?
841 **********************************************************************/
843 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
848 return ctr->num_groups;
851 /***********************************************************************
852 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
853 **********************************************************************/
855 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
857 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
858 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
859 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
865 /* loop over all groups looking for a matching printer name */
867 for ( i=0; i<ctr->num_groups; i++ ) {
868 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
872 /* add a new group? */
874 if ( i == ctr->num_groups ) {
877 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
878 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
881 ctr->msg_groups = groups;
883 /* clear the new entry and set the printer name */
885 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
886 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
889 /* add the change messages; 'i' is the correct index now regardless */
891 msg_grp = &ctr->msg_groups[i];
895 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
896 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
899 msg_grp->msgs = msg_list;
901 new_slot = msg_grp->num_msgs-1;
902 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
904 /* need to allocate own copy of data */
907 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
909 return ctr->num_groups;
912 /***********************************************************************
913 Send a change notication message on all handles which have a call
915 **********************************************************************/
917 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
920 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
921 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
922 SPOOLSS_NOTIFY_MSG *messages;
923 int sending_msg_count;
926 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
930 messages = msg_group->msgs;
933 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
937 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
939 /* loop over all printers */
941 for (p = printers_list; p; p = p->next) {
942 SPOOL_NOTIFY_INFO_DATA *data;
947 /* Is there notification on this handle? */
949 if ( !p->notify.client_connected )
952 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
954 /* For this printer? Print servers always receive
957 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
958 ( !strequal(msg_group->printername, p->sharename) ) )
961 DEBUG(10,("Our printer\n"));
963 /* allocate the max entries possible */
965 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
968 /* build the array of change notifications */
970 sending_msg_count = 0;
972 for ( i=0; i<msg_group->num_msgs; i++ ) {
973 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
975 /* Are we monitoring this event? */
977 if (!is_monitoring_event(p, msg->type, msg->field))
983 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
984 msg->type, msg->field, p->sharename));
987 * if the is a printer notification handle and not a job notification
988 * type, then set the id to 0. Other wise just use what was specified
991 * When registering change notification on a print server handle
992 * we always need to send back the id (snum) matching the printer
993 * for which the change took place. For change notify registered
994 * on a printer handle, this does not matter and the id should be 0.
999 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1005 /* Convert unix jobid to smb jobid */
1007 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1008 id = sysjob_to_jobid(msg->id);
1011 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1016 construct_info_data( &data[data_len], msg->type, msg->field, id );
1019 case PRINTER_NOTIFY_TYPE:
1020 if ( printer_notify_table[msg->field].fn )
1021 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1024 case JOB_NOTIFY_TYPE:
1025 if ( job_notify_table[msg->field].fn )
1026 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1030 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1037 if ( sending_msg_count ) {
1038 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1039 data_len, data, p->notify.change, 0 );
1044 DEBUG(8,("send_notify2_changes: Exit...\n"));
1048 /***********************************************************************
1049 **********************************************************************/
1051 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1054 uint32 tv_sec, tv_usec;
1057 /* Unpack message */
1059 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1062 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1064 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1067 tdb_unpack((char *)buf + offset, len - offset, "dd",
1068 &msg->notify.value[0], &msg->notify.value[1]);
1070 tdb_unpack((char *)buf + offset, len - offset, "B",
1071 &msg->len, &msg->notify.data);
1073 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1074 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1076 tv->tv_sec = tv_sec;
1077 tv->tv_usec = tv_usec;
1080 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1081 msg->notify.value[1]));
1083 dump_data(3, msg->notify.data, msg->len);
1088 /********************************************************************
1089 Receive a notify2 message list
1090 ********************************************************************/
1092 static void receive_notify2_message_list(int msg_type, struct process_id src,
1093 void *msg, size_t len)
1095 size_t msg_count, i;
1096 char *buf = (char *)msg;
1099 SPOOLSS_NOTIFY_MSG notify;
1100 SPOOLSS_NOTIFY_MSG_CTR messages;
1104 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1108 msg_count = IVAL(buf, 0);
1111 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1113 if (msg_count == 0) {
1114 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1118 /* initialize the container */
1120 ZERO_STRUCT( messages );
1121 notify_msg_ctr_init( &messages );
1124 * build message groups for each printer identified
1125 * in a change_notify msg. Remember that a PCN message
1126 * includes the handle returned for the srv_spoolss_replyopenprinter()
1127 * call. Therefore messages are grouped according to printer handle.
1130 for ( i=0; i<msg_count; i++ ) {
1131 struct timeval msg_tv;
1133 if (msg_ptr + 4 - buf > len) {
1134 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1138 msg_len = IVAL(msg_ptr,0);
1141 if (msg_ptr + msg_len - buf > len) {
1142 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1146 /* unpack messages */
1148 ZERO_STRUCT( notify );
1149 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1152 /* add to correct list in container */
1154 notify_msg_ctr_addmsg( &messages, ¬ify );
1156 /* free memory that might have been allocated by notify2_unpack_msg() */
1158 if ( notify.len != 0 )
1159 SAFE_FREE( notify.notify.data );
1162 /* process each group of messages */
1164 num_groups = notify_msg_ctr_numgroups( &messages );
1165 for ( i=0; i<num_groups; i++ )
1166 send_notify2_changes( &messages, i );
1171 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1173 notify_msg_ctr_destroy( &messages );
1178 /********************************************************************
1179 Send a message to ourself about new driver being installed
1180 so we can upgrade the information for each printer bound to this
1182 ********************************************************************/
1184 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1186 int len = strlen(drivername);
1191 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1194 message_send_pid(pid_to_procid(sys_getpid()),
1195 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1200 /**********************************************************************
1201 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1202 over all printers, upgrading ones as necessary
1203 **********************************************************************/
1205 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1209 int n_services = lp_numservices();
1211 len = MIN(len,sizeof(drivername)-1);
1212 strncpy(drivername, buf, len);
1214 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1216 /* Iterate the printer list */
1218 for (snum=0; snum<n_services; snum++)
1220 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1223 NT_PRINTER_INFO_LEVEL *printer = NULL;
1225 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1226 if (!W_ERROR_IS_OK(result))
1229 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1231 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1233 /* all we care about currently is the change_id */
1235 result = mod_a_printer(printer, 2);
1236 if (!W_ERROR_IS_OK(result)) {
1237 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1238 dos_errstr(result)));
1242 free_a_printer(&printer, 2);
1249 /********************************************************************
1250 Update the cache for all printq's with a registered client
1252 ********************************************************************/
1254 void update_monitored_printq_cache( void )
1256 Printer_entry *printer = printers_list;
1259 /* loop through all printers and update the cache where
1260 client_connected == True */
1263 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1264 && printer->notify.client_connected )
1266 snum = print_queue_snum(printer->sharename);
1267 print_queue_status( snum, NULL, NULL );
1270 printer = printer->next;
1275 /********************************************************************
1276 Send a message to ourself about new driver being installed
1277 so we can upgrade the information for each printer bound to this
1279 ********************************************************************/
1281 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1283 int len = strlen(drivername);
1288 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1291 message_send_pid(pid_to_procid(sys_getpid()),
1292 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1297 /**********************************************************************
1298 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1299 over all printers, resetting printer data as neessary
1300 **********************************************************************/
1302 void reset_all_printerdata(int msg_type, struct process_id src,
1303 void *buf, size_t len)
1307 int n_services = lp_numservices();
1309 len = MIN( len, sizeof(drivername)-1 );
1310 strncpy( drivername, buf, len );
1312 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1314 /* Iterate the printer list */
1316 for ( snum=0; snum<n_services; snum++ )
1318 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1321 NT_PRINTER_INFO_LEVEL *printer = NULL;
1323 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1324 if ( !W_ERROR_IS_OK(result) )
1328 * if the printer is bound to the driver,
1329 * then reset to the new driver initdata
1332 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1334 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1336 if ( !set_driver_init(printer, 2) ) {
1337 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1338 printer->info_2->printername, printer->info_2->drivername));
1341 result = mod_a_printer( printer, 2 );
1342 if ( !W_ERROR_IS_OK(result) ) {
1343 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1344 get_dos_error_msg(result)));
1348 free_a_printer( &printer, 2 );
1357 /********************************************************************
1358 Copy routines used by convert_to_openprinterex()
1359 *******************************************************************/
1361 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1369 DEBUG (8,("dup_devmode\n"));
1371 /* bulk copy first */
1373 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1377 /* dup the pointer members separately */
1379 len = unistrlen(devmode->devicename.buffer);
1381 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1382 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1387 len = unistrlen(devmode->formname.buffer);
1389 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1390 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1394 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1399 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1401 if (!new_ctr || !ctr)
1404 DEBUG(8,("copy_devmode_ctr\n"));
1406 new_ctr->size = ctr->size;
1407 new_ctr->devmode_ptr = ctr->devmode_ptr;
1409 if(ctr->devmode_ptr)
1410 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1413 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1415 if (!new_def || !def)
1418 DEBUG(8,("copy_printer_defaults\n"));
1420 new_def->datatype_ptr = def->datatype_ptr;
1422 if (def->datatype_ptr)
1423 copy_unistr2(&new_def->datatype, &def->datatype);
1425 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1427 new_def->access_required = def->access_required;
1430 /********************************************************************
1431 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1432 * SPOOL_Q_OPEN_PRINTER_EX structure
1433 ********************************************************************/
1435 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1437 if (!q_u_ex || !q_u)
1440 DEBUG(8,("convert_to_openprinterex\n"));
1442 if ( q_u->printername ) {
1443 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1444 if (q_u_ex->printername == NULL)
1446 copy_unistr2(q_u_ex->printername, q_u->printername);
1449 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1454 /********************************************************************
1455 * spoolss_open_printer
1457 * called from the spoolss dispatcher
1458 ********************************************************************/
1460 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1462 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1463 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1468 ZERO_STRUCT(q_u_ex);
1469 ZERO_STRUCT(r_u_ex);
1471 /* convert the OpenPrinter() call to OpenPrinterEx() */
1473 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1474 if (!W_ERROR_IS_OK(r_u_ex.status))
1475 return r_u_ex.status;
1477 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1479 /* convert back to OpenPrinter() */
1481 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1486 /********************************************************************
1487 ********************************************************************/
1489 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1491 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1492 POLICY_HND *handle = &r_u->handle;
1496 struct current_user user;
1497 Printer_entry *Printer=NULL;
1499 if ( !q_u->printername )
1500 return WERR_INVALID_PRINTER_NAME;
1502 /* some sanity check because you can open a printer or a print server */
1503 /* aka: \\server\printer or \\server */
1505 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1507 DEBUGADD(3,("checking name: %s\n",name));
1509 if (!open_printer_hnd(p, handle, name, 0))
1510 return WERR_INVALID_PRINTER_NAME;
1512 Printer=find_printer_index_by_hnd(p, handle);
1514 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1515 "handle we created for printer %s\n", name ));
1516 close_printer_handle(p,handle);
1517 return WERR_INVALID_PRINTER_NAME;
1520 get_current_user(&user, p);
1523 * First case: the user is opening the print server:
1525 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1526 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1528 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1529 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1530 * or if the user is listed in the smb.conf printer admin parameter.
1532 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1533 * client view printer folder, but does not show the MSAPW.
1535 * Note: this test needs code to check access rights here too. Jeremy
1536 * could you look at this?
1538 * Second case: the user is opening a printer:
1539 * NT doesn't let us connect to a printer if the connecting user
1540 * doesn't have print permission.
1542 * Third case: user is opening the TCP/IP port monitor
1543 * access checks same as opening a handle to the print server.
1546 switch (Printer->printer_type )
1548 case PRINTER_HANDLE_IS_PRINTSERVER:
1549 case PRINTER_HANDLE_IS_TCPMON:
1550 /* Printserver handles use global struct... */
1554 /* Map standard access rights to object specific access rights */
1556 se_map_standard(&printer_default->access_required,
1557 &printserver_std_mapping);
1559 /* Deny any object specific bits that don't apply to print
1560 servers (i.e printer and job specific bits) */
1562 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1564 if (printer_default->access_required &
1565 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1566 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1567 close_printer_handle(p, handle);
1568 return WERR_ACCESS_DENIED;
1571 /* Allow admin access */
1573 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1575 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1577 if (!lp_ms_add_printer_wizard()) {
1578 close_printer_handle(p, handle);
1579 return WERR_ACCESS_DENIED;
1582 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1583 and not a printer admin, then fail */
1585 if ((user.ut.uid != 0) &&
1586 !user_has_privileges(user.nt_user_token,
1588 !token_contains_name_in_list(
1589 uidtoname(user.ut.uid), NULL,
1591 lp_printer_admin(snum))) {
1592 close_printer_handle(p, handle);
1593 return WERR_ACCESS_DENIED;
1596 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1600 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1603 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1604 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1606 /* We fall through to return WERR_OK */
1609 case PRINTER_HANDLE_IS_PRINTER:
1610 /* NT doesn't let us connect to a printer if the connecting user
1611 doesn't have print permission. */
1613 if (!get_printer_snum(p, handle, &snum)) {
1614 close_printer_handle(p, handle);
1618 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1620 /* map an empty access mask to the minimum access mask */
1621 if (printer_default->access_required == 0x0)
1622 printer_default->access_required = PRINTER_ACCESS_USE;
1625 * If we are not serving the printer driver for this printer,
1626 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1627 * will keep NT clients happy --jerry
1630 if (lp_use_client_driver(snum)
1631 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1633 printer_default->access_required = PRINTER_ACCESS_USE;
1636 /* check smb.conf parameters and the the sec_desc */
1638 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1639 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1640 return WERR_ACCESS_DENIED;
1643 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1645 !print_access_check(&user, snum,
1646 printer_default->access_required)) {
1647 DEBUG(3, ("access DENIED for printer open\n"));
1648 close_printer_handle(p, handle);
1649 return WERR_ACCESS_DENIED;
1652 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1653 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1654 close_printer_handle(p, handle);
1655 return WERR_ACCESS_DENIED;
1658 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1659 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1661 printer_default->access_required = PRINTER_ACCESS_USE;
1663 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1664 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1669 /* sanity check to prevent programmer error */
1673 Printer->access_granted = printer_default->access_required;
1676 * If the client sent a devmode in the OpenPrinter() call, then
1677 * save it here in case we get a job submission on this handle
1680 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1681 && q_u->printer_default.devmode_cont.devmode_ptr )
1683 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1684 &Printer->nt_devmode );
1687 #if 0 /* JERRY -- I'm doubtful this is really effective */
1688 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1689 optimization in Windows 2000 clients --jerry */
1691 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1692 && (RA_WIN2K == get_remote_arch()) )
1694 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1695 sys_usleep( 500000 );
1702 /****************************************************************************
1703 ****************************************************************************/
1705 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1706 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1712 /* allocate memory if needed. Messy because
1713 convert_printer_info is used to update an existing
1714 printer or build a new one */
1716 if ( !printer->info_2 ) {
1717 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1718 if ( !printer->info_2 ) {
1719 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1724 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1725 printer->info_2->setuptime = time(NULL);
1733 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1734 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1740 printer->info_3=NULL;
1741 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1745 printer->info_6=NULL;
1746 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1756 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1757 NT_DEVICEMODE **pp_nt_devmode)
1759 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1762 * Ensure nt_devmode is a valid pointer
1763 * as we will be overwriting it.
1766 if (nt_devmode == NULL) {
1767 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1768 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1772 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1773 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1775 nt_devmode->specversion=devmode->specversion;
1776 nt_devmode->driverversion=devmode->driverversion;
1777 nt_devmode->size=devmode->size;
1778 nt_devmode->fields=devmode->fields;
1779 nt_devmode->orientation=devmode->orientation;
1780 nt_devmode->papersize=devmode->papersize;
1781 nt_devmode->paperlength=devmode->paperlength;
1782 nt_devmode->paperwidth=devmode->paperwidth;
1783 nt_devmode->scale=devmode->scale;
1784 nt_devmode->copies=devmode->copies;
1785 nt_devmode->defaultsource=devmode->defaultsource;
1786 nt_devmode->printquality=devmode->printquality;
1787 nt_devmode->color=devmode->color;
1788 nt_devmode->duplex=devmode->duplex;
1789 nt_devmode->yresolution=devmode->yresolution;
1790 nt_devmode->ttoption=devmode->ttoption;
1791 nt_devmode->collate=devmode->collate;
1793 nt_devmode->logpixels=devmode->logpixels;
1794 nt_devmode->bitsperpel=devmode->bitsperpel;
1795 nt_devmode->pelswidth=devmode->pelswidth;
1796 nt_devmode->pelsheight=devmode->pelsheight;
1797 nt_devmode->displayflags=devmode->displayflags;
1798 nt_devmode->displayfrequency=devmode->displayfrequency;
1799 nt_devmode->icmmethod=devmode->icmmethod;
1800 nt_devmode->icmintent=devmode->icmintent;
1801 nt_devmode->mediatype=devmode->mediatype;
1802 nt_devmode->dithertype=devmode->dithertype;
1803 nt_devmode->reserved1=devmode->reserved1;
1804 nt_devmode->reserved2=devmode->reserved2;
1805 nt_devmode->panningwidth=devmode->panningwidth;
1806 nt_devmode->panningheight=devmode->panningheight;
1809 * Only change private and driverextra if the incoming devmode
1810 * has a new one. JRA.
1813 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1814 SAFE_FREE(nt_devmode->nt_dev_private);
1815 nt_devmode->driverextra=devmode->driverextra;
1816 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1818 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1821 *pp_nt_devmode = nt_devmode;
1826 /********************************************************************
1827 * _spoolss_enddocprinter_internal.
1828 ********************************************************************/
1830 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1832 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1836 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1840 if (!get_printer_snum(p, handle, &snum))
1843 Printer->document_started=False;
1844 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1845 /* error codes unhandled so far ... */
1850 /********************************************************************
1851 * api_spoolss_closeprinter
1852 ********************************************************************/
1854 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1856 POLICY_HND *handle = &q_u->handle;
1858 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1860 if (Printer && Printer->document_started)
1861 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1863 if (!close_printer_handle(p, handle))
1866 /* clear the returned printer handle. Observed behavior
1867 from Win2k server. Don't think this really matters.
1868 Previous code just copied the value of the closed
1871 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1876 /********************************************************************
1877 * api_spoolss_deleteprinter
1879 ********************************************************************/
1881 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1883 POLICY_HND *handle = &q_u->handle;
1884 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1887 if (Printer && Printer->document_started)
1888 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1890 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1892 result = delete_printer_handle(p, handle);
1894 update_c_setprinter(False);
1899 /*******************************************************************
1900 * static function to lookup the version id corresponding to an
1901 * long architecture string
1902 ******************************************************************/
1904 static int get_version_id (char * arch)
1907 struct table_node archi_table[]= {
1909 {"Windows 4.0", "WIN40", 0 },
1910 {"Windows NT x86", "W32X86", 2 },
1911 {"Windows NT R4000", "W32MIPS", 2 },
1912 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1913 {"Windows NT PowerPC", "W32PPC", 2 },
1914 {"Windows IA64", "IA64", 3 },
1915 {"Windows x64", "x64", 3 },
1919 for (i=0; archi_table[i].long_archi != NULL; i++)
1921 if (strcmp(arch, archi_table[i].long_archi) == 0)
1922 return (archi_table[i].version);
1928 /********************************************************************
1929 * _spoolss_deleteprinterdriver
1930 ********************************************************************/
1932 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1936 NT_PRINTER_DRIVER_INFO_LEVEL info;
1937 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1939 struct current_user user;
1941 WERROR status_win2k = WERR_ACCESS_DENIED;
1942 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1944 get_current_user(&user, p);
1946 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1947 and not a printer admin, then fail */
1949 if ( (user.ut.uid != 0)
1950 && !user_has_privileges(user.nt_user_token, &se_printop )
1951 && !token_contains_name_in_list( uidtoname(user.ut.uid),
1952 NULL, user.nt_user_token, lp_printer_admin(-1)) )
1954 return WERR_ACCESS_DENIED;
1957 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1958 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1960 /* check that we have a valid driver name first */
1962 if ((version=get_version_id(arch)) == -1)
1963 return WERR_INVALID_ENVIRONMENT;
1966 ZERO_STRUCT(info_win2k);
1968 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1970 /* try for Win2k driver if "Windows NT x86" */
1972 if ( version == 2 ) {
1974 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1975 status = WERR_UNKNOWN_PRINTER_DRIVER;
1979 /* otherwise it was a failure */
1981 status = WERR_UNKNOWN_PRINTER_DRIVER;
1987 if (printer_driver_in_use(info.info_3)) {
1988 status = WERR_PRINTER_DRIVER_IN_USE;
1994 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1996 /* if we get to here, we now have 2 driver info structures to remove */
1997 /* remove the Win2k driver first*/
1999 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2000 free_a_printer_driver( info_win2k, 3 );
2002 /* this should not have failed---if it did, report to client */
2003 if ( !W_ERROR_IS_OK(status_win2k) )
2005 status = status_win2k;
2011 status = delete_printer_driver(info.info_3, &user, version, False);
2013 /* if at least one of the deletes succeeded return OK */
2015 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2019 free_a_printer_driver( info, 3 );
2024 /********************************************************************
2025 * spoolss_deleteprinterdriverex
2026 ********************************************************************/
2028 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2032 NT_PRINTER_DRIVER_INFO_LEVEL info;
2033 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2035 uint32 flags = q_u->delete_flags;
2037 struct current_user user;
2039 WERROR status_win2k = WERR_ACCESS_DENIED;
2040 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2042 get_current_user(&user, p);
2044 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2045 and not a printer admin, then fail */
2047 if ( (user.ut.uid != 0)
2048 && !user_has_privileges(user.nt_user_token, &se_printop )
2049 && !token_contains_name_in_list( uidtoname(user.ut.uid),
2050 NULL, user.nt_user_token, lp_printer_admin(-1)) )
2052 return WERR_ACCESS_DENIED;
2055 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2056 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2058 /* check that we have a valid driver name first */
2059 if ((version=get_version_id(arch)) == -1) {
2060 /* this is what NT returns */
2061 return WERR_INVALID_ENVIRONMENT;
2064 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2065 version = q_u->version;
2068 ZERO_STRUCT(info_win2k);
2070 status = get_a_printer_driver(&info, 3, driver, arch, version);
2072 if ( !W_ERROR_IS_OK(status) )
2075 * if the client asked for a specific version,
2076 * or this is something other than Windows NT x86,
2080 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2083 /* try for Win2k driver if "Windows NT x86" */
2086 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2087 status = WERR_UNKNOWN_PRINTER_DRIVER;
2092 if ( printer_driver_in_use(info.info_3) ) {
2093 status = WERR_PRINTER_DRIVER_IN_USE;
2098 * we have a couple of cases to consider.
2099 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2100 * then the delete should fail if **any** files overlap with
2102 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2103 * non-overlapping files
2104 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2105 * is set, the do not delete any files
2106 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2109 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2111 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2113 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2114 /* no idea of the correct error here */
2115 status = WERR_ACCESS_DENIED;
2120 /* also check for W32X86/3 if necessary; maybe we already have? */
2122 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2123 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2126 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2127 /* no idea of the correct error here */
2128 free_a_printer_driver( info_win2k, 3 );
2129 status = WERR_ACCESS_DENIED;
2133 /* if we get to here, we now have 2 driver info structures to remove */
2134 /* remove the Win2k driver first*/
2136 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2137 free_a_printer_driver( info_win2k, 3 );
2139 /* this should not have failed---if it did, report to client */
2141 if ( !W_ERROR_IS_OK(status_win2k) )
2146 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2148 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2151 free_a_printer_driver( info, 3 );
2157 /****************************************************************************
2158 Internal routine for retreiving printerdata
2159 ***************************************************************************/
2161 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2162 const char *key, const char *value, uint32 *type, uint8 **data,
2163 uint32 *needed, uint32 in_size )
2165 REGISTRY_VALUE *val;
2169 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2170 return WERR_BADFILE;
2172 *type = regval_type( val );
2174 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2176 size = regval_size( val );
2178 /* copy the min(in_size, len) */
2181 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2183 /* special case for 0 length values */
2185 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2189 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2198 DEBUG(5,("get_printer_dataex: copy done\n"));
2203 /****************************************************************************
2204 Internal routine for removing printerdata
2205 ***************************************************************************/
2207 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2209 return delete_printer_data( printer->info_2, key, value );
2212 /****************************************************************************
2213 Internal routine for storing printerdata
2214 ***************************************************************************/
2216 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2217 uint32 type, uint8 *data, int real_len )
2219 /* the registry objects enforce uniqueness based on value name */
2221 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2224 /********************************************************************
2225 GetPrinterData on a printer server Handle.
2226 ********************************************************************/
2228 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2232 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2234 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2236 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2242 if (!StrCaseCmp(value, "BeepEnabled")) {
2244 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2246 SIVAL(*data, 0, 0x00);
2251 if (!StrCaseCmp(value, "EventLog")) {
2253 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2255 /* formally was 0x1b */
2256 SIVAL(*data, 0, 0x0);
2261 if (!StrCaseCmp(value, "NetPopup")) {
2263 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2265 SIVAL(*data, 0, 0x00);
2270 if (!StrCaseCmp(value, "MajorVersion")) {
2272 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2275 /* Windows NT 4.0 seems to not allow uploading of drivers
2276 to a server that reports 0x3 as the MajorVersion.
2277 need to investigate more how Win2k gets around this .
2280 if ( RA_WINNT == get_remote_arch() )
2289 if (!StrCaseCmp(value, "MinorVersion")) {
2291 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2299 * uint32 size = 0x114
2301 * uint32 minor = [0|1]
2302 * uint32 build = [2195|2600]
2303 * extra unicode string = e.g. "Service Pack 3"
2305 if (!StrCaseCmp(value, "OSVersion")) {
2309 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2312 SIVAL(*data, 0, *needed); /* size */
2313 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2315 SIVAL(*data, 12, 2195); /* build */
2317 /* leave extra string empty */
2323 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2324 const char *string="C:\\PRINTERS";
2326 *needed = 2*(strlen(string)+1);
2327 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2329 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2331 /* it's done by hand ready to go on the wire */
2332 for (i=0; i<strlen(string); i++) {
2333 (*data)[2*i]=string[i];
2334 (*data)[2*i+1]='\0';
2339 if (!StrCaseCmp(value, "Architecture")) {
2340 const char *string="Windows NT x86";
2342 *needed = 2*(strlen(string)+1);
2343 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2345 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2346 for (i=0; i<strlen(string); i++) {
2347 (*data)[2*i]=string[i];
2348 (*data)[2*i+1]='\0';
2353 if (!StrCaseCmp(value, "DsPresent")) {
2355 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2358 /* only show the publish check box if we are a
2359 memeber of a AD domain */
2361 if ( lp_security() == SEC_ADS )
2362 SIVAL(*data, 0, 0x01);
2364 SIVAL(*data, 0, 0x00);
2370 if (!StrCaseCmp(value, "DNSMachineName")) {
2373 if (!get_mydnsfullname(hostname))
2374 return WERR_BADFILE;
2376 *needed = 2*(strlen(hostname)+1);
2377 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2379 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2380 for (i=0; i<strlen(hostname); i++) {
2381 (*data)[2*i]=hostname[i];
2382 (*data)[2*i+1]='\0';
2388 return WERR_BADFILE;
2391 /********************************************************************
2392 * spoolss_getprinterdata
2393 ********************************************************************/
2395 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2397 POLICY_HND *handle = &q_u->handle;
2398 UNISTR2 *valuename = &q_u->valuename;
2399 uint32 in_size = q_u->size;
2400 uint32 *type = &r_u->type;
2401 uint32 *out_size = &r_u->size;
2402 uint8 **data = &r_u->data;
2403 uint32 *needed = &r_u->needed;
2406 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2407 NT_PRINTER_INFO_LEVEL *printer = NULL;
2411 * Reminder: when it's a string, the length is in BYTES
2412 * even if UNICODE is negociated.
2417 *out_size = in_size;
2419 /* in case of problem, return some default values */
2424 DEBUG(4,("_spoolss_getprinterdata\n"));
2427 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2428 status = WERR_BADFID;
2432 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2434 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2435 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2438 if ( !get_printer_snum(p,handle, &snum) ) {
2439 status = WERR_BADFID;
2443 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2444 if ( !W_ERROR_IS_OK(status) )
2447 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2449 if ( strequal(value, "ChangeId") ) {
2451 *needed = sizeof(uint32);
2452 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2453 status = WERR_NOMEM;
2456 SIVAL( *data, 0, printer->info_2->changeid );
2460 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2463 if (*needed > *out_size)
2464 status = WERR_MORE_DATA;
2467 if ( !W_ERROR_IS_OK(status) )
2469 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2471 /* reply this param doesn't exist */
2474 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2476 free_a_printer( &printer, 2 );
2485 /* cleanup & exit */
2488 free_a_printer( &printer, 2 );
2493 /*********************************************************
2494 Connect to the client machine.
2495 **********************************************************/
2497 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2498 struct in_addr *client_ip, const char *remote_machine)
2501 struct cli_state *the_cli;
2502 struct in_addr rm_addr;
2504 if ( is_zero_ip(*client_ip) ) {
2505 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2506 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2510 if ( ismyip( rm_addr )) {
2511 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2515 rm_addr.s_addr = client_ip->s_addr;
2516 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2517 inet_ntoa(*client_ip) ));
2520 /* setup the connection */
2522 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2523 &rm_addr, 0, "IPC$", "IPC",
2527 0, lp_client_signing(), NULL );
2529 if ( !NT_STATUS_IS_OK( ret ) ) {
2530 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2535 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2536 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2537 cli_shutdown(the_cli);
2542 * Ok - we have an anonymous connection to the IPC$ share.
2543 * Now start the NT Domain stuff :-).
2546 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2547 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2548 remote_machine, nt_errstr(ret)));
2549 cli_shutdown(the_cli);
2553 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2555 (*pp_pipe)->cli = the_cli;
2560 /***************************************************************************
2561 Connect to the client.
2562 ****************************************************************************/
2564 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2565 uint32 localprinter, uint32 type,
2566 POLICY_HND *handle, struct in_addr *client_ip)
2571 * If it's the first connection, contact the client
2572 * and connect to the IPC$ share anonymously
2574 if (smb_connections==0) {
2575 fstring unix_printer;
2577 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2579 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2582 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2583 /* Tell the connections db we're now interested in printer
2584 * notify messages. */
2585 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2589 * Tell the specific printing tdb we want messages for this printer
2590 * by registering our PID.
2593 if (!print_notify_register_pid(snum))
2594 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2598 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2601 if (!W_ERROR_IS_OK(result))
2602 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2603 dos_errstr(result)));
2605 return (W_ERROR_IS_OK(result));
2608 /********************************************************************
2610 * ReplyFindFirstPrinterChangeNotifyEx
2612 * before replying OK: status=0 a rpc call is made to the workstation
2613 * asking ReplyOpenPrinter
2615 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2616 * called from api_spoolss_rffpcnex
2617 ********************************************************************/
2619 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2621 POLICY_HND *handle = &q_u->handle;
2622 uint32 flags = q_u->flags;
2623 uint32 options = q_u->options;
2624 UNISTR2 *localmachine = &q_u->localmachine;
2625 uint32 printerlocal = q_u->printerlocal;
2627 SPOOL_NOTIFY_OPTION *option = q_u->option;
2628 struct in_addr client_ip;
2630 /* store the notify value in the printer struct */
2632 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2635 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2639 Printer->notify.flags=flags;
2640 Printer->notify.options=options;
2641 Printer->notify.printerlocal=printerlocal;
2643 if (Printer->notify.option)
2644 free_spool_notify_option(&Printer->notify.option);
2646 Printer->notify.option=dup_spool_notify_option(option);
2648 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2649 sizeof(Printer->notify.localmachine)-1);
2651 /* Connect to the client machine and send a ReplyOpenPrinter */
2653 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2655 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2656 !get_printer_snum(p, handle, &snum) )
2659 client_ip.s_addr = inet_addr(p->conn->client_address);
2661 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2662 Printer->notify.printerlocal, 1,
2663 &Printer->notify.client_hnd, &client_ip))
2664 return WERR_SERVER_UNAVAILABLE;
2666 Printer->notify.client_connected=True;
2671 /*******************************************************************
2672 * fill a notify_info_data with the servername
2673 ********************************************************************/
2675 void spoolss_notify_server_name(int snum,
2676 SPOOL_NOTIFY_INFO_DATA *data,
2677 print_queue_struct *queue,
2678 NT_PRINTER_INFO_LEVEL *printer,
2679 TALLOC_CTX *mem_ctx)
2684 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2686 data->notify_data.data.length = len;
2687 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2689 if (!data->notify_data.data.string) {
2690 data->notify_data.data.length = 0;
2694 memcpy(data->notify_data.data.string, temp, len);
2697 /*******************************************************************
2698 * fill a notify_info_data with the printername (not including the servername).
2699 ********************************************************************/
2701 void spoolss_notify_printer_name(int snum,
2702 SPOOL_NOTIFY_INFO_DATA *data,
2703 print_queue_struct *queue,
2704 NT_PRINTER_INFO_LEVEL *printer,
2705 TALLOC_CTX *mem_ctx)
2710 /* the notify name should not contain the \\server\ part */
2711 char *p = strrchr(printer->info_2->printername, '\\');
2714 p = printer->info_2->printername;
2719 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2721 data->notify_data.data.length = len;
2722 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2724 if (!data->notify_data.data.string) {
2725 data->notify_data.data.length = 0;
2729 memcpy(data->notify_data.data.string, temp, len);
2732 /*******************************************************************
2733 * fill a notify_info_data with the servicename
2734 ********************************************************************/
2736 void spoolss_notify_share_name(int snum,
2737 SPOOL_NOTIFY_INFO_DATA *data,
2738 print_queue_struct *queue,
2739 NT_PRINTER_INFO_LEVEL *printer,
2740 TALLOC_CTX *mem_ctx)
2745 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2747 data->notify_data.data.length = len;
2748 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2750 if (!data->notify_data.data.string) {
2751 data->notify_data.data.length = 0;
2755 memcpy(data->notify_data.data.string, temp, len);
2758 /*******************************************************************
2759 * fill a notify_info_data with the port name
2760 ********************************************************************/
2762 void spoolss_notify_port_name(int snum,
2763 SPOOL_NOTIFY_INFO_DATA *data,
2764 print_queue_struct *queue,
2765 NT_PRINTER_INFO_LEVEL *printer,
2766 TALLOC_CTX *mem_ctx)
2771 /* even if it's strange, that's consistant in all the code */
2773 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2775 data->notify_data.data.length = len;
2776 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2778 if (!data->notify_data.data.string) {
2779 data->notify_data.data.length = 0;
2783 memcpy(data->notify_data.data.string, temp, len);
2786 /*******************************************************************
2787 * fill a notify_info_data with the printername
2788 * but it doesn't exist, have to see what to do
2789 ********************************************************************/
2791 void spoolss_notify_driver_name(int snum,
2792 SPOOL_NOTIFY_INFO_DATA *data,
2793 print_queue_struct *queue,
2794 NT_PRINTER_INFO_LEVEL *printer,
2795 TALLOC_CTX *mem_ctx)
2800 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2802 data->notify_data.data.length = len;
2803 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2805 if (!data->notify_data.data.string) {
2806 data->notify_data.data.length = 0;
2810 memcpy(data->notify_data.data.string, temp, len);
2813 /*******************************************************************
2814 * fill a notify_info_data with the comment
2815 ********************************************************************/
2817 void spoolss_notify_comment(int snum,
2818 SPOOL_NOTIFY_INFO_DATA *data,
2819 print_queue_struct *queue,
2820 NT_PRINTER_INFO_LEVEL *printer,
2821 TALLOC_CTX *mem_ctx)
2826 if (*printer->info_2->comment == '\0')
2827 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2829 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2831 data->notify_data.data.length = len;
2832 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2834 if (!data->notify_data.data.string) {
2835 data->notify_data.data.length = 0;
2839 memcpy(data->notify_data.data.string, temp, len);
2842 /*******************************************************************
2843 * fill a notify_info_data with the comment
2844 * location = "Room 1, floor 2, building 3"
2845 ********************************************************************/
2847 void spoolss_notify_location(int snum,
2848 SPOOL_NOTIFY_INFO_DATA *data,
2849 print_queue_struct *queue,
2850 NT_PRINTER_INFO_LEVEL *printer,
2851 TALLOC_CTX *mem_ctx)
2856 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2858 data->notify_data.data.length = len;
2859 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2861 if (!data->notify_data.data.string) {
2862 data->notify_data.data.length = 0;
2866 memcpy(data->notify_data.data.string, temp, len);
2869 /*******************************************************************
2870 * fill a notify_info_data with the device mode
2871 * jfm:xxxx don't to it for know but that's a real problem !!!
2872 ********************************************************************/
2874 static void spoolss_notify_devmode(int snum,
2875 SPOOL_NOTIFY_INFO_DATA *data,
2876 print_queue_struct *queue,
2877 NT_PRINTER_INFO_LEVEL *printer,
2878 TALLOC_CTX *mem_ctx)
2882 /*******************************************************************
2883 * fill a notify_info_data with the separator file name
2884 ********************************************************************/
2886 void spoolss_notify_sepfile(int snum,
2887 SPOOL_NOTIFY_INFO_DATA *data,
2888 print_queue_struct *queue,
2889 NT_PRINTER_INFO_LEVEL *printer,
2890 TALLOC_CTX *mem_ctx)
2895 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2897 data->notify_data.data.length = len;
2898 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2900 if (!data->notify_data.data.string) {
2901 data->notify_data.data.length = 0;
2905 memcpy(data->notify_data.data.string, temp, len);
2908 /*******************************************************************
2909 * fill a notify_info_data with the print processor
2910 * jfm:xxxx return always winprint to indicate we don't do anything to it
2911 ********************************************************************/
2913 void spoolss_notify_print_processor(int snum,
2914 SPOOL_NOTIFY_INFO_DATA *data,
2915 print_queue_struct *queue,
2916 NT_PRINTER_INFO_LEVEL *printer,
2917 TALLOC_CTX *mem_ctx)
2922 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2924 data->notify_data.data.length = len;
2925 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2927 if (!data->notify_data.data.string) {
2928 data->notify_data.data.length = 0;
2932 memcpy(data->notify_data.data.string, temp, len);
2935 /*******************************************************************
2936 * fill a notify_info_data with the print processor options
2937 * jfm:xxxx send an empty string
2938 ********************************************************************/
2940 void spoolss_notify_parameters(int snum,
2941 SPOOL_NOTIFY_INFO_DATA *data,
2942 print_queue_struct *queue,
2943 NT_PRINTER_INFO_LEVEL *printer,
2944 TALLOC_CTX *mem_ctx)
2949 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2951 data->notify_data.data.length = len;
2952 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2954 if (!data->notify_data.data.string) {
2955 data->notify_data.data.length = 0;
2959 memcpy(data->notify_data.data.string, temp, len);
2962 /*******************************************************************
2963 * fill a notify_info_data with the data type
2964 * jfm:xxxx always send RAW as data type
2965 ********************************************************************/
2967 void spoolss_notify_datatype(int snum,
2968 SPOOL_NOTIFY_INFO_DATA *data,
2969 print_queue_struct *queue,
2970 NT_PRINTER_INFO_LEVEL *printer,
2971 TALLOC_CTX *mem_ctx)
2976 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2978 data->notify_data.data.length = len;
2979 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2981 if (!data->notify_data.data.string) {
2982 data->notify_data.data.length = 0;
2986 memcpy(data->notify_data.data.string, temp, len);
2989 /*******************************************************************
2990 * fill a notify_info_data with the security descriptor
2991 * jfm:xxxx send an null pointer to say no security desc
2992 * have to implement security before !
2993 ********************************************************************/
2995 static void spoolss_notify_security_desc(int snum,
2996 SPOOL_NOTIFY_INFO_DATA *data,
2997 print_queue_struct *queue,
2998 NT_PRINTER_INFO_LEVEL *printer,
2999 TALLOC_CTX *mem_ctx)
3001 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3002 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3005 /*******************************************************************
3006 * fill a notify_info_data with the attributes
3007 * jfm:xxxx a samba printer is always shared
3008 ********************************************************************/
3010 void spoolss_notify_attributes(int snum,
3011 SPOOL_NOTIFY_INFO_DATA *data,
3012 print_queue_struct *queue,
3013 NT_PRINTER_INFO_LEVEL *printer,
3014 TALLOC_CTX *mem_ctx)
3016 data->notify_data.value[0] = printer->info_2->attributes;
3017 data->notify_data.value[1] = 0;
3020 /*******************************************************************
3021 * fill a notify_info_data with the priority
3022 ********************************************************************/
3024 static void spoolss_notify_priority(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->priority;
3031 data->notify_data.value[1] = 0;
3034 /*******************************************************************
3035 * fill a notify_info_data with the default priority
3036 ********************************************************************/
3038 static void spoolss_notify_default_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->default_priority;
3045 data->notify_data.value[1] = 0;
3048 /*******************************************************************
3049 * fill a notify_info_data with the start time
3050 ********************************************************************/
3052 static void spoolss_notify_start_time(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->starttime;
3059 data->notify_data.value[1] = 0;
3062 /*******************************************************************
3063 * fill a notify_info_data with the until time
3064 ********************************************************************/
3066 static void spoolss_notify_until_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->untiltime;
3073 data->notify_data.value[1] = 0;
3076 /*******************************************************************
3077 * fill a notify_info_data with the status
3078 ********************************************************************/
3080 static void spoolss_notify_status(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 print_status_struct status;
3088 print_queue_length(snum, &status);
3089 data->notify_data.value[0]=(uint32) status.status;
3090 data->notify_data.value[1] = 0;
3093 /*******************************************************************
3094 * fill a notify_info_data with the number of jobs queued
3095 ********************************************************************/
3097 void spoolss_notify_cjobs(int snum,
3098 SPOOL_NOTIFY_INFO_DATA *data,
3099 print_queue_struct *queue,
3100 NT_PRINTER_INFO_LEVEL *printer,
3101 TALLOC_CTX *mem_ctx)
3103 data->notify_data.value[0] = print_queue_length(snum, NULL);
3104 data->notify_data.value[1] = 0;
3107 /*******************************************************************
3108 * fill a notify_info_data with the average ppm
3109 ********************************************************************/
3111 static void spoolss_notify_average_ppm(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 /* always respond 8 pages per minutes */
3118 /* a little hard ! */
3119 data->notify_data.value[0] = printer->info_2->averageppm;
3120 data->notify_data.value[1] = 0;
3123 /*******************************************************************
3124 * fill a notify_info_data with username
3125 ********************************************************************/
3127 static void spoolss_notify_username(int snum,
3128 SPOOL_NOTIFY_INFO_DATA *data,
3129 print_queue_struct *queue,
3130 NT_PRINTER_INFO_LEVEL *printer,
3131 TALLOC_CTX *mem_ctx)
3136 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3138 data->notify_data.data.length = len;
3139 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3141 if (!data->notify_data.data.string) {
3142 data->notify_data.data.length = 0;
3146 memcpy(data->notify_data.data.string, temp, len);
3149 /*******************************************************************
3150 * fill a notify_info_data with job status
3151 ********************************************************************/
3153 static void spoolss_notify_job_status(int snum,
3154 SPOOL_NOTIFY_INFO_DATA *data,
3155 print_queue_struct *queue,
3156 NT_PRINTER_INFO_LEVEL *printer,
3157 TALLOC_CTX *mem_ctx)
3159 data->notify_data.value[0]=nt_printj_status(queue->status);
3160 data->notify_data.value[1] = 0;
3163 /*******************************************************************
3164 * fill a notify_info_data with job name
3165 ********************************************************************/
3167 static void spoolss_notify_job_name(int snum,
3168 SPOOL_NOTIFY_INFO_DATA *data,
3169 print_queue_struct *queue,
3170 NT_PRINTER_INFO_LEVEL *printer,
3171 TALLOC_CTX *mem_ctx)
3176 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3178 data->notify_data.data.length = len;
3179 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3181 if (!data->notify_data.data.string) {
3182 data->notify_data.data.length = 0;
3186 memcpy(data->notify_data.data.string, temp, len);
3189 /*******************************************************************
3190 * fill a notify_info_data with job status
3191 ********************************************************************/
3193 static void spoolss_notify_job_status_string(int snum,
3194 SPOOL_NOTIFY_INFO_DATA *data,
3195 print_queue_struct *queue,
3196 NT_PRINTER_INFO_LEVEL *printer,
3197 TALLOC_CTX *mem_ctx)
3200 * Now we're returning job status codes we just return a "" here. JRA.
3207 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3210 switch (queue->status) {
3215 p = ""; /* NT provides the paused string */
3224 #endif /* NO LONGER NEEDED. */
3226 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3228 data->notify_data.data.length = len;
3229 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3231 if (!data->notify_data.data.string) {
3232 data->notify_data.data.length = 0;
3236 memcpy(data->notify_data.data.string, temp, len);
3239 /*******************************************************************
3240 * fill a notify_info_data with job time
3241 ********************************************************************/
3243 static void spoolss_notify_job_time(int snum,
3244 SPOOL_NOTIFY_INFO_DATA *data,
3245 print_queue_struct *queue,
3246 NT_PRINTER_INFO_LEVEL *printer,
3247 TALLOC_CTX *mem_ctx)
3249 data->notify_data.value[0]=0x0;
3250 data->notify_data.value[1]=0;
3253 /*******************************************************************
3254 * fill a notify_info_data with job size
3255 ********************************************************************/
3257 static void spoolss_notify_job_size(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]=queue->size;
3264 data->notify_data.value[1]=0;
3267 /*******************************************************************
3268 * fill a notify_info_data with page info
3269 ********************************************************************/
3270 static void spoolss_notify_total_pages(int snum,
3271 SPOOL_NOTIFY_INFO_DATA *data,
3272 print_queue_struct *queue,
3273 NT_PRINTER_INFO_LEVEL *printer,
3274 TALLOC_CTX *mem_ctx)
3276 data->notify_data.value[0]=queue->page_count;
3277 data->notify_data.value[1]=0;
3280 /*******************************************************************
3281 * fill a notify_info_data with pages printed info.
3282 ********************************************************************/
3283 static void spoolss_notify_pages_printed(int snum,
3284 SPOOL_NOTIFY_INFO_DATA *data,
3285 print_queue_struct *queue,
3286 NT_PRINTER_INFO_LEVEL *printer,
3287 TALLOC_CTX *mem_ctx)
3289 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3290 data->notify_data.value[1]=0;
3293 /*******************************************************************
3294 Fill a notify_info_data with job position.
3295 ********************************************************************/
3297 static void spoolss_notify_job_position(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]=queue->job;
3304 data->notify_data.value[1]=0;
3307 /*******************************************************************
3308 Fill a notify_info_data with submitted time.
3309 ********************************************************************/
3311 static void spoolss_notify_submitted_time(int snum,
3312 SPOOL_NOTIFY_INFO_DATA *data,
3313 print_queue_struct *queue,
3314 NT_PRINTER_INFO_LEVEL *printer,
3315 TALLOC_CTX *mem_ctx)
3322 t=gmtime(&queue->time);
3324 len = sizeof(SYSTEMTIME);
3326 data->notify_data.data.length = len;
3327 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3329 if (!data->notify_data.data.string) {
3330 data->notify_data.data.length = 0;
3334 make_systemtime(&st, t);
3337 * Systemtime must be linearized as a set of UINT16's.
3338 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3341 p = (char *)data->notify_data.data.string;
3342 SSVAL(p, 0, st.year);
3343 SSVAL(p, 2, st.month);
3344 SSVAL(p, 4, st.dayofweek);
3345 SSVAL(p, 6, st.day);
3346 SSVAL(p, 8, st.hour);
3347 SSVAL(p, 10, st.minute);
3348 SSVAL(p, 12, st.second);
3349 SSVAL(p, 14, st.milliseconds);
3352 struct s_notify_info_data_table
3358 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3359 print_queue_struct *queue,
3360 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3363 /* A table describing the various print notification constants and
3364 whether the notification data is a pointer to a variable sized
3365 buffer, a one value uint32 or a two value uint32. */
3367 static const struct s_notify_info_data_table notify_info_data_table[] =
3369 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3370 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3371 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3372 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3373 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3374 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3375 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3376 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3377 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3378 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3379 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3380 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3381 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3382 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3383 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3395 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3396 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3397 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3398 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3399 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3400 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3401 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3402 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3403 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3404 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3405 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3406 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3407 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3408 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3409 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3410 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3411 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3418 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3421 /*******************************************************************
3422 Return the size of info_data structure.
3423 ********************************************************************/
3425 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3429 for (i = 0; i < sizeof(notify_info_data_table); i++)
3431 if ( (notify_info_data_table[i].type == type)
3432 && (notify_info_data_table[i].field == field) )
3434 switch(notify_info_data_table[i].size)
3436 case NOTIFY_ONE_VALUE:
3437 case NOTIFY_TWO_VALUE:
3442 /* The only pointer notify data I have seen on
3443 the wire is the submitted time and this has
3444 the notify size set to 4. -tpot */
3446 case NOTIFY_POINTER:
3449 case NOTIFY_SECDESC:
3455 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3460 /*******************************************************************
3461 Return the type of notify_info_data.
3462 ********************************************************************/
3464 static int type_of_notify_info_data(uint16 type, uint16 field)
3468 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3469 if (notify_info_data_table[i].type == type &&
3470 notify_info_data_table[i].field == field)
3471 return notify_info_data_table[i].size;
3477 /****************************************************************************
3478 ****************************************************************************/
3480 static int search_notify(uint16 type, uint16 field, int *value)
3484 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3485 if (notify_info_data_table[i].type == type &&
3486 notify_info_data_table[i].field == field &&
3487 notify_info_data_table[i].fn != NULL) {
3496 /****************************************************************************
3497 ****************************************************************************/
3499 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3501 info_data->type = type;
3502 info_data->field = field;
3503 info_data->reserved = 0;
3505 info_data->size = size_of_notify_info_data(type, field);
3506 info_data->enc_type = type_of_notify_info_data(type, field);
3513 /*******************************************************************
3515 * fill a notify_info struct with info asked
3517 ********************************************************************/
3519 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3520 snum, SPOOL_NOTIFY_OPTION_TYPE
3521 *option_type, uint32 id,
3522 TALLOC_CTX *mem_ctx)
3528 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3529 NT_PRINTER_INFO_LEVEL *printer = NULL;
3530 print_queue_struct *queue=NULL;
3532 type=option_type->type;
3534 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3535 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3536 option_type->count, lp_servicename(snum)));
3538 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3541 for(field_num=0; field_num<option_type->count; field_num++) {
3542 field = option_type->fields[field_num];
3544 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3546 if (!search_notify(type, field, &j) )
3549 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3550 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3555 current_data = &info->data[info->count];
3557 construct_info_data(current_data, type, field, id);
3559 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3560 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3562 notify_info_data_table[j].fn(snum, current_data, queue,
3568 free_a_printer(&printer, 2);
3572 /*******************************************************************
3574 * fill a notify_info struct with info asked
3576 ********************************************************************/
3578 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3579 SPOOL_NOTIFY_INFO *info,
3580 NT_PRINTER_INFO_LEVEL *printer,
3581 int snum, SPOOL_NOTIFY_OPTION_TYPE
3582 *option_type, uint32 id,
3583 TALLOC_CTX *mem_ctx)
3589 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3591 DEBUG(4,("construct_notify_jobs_info\n"));
3593 type = option_type->type;
3595 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3596 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3597 option_type->count));
3599 for(field_num=0; field_num<option_type->count; field_num++) {
3600 field = option_type->fields[field_num];
3602 if (!search_notify(type, field, &j) )
3605 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3606 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3609 else info->data = tid;
3611 current_data=&(info->data[info->count]);
3613 construct_info_data(current_data, type, field, id);
3614 notify_info_data_table[j].fn(snum, current_data, queue,
3623 * JFM: The enumeration is not that simple, it's even non obvious.
3625 * let's take an example: I want to monitor the PRINTER SERVER for
3626 * the printer's name and the number of jobs currently queued.
3627 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3628 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3630 * I have 3 printers on the back of my server.
3632 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3635 * 1 printer 1 name 1
3636 * 2 printer 1 cjob 1
3637 * 3 printer 2 name 2
3638 * 4 printer 2 cjob 2
3639 * 5 printer 3 name 3
3640 * 6 printer 3 name 3
3642 * that's the print server case, the printer case is even worse.
3645 /*******************************************************************
3647 * enumerate all printers on the printserver
3648 * fill a notify_info struct with info asked
3650 ********************************************************************/
3652 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3653 SPOOL_NOTIFY_INFO *info,
3654 TALLOC_CTX *mem_ctx)
3657 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3658 int n_services=lp_numservices();
3660 SPOOL_NOTIFY_OPTION *option;
3661 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3663 DEBUG(4,("printserver_notify_info\n"));
3668 option=Printer->notify.option;
3673 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3674 sending a ffpcn() request first */
3679 for (i=0; i<option->count; i++) {
3680 option_type=&(option->ctr.type[i]);
3682 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3685 for (snum=0; snum<n_services; snum++)
3687 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3688 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3694 * Debugging information, don't delete.
3697 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3698 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3699 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3701 for (i=0; i<info->count; i++) {
3702 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3703 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3704 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3711 /*******************************************************************
3713 * fill a notify_info struct with info asked
3715 ********************************************************************/
3717 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3718 TALLOC_CTX *mem_ctx)
3721 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3724 SPOOL_NOTIFY_OPTION *option;
3725 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3727 print_queue_struct *queue=NULL;
3728 print_status_struct status;
3730 DEBUG(4,("printer_notify_info\n"));
3735 option=Printer->notify.option;
3741 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3742 sending a ffpcn() request first */
3747 get_printer_snum(p, hnd, &snum);
3749 for (i=0; i<option->count; i++) {
3750 option_type=&option->ctr.type[i];
3752 switch ( option_type->type ) {
3753 case PRINTER_NOTIFY_TYPE:
3754 if(construct_notify_printer_info(Printer, info, snum,
3760 case JOB_NOTIFY_TYPE: {
3761 NT_PRINTER_INFO_LEVEL *printer = NULL;
3763 count = print_queue_status(snum, &queue, &status);
3765 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3768 for (j=0; j<count; j++) {
3769 construct_notify_jobs_info(&queue[j], info,
3776 free_a_printer(&printer, 2);
3786 * Debugging information, don't delete.
3789 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3790 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3791 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3793 for (i=0; i<info->count; i++) {
3794 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3795 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3796 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3802 /********************************************************************
3804 ********************************************************************/
3806 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3808 POLICY_HND *handle = &q_u->handle;
3809 SPOOL_NOTIFY_INFO *info = &r_u->info;
3811 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3812 WERROR result = WERR_BADFID;
3814 /* we always have a NOTIFY_INFO struct */
3818 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3819 OUR_HANDLE(handle)));
3823 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3826 * We are now using the change value, and
3827 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3828 * I don't have a global notification system, I'm sending back all the
3829 * informations even when _NOTHING_ has changed.
3832 /* We need to keep track of the change value to send back in
3833 RRPCN replies otherwise our updates are ignored. */
3835 Printer->notify.fnpcn = True;
3837 if (Printer->notify.client_connected) {
3838 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3839 Printer->notify.change = q_u->change;
3842 /* just ignore the SPOOL_NOTIFY_OPTION */
3844 switch (Printer->printer_type) {
3845 case PRINTER_HANDLE_IS_PRINTSERVER:
3846 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3849 case PRINTER_HANDLE_IS_PRINTER:
3850 result = printer_notify_info(p, handle, info, p->mem_ctx);
3854 Printer->notify.fnpcn = False;
3860 /********************************************************************
3861 * construct_printer_info_0
3862 * fill a printer_info_0 struct
3863 ********************************************************************/
3865 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3869 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3870 counter_printer_0 *session_counter;
3871 uint32 global_counter;
3874 print_status_struct status;
3876 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3879 count = print_queue_length(snum, &status);
3881 /* check if we already have a counter for this printer */
3882 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3883 if (session_counter->snum == snum)
3887 /* it's the first time, add it to the list */
3888 if (session_counter==NULL) {
3889 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3890 free_a_printer(&ntprinter, 2);
3893 ZERO_STRUCTP(session_counter);
3894 session_counter->snum=snum;
3895 session_counter->counter=0;
3896 DLIST_ADD(counter_list, session_counter);
3900 session_counter->counter++;
3903 * the global_counter should be stored in a TDB as it's common to all the clients
3904 * and should be zeroed on samba startup
3906 global_counter=session_counter->counter;
3908 pstrcpy(chaine,ntprinter->info_2->printername);
3910 init_unistr(&printer->printername, chaine);
3912 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3913 init_unistr(&printer->servername, chaine);
3915 printer->cjobs = count;
3916 printer->total_jobs = 0;
3917 printer->total_bytes = 0;
3919 setuptime = (time_t)ntprinter->info_2->setuptime;
3920 t=gmtime(&setuptime);
3922 printer->year = t->tm_year+1900;
3923 printer->month = t->tm_mon+1;
3924 printer->dayofweek = t->tm_wday;
3925 printer->day = t->tm_mday;
3926 printer->hour = t->tm_hour;
3927 printer->minute = t->tm_min;
3928 printer->second = t->tm_sec;
3929 printer->milliseconds = 0;
3931 printer->global_counter = global_counter;
3932 printer->total_pages = 0;
3934 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3935 printer->major_version = 0x0005; /* NT 5 */
3936 printer->build_version = 0x0893; /* build 2195 */
3938 printer->unknown7 = 0x1;
3939 printer->unknown8 = 0x0;
3940 printer->unknown9 = 0x0;
3941 printer->session_counter = session_counter->counter;
3942 printer->unknown11 = 0x0;
3943 printer->printer_errors = 0x0; /* number of print failure */
3944 printer->unknown13 = 0x0;
3945 printer->unknown14 = 0x1;
3946 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3947 printer->unknown16 = 0x0;
3948 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3949 printer->unknown18 = 0x0;
3950 printer->status = nt_printq_status(status.status);
3951 printer->unknown20 = 0x0;
3952 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3953 printer->unknown22 = 0x0;
3954 printer->unknown23 = 0x6; /* 6 ???*/
3955 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3956 printer->unknown25 = 0;
3957 printer->unknown26 = 0;
3958 printer->unknown27 = 0;
3959 printer->unknown28 = 0;
3960 printer->unknown29 = 0;
3962 free_a_printer(&ntprinter,2);
3966 /********************************************************************
3967 * construct_printer_info_1
3968 * fill a printer_info_1 struct
3969 ********************************************************************/
3970 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3974 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3976 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3979 printer->flags=flags;
3981 if (*ntprinter->info_2->comment == '\0') {
3982 init_unistr(&printer->comment, lp_comment(snum));
3983 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3984 ntprinter->info_2->drivername, lp_comment(snum));
3987 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3988 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3989 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3992 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3994 init_unistr(&printer->description, chaine);
3995 init_unistr(&printer->name, chaine2);
3997 free_a_printer(&ntprinter,2);
4002 /****************************************************************************
4003 Free a DEVMODE struct.
4004 ****************************************************************************/
4006 static void free_dev_mode(DEVICEMODE *dev)
4011 SAFE_FREE(dev->dev_private);
4016 /****************************************************************************
4017 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4018 should be valid upon entry
4019 ****************************************************************************/
4021 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4023 if ( !devmode || !ntdevmode )
4026 init_unistr(&devmode->devicename, ntdevmode->devicename);
4028 init_unistr(&devmode->formname, ntdevmode->formname);
4030 devmode->specversion = ntdevmode->specversion;
4031 devmode->driverversion = ntdevmode->driverversion;
4032 devmode->size = ntdevmode->size;
4033 devmode->driverextra = ntdevmode->driverextra;
4034 devmode->fields = ntdevmode->fields;
4036 devmode->orientation = ntdevmode->orientation;
4037 devmode->papersize = ntdevmode->papersize;
4038 devmode->paperlength = ntdevmode->paperlength;
4039 devmode->paperwidth = ntdevmode->paperwidth;
4040 devmode->scale = ntdevmode->scale;
4041 devmode->copies = ntdevmode->copies;
4042 devmode->defaultsource = ntdevmode->defaultsource;
4043 devmode->printquality = ntdevmode->printquality;
4044 devmode->color = ntdevmode->color;
4045 devmode->duplex = ntdevmode->duplex;
4046 devmode->yresolution = ntdevmode->yresolution;
4047 devmode->ttoption = ntdevmode->ttoption;
4048 devmode->collate = ntdevmode->collate;
4049 devmode->icmmethod = ntdevmode->icmmethod;
4050 devmode->icmintent = ntdevmode->icmintent;
4051 devmode->mediatype = ntdevmode->mediatype;
4052 devmode->dithertype = ntdevmode->dithertype;
4054 if (ntdevmode->nt_dev_private != NULL) {
4055 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4062 /****************************************************************************
4063 Create a DEVMODE struct. Returns malloced memory.
4064 ****************************************************************************/
4066 DEVICEMODE *construct_dev_mode(int snum)
4068 NT_PRINTER_INFO_LEVEL *printer = NULL;
4069 DEVICEMODE *devmode = NULL;
4071 DEBUG(7,("construct_dev_mode\n"));
4073 DEBUGADD(8,("getting printer characteristics\n"));
4075 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4078 if ( !printer->info_2->devmode ) {
4079 DEBUG(5, ("BONG! There was no device mode!\n"));
4083 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4084 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4088 ZERO_STRUCTP(devmode);
4090 DEBUGADD(8,("loading DEVICEMODE\n"));
4092 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4093 free_dev_mode( devmode );
4098 free_a_printer(&printer,2);
4103 /********************************************************************
4104 * construct_printer_info_2
4105 * fill a printer_info_2 struct
4106 ********************************************************************/
4108 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4111 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4113 print_status_struct status;
4115 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4118 count = print_queue_length(snum, &status);
4120 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4121 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4122 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4123 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4124 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4126 if (*ntprinter->info_2->comment == '\0')
4127 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4129 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4131 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4132 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4133 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4134 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4135 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4137 printer->attributes = ntprinter->info_2->attributes;
4139 printer->priority = ntprinter->info_2->priority; /* priority */
4140 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4141 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4142 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4143 printer->status = nt_printq_status(status.status); /* status */
4144 printer->cjobs = count; /* jobs */
4145 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4147 if ( !(printer->devmode = construct_dev_mode(snum)) )
4148 DEBUG(8, ("Returning NULL Devicemode!\n"));
4150 printer->secdesc = NULL;
4152 if ( ntprinter->info_2->secdesc_buf
4153 && ntprinter->info_2->secdesc_buf->len != 0 )
4155 /* don't use talloc_steal() here unless you do a deep steal of all
4156 the SEC_DESC members */
4158 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4159 ntprinter->info_2->secdesc_buf->sec );
4162 free_a_printer(&ntprinter, 2);
4167 /********************************************************************
4168 * construct_printer_info_3
4169 * fill a printer_info_3 struct
4170 ********************************************************************/
4172 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4174 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4175 PRINTER_INFO_3 *printer = NULL;
4177 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4181 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4182 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4186 ZERO_STRUCTP(printer);
4188 /* These are the components of the SD we are returning. */
4190 printer->flags = 0x4;
4192 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4193 /* don't use talloc_steal() here unless you do a deep steal of all
4194 the SEC_DESC members */
4196 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4197 ntprinter->info_2->secdesc_buf->sec );
4200 free_a_printer(&ntprinter, 2);
4202 *pp_printer = printer;
4206 /********************************************************************
4207 * construct_printer_info_4
4208 * fill a printer_info_4 struct
4209 ********************************************************************/
4211 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4213 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4215 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4218 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4219 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4220 printer->attributes = ntprinter->info_2->attributes;
4222 free_a_printer(&ntprinter, 2);
4226 /********************************************************************
4227 * construct_printer_info_5
4228 * fill a printer_info_5 struct
4229 ********************************************************************/
4231 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4233 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4235 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4238 init_unistr(&printer->printername, ntprinter->info_2->printername);
4239 init_unistr(&printer->portname, ntprinter->info_2->portname);
4240 printer->attributes = ntprinter->info_2->attributes;
4242 /* these two are not used by NT+ according to MSDN */
4244 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4245 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4247 free_a_printer(&ntprinter, 2);
4252 /********************************************************************
4253 * construct_printer_info_7
4254 * fill a printer_info_7 struct
4255 ********************************************************************/
4257 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4259 char *guid_str = NULL;
4262 if (is_printer_published(print_hnd, snum, &guid)) {
4263 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4264 strupper_m(guid_str);
4265 init_unistr(&printer->guid, guid_str);
4266 printer->action = SPOOL_DS_PUBLISH;
4268 init_unistr(&printer->guid, "");
4269 printer->action = SPOOL_DS_UNPUBLISH;
4275 /********************************************************************
4276 Spoolss_enumprinters.
4277 ********************************************************************/
4279 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4283 int n_services=lp_numservices();
4284 PRINTER_INFO_1 *tp, *printers=NULL;
4285 PRINTER_INFO_1 current_prt;
4286 WERROR result = WERR_OK;
4288 DEBUG(4,("enum_all_printers_info_1\n"));
4290 for (snum=0; snum<n_services; snum++) {
4291 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4292 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4294 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4295 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4296 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4297 SAFE_FREE(printers);
4302 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4304 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4310 /* check the required size. */
4311 for (i=0; i<*returned; i++)
4312 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4314 if (*needed > offered) {
4315 result = WERR_INSUFFICIENT_BUFFER;
4319 if (!rpcbuf_alloc_size(buffer, *needed)) {
4320 result = WERR_NOMEM;
4324 /* fill the buffer with the structures */
4325 for (i=0; i<*returned; i++)
4326 smb_io_printer_info_1("", buffer, &printers[i], 0);
4331 SAFE_FREE(printers);
4333 if ( !W_ERROR_IS_OK(result) )
4339 /********************************************************************
4340 enum_all_printers_info_1_local.
4341 *********************************************************************/
4343 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4345 DEBUG(4,("enum_all_printers_info_1_local\n"));
4347 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4350 /********************************************************************
4351 enum_all_printers_info_1_name.
4352 *********************************************************************/
4354 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4358 DEBUG(4,("enum_all_printers_info_1_name\n"));
4360 if ((name[0] == '\\') && (name[1] == '\\'))
4363 if (is_myname_or_ipaddr(s)) {
4364 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4367 return WERR_INVALID_NAME;
4370 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4371 /********************************************************************
4372 enum_all_printers_info_1_remote.
4373 *********************************************************************/
4375 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4377 PRINTER_INFO_1 *printer;
4378 fstring printername;
4381 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4382 WERROR result = WERR_OK;
4384 /* JFM: currently it's more a place holder than anything else.
4385 * In the spooler world there is a notion of server registration.
4386 * the print servers are registered on the PDC (in the same domain)
4388 * We should have a TDB here. The registration is done thru an
4389 * undocumented RPC call.
4392 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4397 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4398 slprintf(desc, sizeof(desc)-1,"%s", name);
4399 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4401 init_unistr(&printer->description, desc);
4402 init_unistr(&printer->name, printername);
4403 init_unistr(&printer->comment, comment);
4404 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4406 /* check the required size. */
4407 *needed += spoolss_size_printer_info_1(printer);
4409 if (*needed > offered) {
4410 result = WERR_INSUFFICIENT_BUFFER;
4414 if (!rpcbuf_alloc_size(buffer, *needed)) {
4415 result = WERR_NOMEM;
4419 /* fill the buffer with the structures */
4420 smb_io_printer_info_1("", buffer, printer, 0);
4426 if ( !W_ERROR_IS_OK(result) )
4434 /********************************************************************
4435 enum_all_printers_info_1_network.
4436 *********************************************************************/
4438 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4442 DEBUG(4,("enum_all_printers_info_1_network\n"));
4444 /* If we respond to a enum_printers level 1 on our name with flags
4445 set to PRINTER_ENUM_REMOTE with a list of printers then these
4446 printers incorrectly appear in the APW browse list.
4447 Specifically the printers for the server appear at the workgroup
4448 level where all the other servers in the domain are
4449 listed. Windows responds to this call with a
4450 WERR_CAN_NOT_COMPLETE so we should do the same. */
4452 if (name[0] == '\\' && name[1] == '\\')
4455 if (is_myname_or_ipaddr(s))
4456 return WERR_CAN_NOT_COMPLETE;
4458 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4461 /********************************************************************
4462 * api_spoolss_enumprinters
4464 * called from api_spoolss_enumprinters (see this to understand)
4465 ********************************************************************/
4467 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4471 int n_services=lp_numservices();
4472 PRINTER_INFO_2 *tp, *printers=NULL;
4473 PRINTER_INFO_2 current_prt;
4474 WERROR result = WERR_OK;
4476 for (snum=0; snum<n_services; snum++) {
4477 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4478 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4480 if (construct_printer_info_2(NULL, ¤t_prt, snum))
4482 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4483 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4484 SAFE_FREE(printers);
4489 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4492 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4499 /* check the required size. */
4500 for (i=0; i<*returned; i++)
4501 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4503 if (*needed > offered) {
4504 result = WERR_INSUFFICIENT_BUFFER;
4508 if (!rpcbuf_alloc_size(buffer, *needed)) {
4509 result = WERR_NOMEM;
4513 /* fill the buffer with the structures */
4514 for (i=0; i<*returned; i++)
4515 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4520 for (i=0; i<*returned; i++)
4521 free_devmode(printers[i].devmode);
4523 SAFE_FREE(printers);
4525 if ( !W_ERROR_IS_OK(result) )
4531 /********************************************************************
4532 * handle enumeration of printers at level 1
4533 ********************************************************************/
4535 static WERROR enumprinters_level1( uint32 flags, fstring name,
4536 RPC_BUFFER *buffer, uint32 offered,
4537 uint32 *needed, uint32 *returned)
4539 /* Not all the flags are equals */
4541 if (flags & PRINTER_ENUM_LOCAL)
4542 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4544 if (flags & PRINTER_ENUM_NAME)
4545 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4547 #if 0 /* JERRY - disabled for now */
4548 if (flags & PRINTER_ENUM_REMOTE)
4549 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4552 if (flags & PRINTER_ENUM_NETWORK)
4553 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4555 return WERR_OK; /* NT4sp5 does that */
4558 /********************************************************************
4559 * handle enumeration of printers at level 2
4560 ********************************************************************/
4562 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4563 RPC_BUFFER *buffer, uint32 offered,
4564 uint32 *needed, uint32 *returned)
4566 char *s = servername;
4568 if (flags & PRINTER_ENUM_LOCAL) {
4569 return enum_all_printers_info_2(buffer, offered, needed, returned);
4572 if (flags & PRINTER_ENUM_NAME) {
4573 if ((servername[0] == '\\') && (servername[1] == '\\'))
4575 if (is_myname_or_ipaddr(s))
4576 return enum_all_printers_info_2(buffer, offered, needed, returned);
4578 return WERR_INVALID_NAME;
4581 if (flags & PRINTER_ENUM_REMOTE)
4582 return WERR_UNKNOWN_LEVEL;
4587 /********************************************************************
4588 * handle enumeration of printers at level 5
4589 ********************************************************************/
4591 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4592 RPC_BUFFER *buffer, uint32 offered,
4593 uint32 *needed, uint32 *returned)
4595 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4599 /********************************************************************
4600 * api_spoolss_enumprinters
4602 * called from api_spoolss_enumprinters (see this to understand)
4603 ********************************************************************/
4605 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4607 uint32 flags = q_u->flags;
4608 UNISTR2 *servername = &q_u->servername;
4609 uint32 level = q_u->level;
4610 RPC_BUFFER *buffer = NULL;
4611 uint32 offered = q_u->offered;
4612 uint32 *needed = &r_u->needed;
4613 uint32 *returned = &r_u->returned;
4617 /* that's an [in out] buffer */
4619 if ( q_u->buffer ) {
4620 rpcbuf_move(q_u->buffer, &r_u->buffer);
4621 buffer = r_u->buffer;
4624 DEBUG(4,("_spoolss_enumprinters\n"));
4631 * flags==PRINTER_ENUM_NAME
4632 * if name=="" then enumerates all printers
4633 * if name!="" then enumerate the printer
4634 * flags==PRINTER_ENUM_REMOTE
4635 * name is NULL, enumerate printers
4636 * Level 2: name!="" enumerates printers, name can't be NULL
4637 * Level 3: doesn't exist
4638 * Level 4: does a local registry lookup
4639 * Level 5: same as Level 2
4642 unistr2_to_ascii(name, servername, sizeof(name)-1);
4647 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4649 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4651 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4656 return WERR_UNKNOWN_LEVEL;
4659 /****************************************************************************
4660 ****************************************************************************/
4662 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4664 PRINTER_INFO_0 *printer=NULL;
4665 WERROR result = WERR_OK;
4667 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4670 construct_printer_info_0(print_hnd, printer, snum);
4672 /* check the required size. */
4673 *needed += spoolss_size_printer_info_0(printer);
4675 if (*needed > offered) {
4676 result = WERR_INSUFFICIENT_BUFFER;
4680 if (!rpcbuf_alloc_size(buffer, *needed)) {
4681 result = WERR_NOMEM;
4685 /* fill the buffer with the structures */
4686 smb_io_printer_info_0("", buffer, printer, 0);
4696 /****************************************************************************
4697 ****************************************************************************/
4699 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4701 PRINTER_INFO_1 *printer=NULL;
4702 WERROR result = WERR_OK;
4704 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4707 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4709 /* check the required size. */
4710 *needed += spoolss_size_printer_info_1(printer);
4712 if (*needed > offered) {
4713 result = WERR_INSUFFICIENT_BUFFER;
4717 if (!rpcbuf_alloc_size(buffer, *needed)) {
4718 result = WERR_NOMEM;
4722 /* fill the buffer with the structures */
4723 smb_io_printer_info_1("", buffer, printer, 0);
4732 /****************************************************************************
4733 ****************************************************************************/
4735 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4737 PRINTER_INFO_2 *printer=NULL;
4738 WERROR result = WERR_OK;
4740 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4743 construct_printer_info_2(print_hnd, printer, snum);
4745 /* check the required size. */
4746 *needed += spoolss_size_printer_info_2(printer);
4748 if (*needed > offered) {
4749 result = WERR_INSUFFICIENT_BUFFER;
4753 if (!rpcbuf_alloc_size(buffer, *needed)) {
4754 result = WERR_NOMEM;
4758 /* fill the buffer with the structures */
4759 if (!smb_io_printer_info_2("", buffer, printer, 0))
4760 result = WERR_NOMEM;
4764 free_printer_info_2(printer);
4769 /****************************************************************************
4770 ****************************************************************************/
4772 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4774 PRINTER_INFO_3 *printer=NULL;
4775 WERROR result = WERR_OK;
4777 if (!construct_printer_info_3(print_hnd, &printer, snum))
4780 /* check the required size. */
4781 *needed += spoolss_size_printer_info_3(printer);
4783 if (*needed > offered) {
4784 result = WERR_INSUFFICIENT_BUFFER;
4788 if (!rpcbuf_alloc_size(buffer, *needed)) {
4789 result = WERR_NOMEM;
4793 /* fill the buffer with the structures */
4794 smb_io_printer_info_3("", buffer, printer, 0);
4798 free_printer_info_3(printer);
4803 /****************************************************************************
4804 ****************************************************************************/
4806 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4808 PRINTER_INFO_4 *printer=NULL;
4809 WERROR result = WERR_OK;
4811 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4814 if (!construct_printer_info_4(print_hnd, printer, snum))
4817 /* check the required size. */
4818 *needed += spoolss_size_printer_info_4(printer);
4820 if (*needed > offered) {
4821 result = WERR_INSUFFICIENT_BUFFER;
4825 if (!rpcbuf_alloc_size(buffer, *needed)) {
4826 result = WERR_NOMEM;
4830 /* fill the buffer with the structures */
4831 smb_io_printer_info_4("", buffer, printer, 0);
4835 free_printer_info_4(printer);
4840 /****************************************************************************
4841 ****************************************************************************/
4843 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4845 PRINTER_INFO_5 *printer=NULL;
4846 WERROR result = WERR_OK;
4848 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4851 if (!construct_printer_info_5(print_hnd, printer, snum))
4854 /* check the required size. */
4855 *needed += spoolss_size_printer_info_5(printer);
4857 if (*needed > offered) {
4858 result = WERR_INSUFFICIENT_BUFFER;
4862 if (!rpcbuf_alloc_size(buffer, *needed)) {
4863 result = WERR_NOMEM;
4867 /* fill the buffer with the structures */
4868 smb_io_printer_info_5("", buffer, printer, 0);
4872 free_printer_info_5(printer);
4877 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4879 PRINTER_INFO_7 *printer=NULL;
4880 WERROR result = WERR_OK;
4882 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4885 if (!construct_printer_info_7(print_hnd, printer, snum))
4888 /* check the required size. */
4889 *needed += spoolss_size_printer_info_7(printer);
4891 if (*needed > offered) {
4892 result = WERR_INSUFFICIENT_BUFFER;
4896 if (!rpcbuf_alloc_size(buffer, *needed)) {
4897 result = WERR_NOMEM;
4902 /* fill the buffer with the structures */
4903 smb_io_printer_info_7("", buffer, printer, 0);
4907 free_printer_info_7(printer);
4912 /****************************************************************************
4913 ****************************************************************************/
4915 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4917 POLICY_HND *handle = &q_u->handle;
4918 uint32 level = q_u->level;
4919 RPC_BUFFER *buffer = NULL;
4920 uint32 offered = q_u->offered;
4921 uint32 *needed = &r_u->needed;
4922 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4926 /* that's an [in out] buffer */
4928 if ( q_u->buffer ) {
4929 rpcbuf_move(q_u->buffer, &r_u->buffer);
4930 buffer = r_u->buffer;
4935 if (!get_printer_snum(p, handle, &snum))
4940 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4942 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4944 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4946 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4948 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4950 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4952 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4954 return WERR_UNKNOWN_LEVEL;
4957 /********************************************************************
4958 * fill a DRIVER_INFO_1 struct
4959 ********************************************************************/
4961 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4963 init_unistr( &info->name, driver.info_3->name);
4966 /********************************************************************
4967 * construct_printer_driver_info_1
4968 ********************************************************************/
4970 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4972 NT_PRINTER_INFO_LEVEL *printer = NULL;
4973 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4975 ZERO_STRUCT(driver);
4977 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4978 return WERR_INVALID_PRINTER_NAME;
4980 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4981 return WERR_UNKNOWN_PRINTER_DRIVER;
4983 fill_printer_driver_info_1(info, driver, servername, architecture);
4985 free_a_printer(&printer,2);
4990 /********************************************************************
4991 * construct_printer_driver_info_2
4992 * fill a printer_info_2 struct
4993 ********************************************************************/
4995 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4999 info->version=driver.info_3->cversion;
5001 init_unistr( &info->name, driver.info_3->name );
5002 init_unistr( &info->architecture, driver.info_3->environment );
5005 if (strlen(driver.info_3->driverpath)) {
5006 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5007 init_unistr( &info->driverpath, temp );
5009 init_unistr( &info->driverpath, "" );
5011 if (strlen(driver.info_3->datafile)) {
5012 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5013 init_unistr( &info->datafile, temp );
5015 init_unistr( &info->datafile, "" );
5017 if (strlen(driver.info_3->configfile)) {
5018 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5019 init_unistr( &info->configfile, temp );
5021 init_unistr( &info->configfile, "" );
5024 /********************************************************************
5025 * construct_printer_driver_info_2
5026 * fill a printer_info_2 struct
5027 ********************************************************************/
5029 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5031 NT_PRINTER_INFO_LEVEL *printer = NULL;
5032 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5034 ZERO_STRUCT(printer);
5035 ZERO_STRUCT(driver);
5037 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5038 return WERR_INVALID_PRINTER_NAME;
5040 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5041 return WERR_UNKNOWN_PRINTER_DRIVER;
5043 fill_printer_driver_info_2(info, driver, servername);
5045 free_a_printer(&printer,2);
5050 /********************************************************************
5051 * copy a strings array and convert to UNICODE
5053 * convert an array of ascii string to a UNICODE string
5054 ********************************************************************/
5056 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5064 DEBUG(6,("init_unistr_array\n"));
5075 v = ""; /* hack to handle null lists */
5078 /* hack to allow this to be used in places other than when generating
5079 the list of dependent files */
5082 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5086 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5088 /* add one extra unit16 for the second terminating NULL */
5090 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5091 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5099 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5104 /* special case for ""; we need to add both NULL's here */
5106 (*uni_array)[j++]=0x0000;
5107 (*uni_array)[j]=0x0000;
5110 DEBUGADD(6,("last one:done\n"));
5112 /* return size of array in uint16's */
5117 /********************************************************************
5118 * construct_printer_info_3
5119 * fill a printer_info_3 struct
5120 ********************************************************************/
5122 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5128 info->version=driver.info_3->cversion;
5130 init_unistr( &info->name, driver.info_3->name );
5131 init_unistr( &info->architecture, driver.info_3->environment );
5133 if (strlen(driver.info_3->driverpath)) {
5134 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5135 init_unistr( &info->driverpath, temp );
5137 init_unistr( &info->driverpath, "" );
5139 if (strlen(driver.info_3->datafile)) {
5140 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5141 init_unistr( &info->datafile, temp );
5143 init_unistr( &info->datafile, "" );
5145 if (strlen(driver.info_3->configfile)) {
5146 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5147 init_unistr( &info->configfile, temp );
5149 init_unistr( &info->configfile, "" );
5151 if (strlen(driver.info_3->helpfile)) {
5152 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5153 init_unistr( &info->helpfile, temp );
5155 init_unistr( &info->helpfile, "" );
5157 init_unistr( &info->monitorname, driver.info_3->monitorname );
5158 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5160 info->dependentfiles=NULL;
5161 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5164 /********************************************************************
5165 * construct_printer_info_3
5166 * fill a printer_info_3 struct
5167 ********************************************************************/
5169 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5171 NT_PRINTER_INFO_LEVEL *printer = NULL;
5172 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5174 ZERO_STRUCT(driver);
5176 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5177 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5178 if (!W_ERROR_IS_OK(status))
5179 return WERR_INVALID_PRINTER_NAME;
5181 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5182 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5187 * I put this code in during testing. Helpful when commenting out the
5188 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5189 * as win2k always queries the driver using an infor level of 6.
5190 * I've left it in (but ifdef'd out) because I'll probably
5191 * use it in experimentation again in the future. --jerry 22/01/2002
5194 if (!W_ERROR_IS_OK(status)) {
5196 * Is this a W2k client ?
5199 /* Yes - try again with a WinNT driver. */
5201 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5202 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5206 if (!W_ERROR_IS_OK(status)) {
5207 free_a_printer(&printer,2);
5208 return WERR_UNKNOWN_PRINTER_DRIVER;
5216 fill_printer_driver_info_3(info, driver, servername);
5218 free_a_printer(&printer,2);
5223 /********************************************************************
5224 * construct_printer_info_6
5225 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5226 ********************************************************************/
5228 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5234 memset(&nullstr, '\0', sizeof(fstring));
5236 info->version=driver.info_3->cversion;
5238 init_unistr( &info->name, driver.info_3->name );
5239 init_unistr( &info->architecture, driver.info_3->environment );
5241 if (strlen(driver.info_3->driverpath)) {
5242 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5243 init_unistr( &info->driverpath, temp );
5245 init_unistr( &info->driverpath, "" );
5247 if (strlen(driver.info_3->datafile)) {
5248 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5249 init_unistr( &info->datafile, temp );
5251 init_unistr( &info->datafile, "" );
5253 if (strlen(driver.info_3->configfile)) {
5254 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5255 init_unistr( &info->configfile, temp );
5257 init_unistr( &info->configfile, "" );
5259 if (strlen(driver.info_3->helpfile)) {
5260 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5261 init_unistr( &info->helpfile, temp );
5263 init_unistr( &info->helpfile, "" );
5265 init_unistr( &info->monitorname, driver.info_3->monitorname );
5266 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5268 info->dependentfiles = NULL;
5269 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5271 info->previousdrivernames=NULL;
5272 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5274 info->driver_date.low=0;
5275 info->driver_date.high=0;
5278 info->driver_version_low=0;
5279 info->driver_version_high=0;
5281 init_unistr( &info->mfgname, "");
5282 init_unistr( &info->oem_url, "");
5283 init_unistr( &info->hardware_id, "");
5284 init_unistr( &info->provider, "");
5287 /********************************************************************
5288 * construct_printer_info_6
5289 * fill a printer_info_6 struct
5290 ********************************************************************/
5292 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5293 fstring servername, fstring architecture, uint32 version)
5295 NT_PRINTER_INFO_LEVEL *printer = NULL;
5296 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5299 ZERO_STRUCT(driver);
5301 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5303 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5305 if (!W_ERROR_IS_OK(status))
5306 return WERR_INVALID_PRINTER_NAME;
5308 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5310 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5312 if (!W_ERROR_IS_OK(status))
5315 * Is this a W2k client ?
5319 free_a_printer(&printer,2);
5320 return WERR_UNKNOWN_PRINTER_DRIVER;
5323 /* Yes - try again with a WinNT driver. */
5325 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)));
5327 if (!W_ERROR_IS_OK(status)) {
5328 free_a_printer(&printer,2);
5329 return WERR_UNKNOWN_PRINTER_DRIVER;
5333 fill_printer_driver_info_6(info, driver, servername);
5335 free_a_printer(&printer,2);
5336 free_a_printer_driver(driver, 3);
5341 /****************************************************************************
5342 ****************************************************************************/
5344 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5346 SAFE_FREE(info->dependentfiles);
5349 /****************************************************************************
5350 ****************************************************************************/
5352 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5354 SAFE_FREE(info->dependentfiles);
5357 /****************************************************************************
5358 ****************************************************************************/
5360 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5362 DRIVER_INFO_1 *info=NULL;
5365 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5368 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5369 if (!W_ERROR_IS_OK(result))
5372 /* check the required size. */
5373 *needed += spoolss_size_printer_driver_info_1(info);
5375 if (*needed > offered) {
5376 result = WERR_INSUFFICIENT_BUFFER;
5380 if (!rpcbuf_alloc_size(buffer, *needed)) {
5381 result = WERR_NOMEM;
5385 /* fill the buffer with the structures */
5386 smb_io_printer_driver_info_1("", buffer, info, 0);
5395 /****************************************************************************
5396 ****************************************************************************/
5398 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5400 DRIVER_INFO_2 *info=NULL;
5403 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5406 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5407 if (!W_ERROR_IS_OK(result))
5410 /* check the required size. */
5411 *needed += spoolss_size_printer_driver_info_2(info);
5413 if (*needed > offered) {
5414 result = WERR_INSUFFICIENT_BUFFER;
5418 if (!rpcbuf_alloc_size(buffer, *needed)) {
5419 result = WERR_NOMEM;
5423 /* fill the buffer with the structures */
5424 smb_io_printer_driver_info_2("", buffer, info, 0);
5433 /****************************************************************************
5434 ****************************************************************************/
5436 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5443 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5444 if (!W_ERROR_IS_OK(result))
5447 /* check the required size. */
5448 *needed += spoolss_size_printer_driver_info_3(&info);
5450 if (*needed > offered) {
5451 result = WERR_INSUFFICIENT_BUFFER;
5455 if (!rpcbuf_alloc_size(buffer, *needed)) {
5456 result = WERR_NOMEM;
5460 /* fill the buffer with the structures */
5461 smb_io_printer_driver_info_3("", buffer, &info, 0);
5464 free_printer_driver_info_3(&info);
5469 /****************************************************************************
5470 ****************************************************************************/
5472 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5479 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5480 if (!W_ERROR_IS_OK(result))
5483 /* check the required size. */
5484 *needed += spoolss_size_printer_driver_info_6(&info);
5486 if (*needed > offered) {
5487 result = WERR_INSUFFICIENT_BUFFER;
5491 if (!rpcbuf_alloc_size(buffer, *needed)) {
5492 result = WERR_NOMEM;
5496 /* fill the buffer with the structures */
5497 smb_io_printer_driver_info_6("", buffer, &info, 0);
5500 free_printer_driver_info_6(&info);
5505 /****************************************************************************
5506 ****************************************************************************/
5508 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5510 POLICY_HND *handle = &q_u->handle;
5511 UNISTR2 *uni_arch = &q_u->architecture;
5512 uint32 level = q_u->level;
5513 uint32 clientmajorversion = q_u->clientmajorversion;
5514 RPC_BUFFER *buffer = NULL;
5515 uint32 offered = q_u->offered;
5516 uint32 *needed = &r_u->needed;
5517 uint32 *servermajorversion = &r_u->servermajorversion;
5518 uint32 *serverminorversion = &r_u->serverminorversion;
5519 Printer_entry *printer;
5522 fstring architecture;
5525 /* that's an [in out] buffer */
5527 if ( q_u->buffer ) {
5528 rpcbuf_move(q_u->buffer, &r_u->buffer);
5529 buffer = r_u->buffer;
5532 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5534 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5535 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5536 return WERR_INVALID_PRINTER_NAME;
5540 *servermajorversion = 0;
5541 *serverminorversion = 0;
5543 fstrcpy(servername, get_server_name( printer ));
5544 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5546 if (!get_printer_snum(p, handle, &snum))
5551 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5553 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5555 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5557 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5560 /* apparently this call is the equivalent of
5561 EnumPrinterDataEx() for the DsDriver key */
5566 return WERR_UNKNOWN_LEVEL;
5569 /****************************************************************************
5570 ****************************************************************************/
5572 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5574 POLICY_HND *handle = &q_u->handle;
5576 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5579 DEBUG(3,("Error in startpageprinter printer handle\n"));
5583 Printer->page_started=True;
5587 /****************************************************************************
5588 ****************************************************************************/
5590 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5592 POLICY_HND *handle = &q_u->handle;
5595 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5598 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5602 if (!get_printer_snum(p, handle, &snum))
5605 Printer->page_started=False;
5606 print_job_endpage(snum, Printer->jobid);
5611 /********************************************************************
5612 * api_spoolss_getprinter
5613 * called from the spoolss dispatcher
5615 ********************************************************************/
5617 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5619 POLICY_HND *handle = &q_u->handle;
5620 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5621 uint32 *jobid = &r_u->jobid;
5623 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5627 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5628 struct current_user user;
5631 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5635 get_current_user(&user, p);
5638 * a nice thing with NT is it doesn't listen to what you tell it.
5639 * when asked to send _only_ RAW datas, it tries to send datas
5642 * So I add checks like in NT Server ...
5645 if (info_1->p_datatype != 0) {
5646 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5647 if (strcmp(datatype, "RAW") != 0) {
5649 return WERR_INVALID_DATATYPE;
5653 /* get the share number of the printer */
5654 if (!get_printer_snum(p, handle, &snum)) {
5658 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5660 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5662 /* An error occured in print_job_start() so return an appropriate
5665 if (Printer->jobid == -1) {
5666 return map_werror_from_unix(errno);
5669 Printer->document_started=True;
5670 (*jobid) = Printer->jobid;
5675 /********************************************************************
5676 * api_spoolss_getprinter
5677 * called from the spoolss dispatcher
5679 ********************************************************************/
5681 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5683 POLICY_HND *handle = &q_u->handle;
5685 return _spoolss_enddocprinter_internal(p, handle);
5688 /****************************************************************************
5689 ****************************************************************************/
5691 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5693 POLICY_HND *handle = &q_u->handle;
5694 uint32 buffer_size = q_u->buffer_size;
5695 uint8 *buffer = q_u->buffer;
5696 uint32 *buffer_written = &q_u->buffer_size2;
5698 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5701 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5702 r_u->buffer_written = q_u->buffer_size2;
5706 if (!get_printer_snum(p, handle, &snum))
5709 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5710 (SMB_OFF_T)-1, (size_t)buffer_size);
5711 if (*buffer_written == (uint32)-1) {
5712 r_u->buffer_written = 0;
5713 if (errno == ENOSPC)
5714 return WERR_NO_SPOOL_SPACE;
5716 return WERR_ACCESS_DENIED;
5719 r_u->buffer_written = q_u->buffer_size2;
5724 /********************************************************************
5725 * api_spoolss_getprinter
5726 * called from the spoolss dispatcher
5728 ********************************************************************/
5730 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5733 struct current_user user;
5735 WERROR errcode = WERR_BADFUNC;
5736 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5738 get_current_user(&user, p);
5741 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5745 if (!get_printer_snum(p, handle, &snum))
5749 case PRINTER_CONTROL_PAUSE:
5750 if (print_queue_pause(&user, snum, &errcode)) {
5754 case PRINTER_CONTROL_RESUME:
5755 case PRINTER_CONTROL_UNPAUSE:
5756 if (print_queue_resume(&user, snum, &errcode)) {
5760 case PRINTER_CONTROL_PURGE:
5761 if (print_queue_purge(&user, snum, &errcode)) {
5766 return WERR_UNKNOWN_LEVEL;
5772 /********************************************************************
5773 * api_spoolss_abortprinter
5774 * From MSDN: "Deletes printer's spool file if printer is configured
5776 ********************************************************************/
5778 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5780 POLICY_HND *handle = &q_u->handle;
5781 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5783 struct current_user user;
5784 WERROR errcode = WERR_OK;
5787 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5791 if (!get_printer_snum(p, handle, &snum))
5794 get_current_user( &user, p );
5796 print_job_delete( &user, snum, Printer->jobid, &errcode );
5801 /********************************************************************
5802 * called by spoolss_api_setprinter
5803 * when updating a printer description
5804 ********************************************************************/
5806 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5807 const SPOOL_PRINTER_INFO_LEVEL *info,
5808 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5810 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5814 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5816 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5817 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5818 OUR_HANDLE(handle)));
5820 result = WERR_BADFID;
5824 /* Check the user has permissions to change the security
5825 descriptor. By experimentation with two NT machines, the user
5826 requires Full Access to the printer to change security
5829 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5830 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5831 result = WERR_ACCESS_DENIED;
5835 /* NT seems to like setting the security descriptor even though
5836 nothing may have actually changed. */
5838 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5840 if (DEBUGLEVEL >= 10) {
5844 the_acl = old_secdesc_ctr->sec->dacl;
5845 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5846 PRINTERNAME(snum), the_acl->num_aces));
5848 for (i = 0; i < the_acl->num_aces; i++) {
5851 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5853 DEBUG(10, ("%s 0x%08x\n", sid_str,
5854 the_acl->ace[i].info.mask));
5857 the_acl = secdesc_ctr->sec->dacl;
5860 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5861 PRINTERNAME(snum), the_acl->num_aces));
5863 for (i = 0; i < the_acl->num_aces; i++) {
5866 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5868 DEBUG(10, ("%s 0x%08x\n", sid_str,
5869 the_acl->ace[i].info.mask));
5872 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5876 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5878 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5883 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5890 /********************************************************************
5891 Canonicalize printer info from a client
5893 ATTN: It does not matter what we set the servername to hear
5894 since we do the necessary work in get_a_printer() to set it to
5895 the correct value based on what the client sent in the
5896 _spoolss_open_printer_ex().
5897 ********************************************************************/
5899 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5901 fstring printername;
5904 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5905 "portname=%s drivername=%s comment=%s location=%s\n",
5906 info->servername, info->printername, info->sharename,
5907 info->portname, info->drivername, info->comment, info->location));
5909 /* we force some elements to "correct" values */
5910 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5911 fstrcpy(info->sharename, lp_servicename(snum));
5913 /* check to see if we allow printername != sharename */
5915 if ( lp_force_printername(snum) ) {
5916 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5917 global_myname(), info->sharename );
5920 /* make sure printername is in \\server\printername format */
5922 fstrcpy( printername, info->printername );
5924 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5925 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5929 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5930 global_myname(), p );
5933 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5934 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5941 /****************************************************************************
5942 ****************************************************************************/
5944 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5946 char *cmd = lp_addprinter_cmd();
5952 fstring remote_machine = "%m";
5953 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5954 BOOL is_print_op = False;
5956 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5958 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5959 cmd, printer->info_2->printername, printer->info_2->sharename,
5960 printer->info_2->portname, printer->info_2->drivername,
5961 printer->info_2->location, printer->info_2->comment, remote_machine);
5964 is_print_op = user_has_privileges( token, &se_printop );
5966 DEBUG(10,("Running [%s]\n", command));
5968 /********* BEGIN SePrintOperatorPrivilege **********/
5973 if ( (ret = smbrun(command, &fd)) == 0 ) {
5974 /* Tell everyone we updated smb.conf. */
5975 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
5981 /********* END SePrintOperatorPrivilege **********/
5983 DEBUGADD(10,("returned [%d]\n", ret));
5991 /* reload our services immediately */
5992 reload_services( False );
5995 /* Get lines and convert them back to dos-codepage */
5996 qlines = fd_lines_load(fd, &numlines, 0);
5997 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6000 /* Set the portname to what the script says the portname should be. */
6001 /* but don't require anything to be return from the script exit a good error code */
6004 /* Set the portname to what the script says the portname should be. */
6005 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6006 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6009 file_lines_free(qlines);
6013 /********************************************************************
6014 * Called by spoolss_api_setprinter
6015 * when updating a printer description.
6016 ********************************************************************/
6018 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6019 const SPOOL_PRINTER_INFO_LEVEL *info,
6020 DEVICEMODE *devmode)
6023 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6024 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6029 DEBUG(8,("update_printer\n"));
6034 result = WERR_BADFID;
6038 if (!get_printer_snum(p, handle, &snum)) {
6039 result = WERR_BADFID;
6043 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6044 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6045 result = WERR_BADFID;
6049 DEBUGADD(8,("Converting info_2 struct\n"));
6052 * convert_printer_info converts the incoming
6053 * info from the client and overwrites the info
6054 * just read from the tdb in the pointer 'printer'.
6057 if (!convert_printer_info(info, printer, level)) {
6058 result = WERR_NOMEM;
6063 /* we have a valid devmode
6064 convert it and link it*/
6066 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6067 if (!convert_devicemode(printer->info_2->printername, devmode,
6068 &printer->info_2->devmode)) {
6069 result = WERR_NOMEM;
6074 /* Do sanity check on the requested changes for Samba */
6076 if (!check_printer_ok(printer->info_2, snum)) {
6077 result = WERR_INVALID_PARAM;
6081 /* FIXME!!! If the driver has changed we really should verify that
6082 it is installed before doing much else --jerry */
6084 /* Check calling user has permission to update printer description */
6086 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6087 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6088 result = WERR_ACCESS_DENIED;
6092 /* Call addprinter hook */
6093 /* Check changes to see if this is really needed */
6095 if ( *lp_addprinter_cmd()
6096 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6097 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6098 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6099 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6101 /* add_printer_hook() will call reload_services() */
6103 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6104 result = WERR_ACCESS_DENIED;
6110 * When a *new* driver is bound to a printer, the drivername is used to
6111 * lookup previously saved driver initialization info, which is then
6112 * bound to the printer, simulating what happens in the Windows arch.
6114 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6116 if (!set_driver_init(printer, 2))
6118 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6119 printer->info_2->drivername));
6122 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6123 printer->info_2->drivername));
6125 notify_printer_driver(snum, printer->info_2->drivername);
6129 * flag which changes actually occured. This is a small subset of
6130 * all the possible changes. We also have to update things in the
6134 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6135 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6136 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6137 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6139 notify_printer_comment(snum, printer->info_2->comment);
6142 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6143 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6144 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6145 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6147 notify_printer_sharename(snum, printer->info_2->sharename);
6150 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6153 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6156 pname = printer->info_2->printername;
6159 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6160 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6161 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6163 notify_printer_printername( snum, pname );
6166 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6167 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6168 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6169 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6171 notify_printer_port(snum, printer->info_2->portname);
6174 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6175 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6176 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6177 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6179 notify_printer_location(snum, printer->info_2->location);
6182 /* here we need to update some more DsSpooler keys */
6183 /* uNCName, serverName, shortServerName */
6185 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6186 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6187 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6188 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6189 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6191 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6192 global_myname(), printer->info_2->sharename );
6193 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6194 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6195 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6197 /* Update printer info */
6198 result = mod_a_printer(printer, 2);
6201 free_a_printer(&printer, 2);
6202 free_a_printer(&old_printer, 2);
6208 /****************************************************************************
6209 ****************************************************************************/
6210 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6211 const SPOOL_PRINTER_INFO_LEVEL *info)
6214 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6216 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6218 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6223 if (!get_printer_snum(p, handle, &snum))
6226 nt_printer_publish(Printer, snum, info7->action);
6230 return WERR_UNKNOWN_LEVEL;
6233 /****************************************************************************
6234 ****************************************************************************/
6236 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6238 POLICY_HND *handle = &q_u->handle;
6239 uint32 level = q_u->level;
6240 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6241 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6242 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6243 uint32 command = q_u->command;
6246 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6249 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6253 /* check the level */
6256 return control_printer(handle, command, p);
6258 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6259 if (!W_ERROR_IS_OK(result))
6262 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6265 return update_printer_sec(handle, level, info, p,
6268 return publish_or_unpublish_printer(p, handle, info);
6270 return WERR_UNKNOWN_LEVEL;
6274 /****************************************************************************
6275 ****************************************************************************/
6277 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6279 POLICY_HND *handle = &q_u->handle;
6280 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6283 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6287 if (Printer->notify.client_connected==True) {
6290 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6292 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6293 !get_printer_snum(p, handle, &snum) )
6296 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6299 Printer->notify.flags=0;
6300 Printer->notify.options=0;
6301 Printer->notify.localmachine[0]='\0';
6302 Printer->notify.printerlocal=0;
6303 if (Printer->notify.option)
6304 free_spool_notify_option(&Printer->notify.option);
6305 Printer->notify.client_connected=False;
6310 /****************************************************************************
6311 ****************************************************************************/
6313 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6315 /* that's an [in out] buffer */
6318 rpcbuf_move(q_u->buffer, &r_u->buffer);
6321 return WERR_INVALID_PARAM; /* this is what a NT server
6322 returns for AddJob. AddJob
6323 must fail on non-local
6327 /****************************************************************************
6328 ****************************************************************************/
6330 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6331 int position, int snum,
6332 NT_PRINTER_INFO_LEVEL *ntprinter)
6336 t=gmtime(&queue->time);
6338 job_info->jobid=queue->job;
6339 init_unistr(&job_info->printername, lp_servicename(snum));
6340 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6341 init_unistr(&job_info->username, queue->fs_user);
6342 init_unistr(&job_info->document, queue->fs_file);
6343 init_unistr(&job_info->datatype, "RAW");
6344 init_unistr(&job_info->text_status, "");
6345 job_info->status=nt_printj_status(queue->status);
6346 job_info->priority=queue->priority;
6347 job_info->position=position;
6348 job_info->totalpages=queue->page_count;
6349 job_info->pagesprinted=0;
6351 make_systemtime(&job_info->submitted, t);
6354 /****************************************************************************
6355 ****************************************************************************/
6357 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6358 int position, int snum,
6359 NT_PRINTER_INFO_LEVEL *ntprinter,
6360 DEVICEMODE *devmode)
6364 t=gmtime(&queue->time);
6366 job_info->jobid=queue->job;
6368 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6370 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6371 init_unistr(&job_info->username, queue->fs_user);
6372 init_unistr(&job_info->document, queue->fs_file);
6373 init_unistr(&job_info->notifyname, queue->fs_user);
6374 init_unistr(&job_info->datatype, "RAW");
6375 init_unistr(&job_info->printprocessor, "winprint");
6376 init_unistr(&job_info->parameters, "");
6377 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6378 init_unistr(&job_info->text_status, "");
6380 /* and here the security descriptor */
6382 job_info->status=nt_printj_status(queue->status);
6383 job_info->priority=queue->priority;
6384 job_info->position=position;
6385 job_info->starttime=0;
6386 job_info->untiltime=0;
6387 job_info->totalpages=queue->page_count;
6388 job_info->size=queue->size;
6389 make_systemtime(&(job_info->submitted), t);
6390 job_info->timeelapsed=0;
6391 job_info->pagesprinted=0;
6393 job_info->devmode = devmode;
6398 /****************************************************************************
6399 Enumjobs at level 1.
6400 ****************************************************************************/
6402 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6403 NT_PRINTER_INFO_LEVEL *ntprinter,
6404 RPC_BUFFER *buffer, uint32 offered,
6405 uint32 *needed, uint32 *returned)
6409 WERROR result = WERR_OK;
6411 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6418 for (i=0; i<*returned; i++)
6419 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6423 /* check the required size. */
6424 for (i=0; i<*returned; i++)
6425 (*needed) += spoolss_size_job_info_1(&info[i]);
6427 if (*needed > offered) {
6428 result = WERR_INSUFFICIENT_BUFFER;
6432 if (!rpcbuf_alloc_size(buffer, *needed)) {
6433 result = WERR_NOMEM;
6437 /* fill the buffer with the structures */
6438 for (i=0; i<*returned; i++)
6439 smb_io_job_info_1("", buffer, &info[i], 0);
6445 if ( !W_ERROR_IS_OK(result) )
6451 /****************************************************************************
6452 Enumjobs at level 2.
6453 ****************************************************************************/
6455 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6456 NT_PRINTER_INFO_LEVEL *ntprinter,
6457 RPC_BUFFER *buffer, uint32 offered,
6458 uint32 *needed, uint32 *returned)
6460 JOB_INFO_2 *info = NULL;
6462 WERROR result = WERR_OK;
6463 DEVICEMODE *devmode = NULL;
6465 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6470 /* this should not be a failure condition if the devmode is NULL */
6472 devmode = construct_dev_mode(snum);
6474 for (i=0; i<*returned; i++)
6475 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6477 free_a_printer(&ntprinter, 2);
6480 /* check the required size. */
6481 for (i=0; i<*returned; i++)
6482 (*needed) += spoolss_size_job_info_2(&info[i]);
6484 if (*needed > offered) {
6485 result = WERR_INSUFFICIENT_BUFFER;
6489 if (!rpcbuf_alloc_size(buffer, *needed)) {
6490 result = WERR_NOMEM;
6494 /* fill the buffer with the structures */
6495 for (i=0; i<*returned; i++)
6496 smb_io_job_info_2("", buffer, &info[i], 0);
6499 free_devmode(devmode);
6502 if ( !W_ERROR_IS_OK(result) )
6509 /****************************************************************************
6511 ****************************************************************************/
6513 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6515 POLICY_HND *handle = &q_u->handle;
6516 uint32 level = q_u->level;
6517 RPC_BUFFER *buffer = NULL;
6518 uint32 offered = q_u->offered;
6519 uint32 *needed = &r_u->needed;
6520 uint32 *returned = &r_u->returned;
6522 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6524 print_status_struct prt_status;
6525 print_queue_struct *queue=NULL;
6527 /* that's an [in out] buffer */
6529 if ( q_u->buffer ) {
6530 rpcbuf_move(q_u->buffer, &r_u->buffer);
6531 buffer = r_u->buffer;
6534 DEBUG(4,("_spoolss_enumjobs\n"));
6539 /* lookup the printer snum and tdb entry */
6541 if (!get_printer_snum(p, handle, &snum))
6544 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6545 if ( !W_ERROR_IS_OK(wret) )
6548 *returned = print_queue_status(snum, &queue, &prt_status);
6549 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6551 if (*returned == 0) {
6558 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6561 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6566 wret = WERR_UNKNOWN_LEVEL;
6569 free_a_printer( &ntprinter, 2 );
6573 /****************************************************************************
6574 ****************************************************************************/
6576 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6581 /****************************************************************************
6582 ****************************************************************************/
6584 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6586 POLICY_HND *handle = &q_u->handle;
6587 uint32 jobid = q_u->jobid;
6588 uint32 command = q_u->command;
6590 struct current_user user;
6592 WERROR errcode = WERR_BADFUNC;
6594 if (!get_printer_snum(p, handle, &snum)) {
6598 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6599 return WERR_INVALID_PRINTER_NAME;
6602 get_current_user(&user, p);
6605 case JOB_CONTROL_CANCEL:
6606 case JOB_CONTROL_DELETE:
6607 if (print_job_delete(&user, snum, jobid, &errcode)) {
6611 case JOB_CONTROL_PAUSE:
6612 if (print_job_pause(&user, snum, jobid, &errcode)) {
6616 case JOB_CONTROL_RESTART:
6617 case JOB_CONTROL_RESUME:
6618 if (print_job_resume(&user, snum, jobid, &errcode)) {
6623 return WERR_UNKNOWN_LEVEL;
6629 /****************************************************************************
6630 Enumerates all printer drivers at level 1.
6631 ****************************************************************************/
6633 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6638 fstring *list = NULL;
6639 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6640 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6641 WERROR result = WERR_OK;
6645 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6647 ndrivers=get_ntdrivers(&list, architecture, version);
6648 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6654 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6655 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6656 SAFE_FREE(driver_info_1);
6660 else driver_info_1 = tdi1;
6663 for (i=0; i<ndrivers; i++) {
6665 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6666 ZERO_STRUCT(driver);
6667 status = get_a_printer_driver(&driver, 3, list[i],
6668 architecture, version);
6669 if (!W_ERROR_IS_OK(status)) {
6673 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6674 free_a_printer_driver(driver, 3);
6677 *returned+=ndrivers;
6681 /* check the required size. */
6682 for (i=0; i<*returned; i++) {
6683 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6684 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6687 if (*needed > offered) {
6688 result = WERR_INSUFFICIENT_BUFFER;
6692 if (!rpcbuf_alloc_size(buffer, *needed)) {
6693 result = WERR_NOMEM;
6697 /* fill the buffer with the driver structures */
6698 for (i=0; i<*returned; i++) {
6699 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6700 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6704 SAFE_FREE(driver_info_1);
6706 if ( !W_ERROR_IS_OK(result) )
6712 /****************************************************************************
6713 Enumerates all printer drivers at level 2.
6714 ****************************************************************************/
6716 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6721 fstring *list = NULL;
6722 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6723 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6724 WERROR result = WERR_OK;
6728 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6730 ndrivers=get_ntdrivers(&list, architecture, version);
6731 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6737 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6738 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6739 SAFE_FREE(driver_info_2);
6743 else driver_info_2 = tdi2;
6746 for (i=0; i<ndrivers; i++) {
6749 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6750 ZERO_STRUCT(driver);
6751 status = get_a_printer_driver(&driver, 3, list[i],
6752 architecture, version);
6753 if (!W_ERROR_IS_OK(status)) {
6757 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6758 free_a_printer_driver(driver, 3);
6761 *returned+=ndrivers;
6765 /* check the required size. */
6766 for (i=0; i<*returned; i++) {
6767 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6768 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6771 if (*needed > offered) {
6772 result = WERR_INSUFFICIENT_BUFFER;
6776 if (!rpcbuf_alloc_size(buffer, *needed)) {
6777 result = WERR_NOMEM;
6781 /* fill the buffer with the form structures */
6782 for (i=0; i<*returned; i++) {
6783 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6784 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6788 SAFE_FREE(driver_info_2);
6790 if ( !W_ERROR_IS_OK(result) )
6796 /****************************************************************************
6797 Enumerates all printer drivers at level 3.
6798 ****************************************************************************/
6800 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6805 fstring *list = NULL;
6806 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6807 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6808 WERROR result = WERR_OK;
6812 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6814 ndrivers=get_ntdrivers(&list, architecture, version);
6815 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6821 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6822 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6823 SAFE_FREE(driver_info_3);
6827 else driver_info_3 = tdi3;
6830 for (i=0; i<ndrivers; i++) {
6833 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6834 ZERO_STRUCT(driver);
6835 status = get_a_printer_driver(&driver, 3, list[i],
6836 architecture, version);
6837 if (!W_ERROR_IS_OK(status)) {
6841 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6842 free_a_printer_driver(driver, 3);
6845 *returned+=ndrivers;
6849 /* check the required size. */
6850 for (i=0; i<*returned; i++) {
6851 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6852 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6855 if (*needed > offered) {
6856 result = WERR_INSUFFICIENT_BUFFER;
6860 if (!rpcbuf_alloc_size(buffer, *needed)) {
6861 result = WERR_NOMEM;
6865 /* fill the buffer with the driver structures */
6866 for (i=0; i<*returned; i++) {
6867 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6868 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6872 for (i=0; i<*returned; i++)
6873 SAFE_FREE(driver_info_3[i].dependentfiles);
6875 SAFE_FREE(driver_info_3);
6877 if ( !W_ERROR_IS_OK(result) )
6883 /****************************************************************************
6884 Enumerates all printer drivers.
6885 ****************************************************************************/
6887 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6889 uint32 level = q_u->level;
6890 RPC_BUFFER *buffer = NULL;
6891 uint32 offered = q_u->offered;
6892 uint32 *needed = &r_u->needed;
6893 uint32 *returned = &r_u->returned;
6896 fstring architecture;
6898 /* that's an [in out] buffer */
6900 if ( q_u->buffer ) {
6901 rpcbuf_move(q_u->buffer, &r_u->buffer);
6902 buffer = r_u->buffer;
6905 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6910 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6911 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6913 if ( !is_myname_or_ipaddr( servername ) )
6914 return WERR_UNKNOWN_PRINTER_DRIVER;
6918 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6920 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6922 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6924 return WERR_UNKNOWN_LEVEL;
6928 /****************************************************************************
6929 ****************************************************************************/
6931 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6933 form->flag=list->flag;
6934 init_unistr(&form->name, list->name);
6935 form->width=list->width;
6936 form->length=list->length;
6937 form->left=list->left;
6938 form->top=list->top;
6939 form->right=list->right;
6940 form->bottom=list->bottom;
6943 /****************************************************************************
6944 ****************************************************************************/
6946 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6948 uint32 level = q_u->level;
6949 RPC_BUFFER *buffer = NULL;
6950 uint32 offered = q_u->offered;
6951 uint32 *needed = &r_u->needed;
6952 uint32 *numofforms = &r_u->numofforms;
6953 uint32 numbuiltinforms;
6955 nt_forms_struct *list=NULL;
6956 nt_forms_struct *builtinlist=NULL;
6961 /* that's an [in out] buffer */
6963 if ( q_u->buffer ) {
6964 rpcbuf_move(q_u->buffer, &r_u->buffer);
6965 buffer = r_u->buffer;
6968 DEBUG(4,("_spoolss_enumforms\n"));
6969 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6970 DEBUGADD(5,("Info level [%d]\n", level));
6972 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6973 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6974 *numofforms = get_ntforms(&list);
6975 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6976 *numofforms += numbuiltinforms;
6978 if (*numofforms == 0)
6979 return WERR_NO_MORE_ITEMS;
6983 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
6988 /* construct the list of form structures */
6989 for (i=0; i<numbuiltinforms; i++) {
6990 DEBUGADD(6,("Filling form number [%d]\n",i));
6991 fill_form_1(&forms_1[i], &builtinlist[i]);
6994 SAFE_FREE(builtinlist);
6996 for (; i<*numofforms; i++) {
6997 DEBUGADD(6,("Filling form number [%d]\n",i));
6998 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7003 /* check the required size. */
7004 for (i=0; i<numbuiltinforms; i++) {
7005 DEBUGADD(6,("adding form [%d]'s size\n",i));
7006 buffer_size += spoolss_size_form_1(&forms_1[i]);
7008 for (; i<*numofforms; i++) {
7009 DEBUGADD(6,("adding form [%d]'s size\n",i));
7010 buffer_size += spoolss_size_form_1(&forms_1[i]);
7013 *needed=buffer_size;
7015 if (*needed > offered) {
7018 return WERR_INSUFFICIENT_BUFFER;
7021 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7027 /* fill the buffer with the form structures */
7028 for (i=0; i<numbuiltinforms; i++) {
7029 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7030 smb_io_form_1("", buffer, &forms_1[i], 0);
7032 for (; i<*numofforms; i++) {
7033 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7034 smb_io_form_1("", buffer, &forms_1[i], 0);
7043 SAFE_FREE(builtinlist);
7044 return WERR_UNKNOWN_LEVEL;
7049 /****************************************************************************
7050 ****************************************************************************/
7052 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7054 uint32 level = q_u->level;
7055 UNISTR2 *uni_formname = &q_u->formname;
7056 RPC_BUFFER *buffer = NULL;
7057 uint32 offered = q_u->offered;
7058 uint32 *needed = &r_u->needed;
7060 nt_forms_struct *list=NULL;
7061 nt_forms_struct builtin_form;
7066 int numofforms=0, i=0;
7068 /* that's an [in out] buffer */
7070 if ( q_u->buffer ) {
7071 rpcbuf_move(q_u->buffer, &r_u->buffer);
7072 buffer = r_u->buffer;
7075 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7077 DEBUG(4,("_spoolss_getform\n"));
7078 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7079 DEBUGADD(5,("Info level [%d]\n", level));
7081 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7082 if (!foundBuiltin) {
7083 numofforms = get_ntforms(&list);
7084 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7086 if (numofforms == 0)
7093 fill_form_1(&form_1, &builtin_form);
7096 /* Check if the requested name is in the list of form structures */
7097 for (i=0; i<numofforms; i++) {
7099 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7101 if (strequal(form_name, list[i].name)) {
7102 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7103 fill_form_1(&form_1, &list[i]);
7109 if (i == numofforms) {
7113 /* check the required size. */
7115 *needed=spoolss_size_form_1(&form_1);
7117 if (*needed > offered)
7118 return WERR_INSUFFICIENT_BUFFER;
7120 if (!rpcbuf_alloc_size(buffer, buffer_size))
7123 /* fill the buffer with the form structures */
7124 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7125 smb_io_form_1("", buffer, &form_1, 0);
7131 return WERR_UNKNOWN_LEVEL;
7135 /****************************************************************************
7136 ****************************************************************************/
7138 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7140 init_unistr(&port->port_name, name);
7143 /****************************************************************************
7144 ****************************************************************************/
7146 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7148 init_unistr(&port->port_name, name);
7149 init_unistr(&port->monitor_name, "Local Monitor");
7150 init_unistr(&port->description, "Local Port");
7151 port->port_type=PORT_TYPE_WRITE;
7156 /****************************************************************************
7157 wrapper around the enumer ports command
7158 ****************************************************************************/
7160 WERROR enumports_hook( int *count, char ***lines )
7162 char *cmd = lp_enumports_cmd();
7170 /* if no hook then just fill in the default port */
7173 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7174 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7179 /* we have a valid enumport command */
7181 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7183 DEBUG(10,("Running [%s]\n", command));
7184 ret = smbrun(command, &fd);
7185 DEBUG(10,("Returned [%d]\n", ret));
7190 return WERR_ACCESS_DENIED;
7194 qlines = fd_lines_load(fd, &numlines, 0);
7195 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7205 /****************************************************************************
7207 ****************************************************************************/
7209 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7211 PORT_INFO_1 *ports=NULL;
7213 WERROR result = WERR_OK;
7217 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7221 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7222 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7223 dos_errstr(WERR_NOMEM)));
7224 file_lines_free(qlines);
7228 for (i=0; i<numlines; i++) {
7229 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7230 fill_port_1(&ports[i], qlines[i]);
7233 file_lines_free(qlines);
7236 *returned = numlines;
7238 /* check the required size. */
7239 for (i=0; i<*returned; i++) {
7240 DEBUGADD(6,("adding port [%d]'s size\n", i));
7241 *needed += spoolss_size_port_info_1(&ports[i]);
7244 if (*needed > offered) {
7245 result = WERR_INSUFFICIENT_BUFFER;
7249 if (!rpcbuf_alloc_size(buffer, *needed)) {
7250 result = WERR_NOMEM;
7254 /* fill the buffer with the ports structures */
7255 for (i=0; i<*returned; i++) {
7256 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7257 smb_io_port_1("", buffer, &ports[i], 0);
7263 if ( !W_ERROR_IS_OK(result) )
7269 /****************************************************************************
7271 ****************************************************************************/
7273 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7275 PORT_INFO_2 *ports=NULL;
7277 WERROR result = WERR_OK;
7281 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7286 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7287 file_lines_free(qlines);
7291 for (i=0; i<numlines; i++) {
7292 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7293 fill_port_2(&(ports[i]), qlines[i]);
7296 file_lines_free(qlines);
7299 *returned = numlines;
7301 /* check the required size. */
7302 for (i=0; i<*returned; i++) {
7303 DEBUGADD(6,("adding port [%d]'s size\n", i));
7304 *needed += spoolss_size_port_info_2(&ports[i]);
7307 if (*needed > offered) {
7308 result = WERR_INSUFFICIENT_BUFFER;
7312 if (!rpcbuf_alloc_size(buffer, *needed)) {
7313 result = WERR_NOMEM;
7317 /* fill the buffer with the ports structures */
7318 for (i=0; i<*returned; i++) {
7319 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7320 smb_io_port_2("", buffer, &ports[i], 0);
7326 if ( !W_ERROR_IS_OK(result) )
7332 /****************************************************************************
7334 ****************************************************************************/
7336 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7338 uint32 level = q_u->level;
7339 RPC_BUFFER *buffer = NULL;
7340 uint32 offered = q_u->offered;
7341 uint32 *needed = &r_u->needed;
7342 uint32 *returned = &r_u->returned;
7344 /* that's an [in out] buffer */
7346 if ( q_u->buffer ) {
7347 rpcbuf_move(q_u->buffer, &r_u->buffer);
7348 buffer = r_u->buffer;
7351 DEBUG(4,("_spoolss_enumports\n"));
7358 return enumports_level_1(buffer, offered, needed, returned);
7360 return enumports_level_2(buffer, offered, needed, returned);
7362 return WERR_UNKNOWN_LEVEL;
7366 /****************************************************************************
7367 ****************************************************************************/
7369 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7370 const SPOOL_PRINTER_INFO_LEVEL *info,
7371 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7372 uint32 user_switch, const SPOOL_USER_CTR *user,
7375 NT_PRINTER_INFO_LEVEL *printer = NULL;
7378 WERROR err = WERR_OK;
7380 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7381 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7385 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7386 if (!convert_printer_info(info, printer, 2)) {
7387 free_a_printer(&printer, 2);
7391 /* check to see if the printer already exists */
7393 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7394 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7395 printer->info_2->sharename));
7396 free_a_printer(&printer, 2);
7397 return WERR_PRINTER_ALREADY_EXISTS;
7400 /* FIXME!!! smbd should check to see if the driver is installed before
7401 trying to add a printer like this --jerry */
7403 if (*lp_addprinter_cmd() ) {
7404 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7405 free_a_printer(&printer,2);
7406 return WERR_ACCESS_DENIED;
7409 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7410 "smb.conf parameter \"addprinter command\" is defined. This"
7411 "parameter must exist for this call to succeed\n",
7412 printer->info_2->sharename ));
7415 /* use our primary netbios name since get_a_printer() will convert
7416 it to what the client expects on a case by case basis */
7418 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7419 printer->info_2->sharename);
7422 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7423 free_a_printer(&printer,2);
7424 return WERR_ACCESS_DENIED;
7427 /* you must be a printer admin to add a new printer */
7428 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7429 free_a_printer(&printer,2);
7430 return WERR_ACCESS_DENIED;
7434 * Do sanity check on the requested changes for Samba.
7437 if (!check_printer_ok(printer->info_2, snum)) {
7438 free_a_printer(&printer,2);
7439 return WERR_INVALID_PARAM;
7443 * When a printer is created, the drivername bound to the printer is used
7444 * to lookup previously saved driver initialization info, which is then
7445 * bound to the new printer, simulating what happens in the Windows arch.
7450 set_driver_init(printer, 2);
7454 /* A valid devmode was included, convert and link it
7456 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7458 if (!convert_devicemode(printer->info_2->printername, devmode,
7459 &printer->info_2->devmode))
7463 /* write the ASCII on disk */
7464 err = mod_a_printer(printer, 2);
7465 if (!W_ERROR_IS_OK(err)) {
7466 free_a_printer(&printer,2);
7470 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7471 /* Handle open failed - remove addition. */
7472 del_a_printer(printer->info_2->sharename);
7473 free_a_printer(&printer,2);
7474 return WERR_ACCESS_DENIED;
7477 update_c_setprinter(False);
7478 free_a_printer(&printer,2);
7483 /****************************************************************************
7484 ****************************************************************************/
7486 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7488 UNISTR2 *uni_srv_name = q_u->server_name;
7489 uint32 level = q_u->level;
7490 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7491 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7492 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7493 uint32 user_switch = q_u->user_switch;
7494 SPOOL_USER_CTR *user = &q_u->user_ctr;
7495 POLICY_HND *handle = &r_u->handle;
7499 /* we don't handle yet */
7500 /* but I know what to do ... */
7501 return WERR_UNKNOWN_LEVEL;
7503 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7505 user_switch, user, handle);
7507 return WERR_UNKNOWN_LEVEL;
7511 /****************************************************************************
7512 ****************************************************************************/
7514 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7516 uint32 level = q_u->level;
7517 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7518 WERROR err = WERR_OK;
7519 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7520 struct current_user user;
7521 fstring driver_name;
7524 ZERO_STRUCT(driver);
7526 get_current_user(&user, p);
7528 if (!convert_printer_driver_info(info, &driver, level)) {
7533 DEBUG(5,("Cleaning driver's information\n"));
7534 err = clean_up_driver_struct(driver, level, &user);
7535 if (!W_ERROR_IS_OK(err))
7538 DEBUG(5,("Moving driver to final destination\n"));
7539 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7543 if (add_a_printer_driver(driver, level)!=0) {
7544 err = WERR_ACCESS_DENIED;
7548 /* BEGIN_ADMIN_LOG */
7551 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7552 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7553 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.ut.uid));
7556 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7557 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7558 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.ut.uid));
7564 * I think this is where he DrvUpgradePrinter() hook would be
7565 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7566 * server. Right now, we just need to send ourselves a message
7567 * to update each printer bound to this driver. --jerry
7570 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7571 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7576 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7577 * decide if the driver init data should be deleted. The rules are:
7578 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7579 * 2) delete init data only if there is no 2k/Xp driver
7580 * 3) always delete init data
7581 * The generalized rule is always use init data from the highest order driver.
7582 * It is necessary to follow the driver install by an initialization step to
7583 * finish off this process.
7586 version = driver.info_3->cversion;
7587 else if (level == 6)
7588 version = driver.info_6->version;
7593 * 9x printer driver - never delete init data
7596 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7601 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7602 * there is no 2k/Xp driver init data for this driver name.
7606 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7608 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7610 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7612 if (!del_driver_init(driver_name))
7613 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7616 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7618 free_a_printer_driver(driver1,3);
7619 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7626 * 2k or Xp printer driver - always delete init data
7629 if (!del_driver_init(driver_name))
7630 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7634 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7640 free_a_printer_driver(driver, level);
7644 /********************************************************************
7645 * spoolss_addprinterdriverex
7646 ********************************************************************/
7648 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7650 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7651 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7654 * we only support the semantics of AddPrinterDriver()
7655 * i.e. only copy files that are newer than existing ones
7658 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7659 return WERR_ACCESS_DENIED;
7661 ZERO_STRUCT(q_u_local);
7662 ZERO_STRUCT(r_u_local);
7664 /* just pass the information off to _spoolss_addprinterdriver() */
7665 q_u_local.server_name_ptr = q_u->server_name_ptr;
7666 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7667 q_u_local.level = q_u->level;
7668 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7670 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7673 /****************************************************************************
7674 ****************************************************************************/
7676 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7678 init_unistr(&info->name, name);
7681 /****************************************************************************
7682 ****************************************************************************/
7684 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7690 const char *short_archi;
7691 DRIVER_DIRECTORY_1 *info=NULL;
7692 WERROR result = WERR_OK;
7694 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7695 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7697 /* check for beginning double '\'s and that the server
7700 pservername = servername;
7701 if ( *pservername == '\\' && strlen(servername)>2 ) {
7705 if ( !is_myname_or_ipaddr( pservername ) )
7706 return WERR_INVALID_PARAM;
7708 if (!(short_archi = get_short_archi(long_archi)))
7709 return WERR_INVALID_ENVIRONMENT;
7711 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7714 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7716 DEBUG(4,("printer driver directory: [%s]\n", path));
7718 fill_driverdir_1(info, path);
7720 *needed += spoolss_size_driverdir_info_1(info);
7722 if (*needed > offered) {
7723 result = WERR_INSUFFICIENT_BUFFER;
7727 if (!rpcbuf_alloc_size(buffer, *needed)) {
7728 result = WERR_NOMEM;
7732 smb_io_driverdir_1("", buffer, info, 0);
7740 /****************************************************************************
7741 ****************************************************************************/
7743 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7745 UNISTR2 *name = &q_u->name;
7746 UNISTR2 *uni_environment = &q_u->environment;
7747 uint32 level = q_u->level;
7748 RPC_BUFFER *buffer = NULL;
7749 uint32 offered = q_u->offered;
7750 uint32 *needed = &r_u->needed;
7752 /* that's an [in out] buffer */
7754 if ( q_u->buffer ) {
7755 rpcbuf_move(q_u->buffer, &r_u->buffer);
7756 buffer = r_u->buffer;
7759 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7765 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7767 return WERR_UNKNOWN_LEVEL;
7771 /****************************************************************************
7772 ****************************************************************************/
7774 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7776 POLICY_HND *handle = &q_u->handle;
7777 uint32 idx = q_u->index;
7778 uint32 in_value_len = q_u->valuesize;
7779 uint32 in_data_len = q_u->datasize;
7780 uint32 *out_max_value_len = &r_u->valuesize;
7781 uint16 **out_value = &r_u->value;
7782 uint32 *out_value_len = &r_u->realvaluesize;
7783 uint32 *out_type = &r_u->type;
7784 uint32 *out_max_data_len = &r_u->datasize;
7785 uint8 **data_out = &r_u->data;
7786 uint32 *out_data_len = &r_u->realdatasize;
7788 NT_PRINTER_INFO_LEVEL *printer = NULL;
7790 uint32 biggest_valuesize;
7791 uint32 biggest_datasize;
7793 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7796 REGISTRY_VALUE *val = NULL;
7797 NT_PRINTER_DATA *p_data;
7798 int i, key_index, num_values;
7803 *out_max_data_len = 0;
7807 DEBUG(5,("spoolss_enumprinterdata\n"));
7810 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7814 if (!get_printer_snum(p,handle, &snum))
7817 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7818 if (!W_ERROR_IS_OK(result))
7821 p_data = printer->info_2->data;
7822 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7827 * The NT machine wants to know the biggest size of value and data
7829 * cf: MSDN EnumPrinterData remark section
7832 if ( !in_value_len && !in_data_len && (key_index != -1) )
7834 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7836 biggest_valuesize = 0;
7837 biggest_datasize = 0;
7839 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7841 for ( i=0; i<num_values; i++ )
7843 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7845 name_length = strlen(val->valuename);
7846 if ( strlen(val->valuename) > biggest_valuesize )
7847 biggest_valuesize = name_length;
7849 if ( val->size > biggest_datasize )
7850 biggest_datasize = val->size;
7852 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7856 /* the value is an UNICODE string but real_value_size is the length
7857 in bytes including the trailing 0 */
7859 *out_value_len = 2 * (1+biggest_valuesize);
7860 *out_data_len = biggest_datasize;
7862 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7868 * the value len is wrong in NT sp3
7869 * that's the number of bytes not the number of unicode chars
7872 if ( key_index != -1 )
7873 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7878 /* out_value should default to "" or else NT4 has
7879 problems unmarshalling the response */
7881 *out_max_value_len=(in_value_len/sizeof(uint16));
7883 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7885 result = WERR_NOMEM;
7889 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7891 /* the data is counted in bytes */
7893 *out_max_data_len = in_data_len;
7894 *out_data_len = in_data_len;
7896 /* only allocate when given a non-zero data_len */
7898 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7900 result = WERR_NOMEM;
7904 result = WERR_NO_MORE_ITEMS;
7910 * - counted in bytes in the request
7911 * - counted in UNICODE chars in the max reply
7912 * - counted in bytes in the real size
7914 * take a pause *before* coding not *during* coding
7918 *out_max_value_len=(in_value_len/sizeof(uint16));
7919 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7921 result = WERR_NOMEM;
7925 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7929 *out_type = regval_type( val );
7931 /* data - counted in bytes */
7933 *out_max_data_len = in_data_len;
7934 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7936 result = WERR_NOMEM;
7939 data_len = regval_size(val);
7941 memcpy( *data_out, regval_data_p(val), data_len );
7942 *out_data_len = data_len;
7946 free_a_printer(&printer, 2);
7950 /****************************************************************************
7951 ****************************************************************************/
7953 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7955 POLICY_HND *handle = &q_u->handle;
7956 UNISTR2 *value = &q_u->value;
7957 uint32 type = q_u->type;
7958 uint8 *data = q_u->data;
7959 uint32 real_len = q_u->real_len;
7961 NT_PRINTER_INFO_LEVEL *printer = NULL;
7963 WERROR status = WERR_OK;
7964 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7967 DEBUG(5,("spoolss_setprinterdata\n"));
7970 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7974 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7975 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7976 return WERR_INVALID_PARAM;
7979 if (!get_printer_snum(p,handle, &snum))
7983 * Access check : NT returns "access denied" if you make a
7984 * SetPrinterData call without the necessary privildge.
7985 * we were originally returning OK if nothing changed
7986 * which made Win2k issue **a lot** of SetPrinterData
7987 * when connecting to a printer --jerry
7990 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7992 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7993 status = WERR_ACCESS_DENIED;
7997 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7998 if (!W_ERROR_IS_OK(status))
8001 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8004 * When client side code sets a magic printer data key, detect it and save
8005 * the current printer data and the magic key's data (its the DEVMODE) for
8006 * future printer/driver initializations.
8008 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8010 /* Set devmode and printer initialization info */
8011 status = save_driver_init( printer, 2, data, real_len );
8013 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8017 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8018 type, data, real_len );
8019 if ( W_ERROR_IS_OK(status) )
8020 status = mod_a_printer(printer, 2);
8024 free_a_printer(&printer, 2);
8029 /****************************************************************************
8030 ****************************************************************************/
8032 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8034 POLICY_HND *handle = &q_u->handle;
8035 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8038 DEBUG(5,("_spoolss_resetprinter\n"));
8041 * All we do is to check to see if the handle and queue is valid.
8042 * This call really doesn't mean anything to us because we only
8043 * support RAW printing. --jerry
8047 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8051 if (!get_printer_snum(p,handle, &snum))
8055 /* blindly return success */
8060 /****************************************************************************
8061 ****************************************************************************/
8063 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8065 POLICY_HND *handle = &q_u->handle;
8066 UNISTR2 *value = &q_u->valuename;
8068 NT_PRINTER_INFO_LEVEL *printer = NULL;
8070 WERROR status = WERR_OK;
8071 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8074 DEBUG(5,("spoolss_deleteprinterdata\n"));
8077 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8081 if (!get_printer_snum(p, handle, &snum))
8084 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8085 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8086 return WERR_ACCESS_DENIED;
8089 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8090 if (!W_ERROR_IS_OK(status))
8093 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8095 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8097 if ( W_ERROR_IS_OK(status) )
8098 mod_a_printer( printer, 2 );
8100 free_a_printer(&printer, 2);
8105 /****************************************************************************
8106 ****************************************************************************/
8108 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8110 POLICY_HND *handle = &q_u->handle;
8111 FORM *form = &q_u->form;
8112 nt_forms_struct tmpForm;
8114 WERROR status = WERR_OK;
8115 NT_PRINTER_INFO_LEVEL *printer = NULL;
8118 nt_forms_struct *list=NULL;
8119 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8121 DEBUG(5,("spoolss_addform\n"));
8124 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8129 /* forms can be added on printer of on the print server handle */
8131 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8133 if (!get_printer_snum(p,handle, &snum))
8136 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8137 if (!W_ERROR_IS_OK(status))
8141 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8142 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8143 status = WERR_ACCESS_DENIED;
8147 /* can't add if builtin */
8149 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8150 status = WERR_ALREADY_EXISTS;
8154 count = get_ntforms(&list);
8156 if(!add_a_form(&list, form, &count)) {
8157 status = WERR_NOMEM;
8161 write_ntforms(&list, count);
8164 * ChangeID must always be set if this is a printer
8167 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8168 status = mod_a_printer(printer, 2);
8172 free_a_printer(&printer, 2);
8178 /****************************************************************************
8179 ****************************************************************************/
8181 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8183 POLICY_HND *handle = &q_u->handle;
8184 UNISTR2 *form_name = &q_u->name;
8185 nt_forms_struct tmpForm;
8187 nt_forms_struct *list=NULL;
8188 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8190 WERROR status = WERR_OK;
8191 NT_PRINTER_INFO_LEVEL *printer = NULL;
8193 DEBUG(5,("spoolss_deleteform\n"));
8196 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8200 /* forms can be deleted on printer of on the print server handle */
8202 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8204 if (!get_printer_snum(p,handle, &snum))
8207 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8208 if (!W_ERROR_IS_OK(status))
8212 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8213 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8214 status = WERR_ACCESS_DENIED;
8218 /* can't delete if builtin */
8220 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8221 status = WERR_INVALID_PARAM;
8225 count = get_ntforms(&list);
8227 if ( !delete_a_form(&list, form_name, &count, &status ))
8231 * ChangeID must always be set if this is a printer
8234 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8235 status = mod_a_printer(printer, 2);
8239 free_a_printer(&printer, 2);
8245 /****************************************************************************
8246 ****************************************************************************/
8248 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8250 POLICY_HND *handle = &q_u->handle;
8251 FORM *form = &q_u->form;
8252 nt_forms_struct tmpForm;
8254 WERROR status = WERR_OK;
8255 NT_PRINTER_INFO_LEVEL *printer = NULL;
8258 nt_forms_struct *list=NULL;
8259 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8261 DEBUG(5,("spoolss_setform\n"));
8264 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8268 /* forms can be modified on printer of on the print server handle */
8270 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8272 if (!get_printer_snum(p,handle, &snum))
8275 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8276 if (!W_ERROR_IS_OK(status))
8280 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8281 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8282 status = WERR_ACCESS_DENIED;
8286 /* can't set if builtin */
8287 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8288 status = WERR_INVALID_PARAM;
8292 count = get_ntforms(&list);
8293 update_a_form(&list, form, count);
8294 write_ntforms(&list, count);
8297 * ChangeID must always be set if this is a printer
8300 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8301 status = mod_a_printer(printer, 2);
8306 free_a_printer(&printer, 2);
8312 /****************************************************************************
8313 enumprintprocessors level 1.
8314 ****************************************************************************/
8316 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8318 PRINTPROCESSOR_1 *info_1=NULL;
8319 WERROR result = WERR_OK;
8321 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8326 init_unistr(&info_1->name, "winprint");
8328 *needed += spoolss_size_printprocessor_info_1(info_1);
8330 if (*needed > offered) {
8331 result = WERR_INSUFFICIENT_BUFFER;
8335 if (!rpcbuf_alloc_size(buffer, *needed)) {
8336 result = WERR_NOMEM;
8340 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8345 if ( !W_ERROR_IS_OK(result) )
8351 /****************************************************************************
8352 ****************************************************************************/
8354 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8356 uint32 level = q_u->level;
8357 RPC_BUFFER *buffer = NULL;
8358 uint32 offered = q_u->offered;
8359 uint32 *needed = &r_u->needed;
8360 uint32 *returned = &r_u->returned;
8362 /* that's an [in out] buffer */
8364 if ( q_u->buffer ) {
8365 rpcbuf_move(q_u->buffer, &r_u->buffer);
8366 buffer = r_u->buffer;
8369 DEBUG(5,("spoolss_enumprintprocessors\n"));
8372 * Enumerate the print processors ...
8374 * Just reply with "winprint", to keep NT happy
8375 * and I can use my nice printer checker.
8383 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8385 return WERR_UNKNOWN_LEVEL;
8389 /****************************************************************************
8390 enumprintprocdatatypes level 1.
8391 ****************************************************************************/
8393 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8395 PRINTPROCDATATYPE_1 *info_1=NULL;
8396 WERROR result = WERR_NOMEM;
8398 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8403 init_unistr(&info_1->name, "RAW");
8405 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8407 if (*needed > offered) {
8408 result = WERR_INSUFFICIENT_BUFFER;
8412 if (!rpcbuf_alloc_size(buffer, *needed)) {
8413 result = WERR_NOMEM;
8417 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8422 if ( !W_ERROR_IS_OK(result) )
8428 /****************************************************************************
8429 ****************************************************************************/
8431 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8433 uint32 level = q_u->level;
8434 RPC_BUFFER *buffer = NULL;
8435 uint32 offered = q_u->offered;
8436 uint32 *needed = &r_u->needed;
8437 uint32 *returned = &r_u->returned;
8439 /* that's an [in out] buffer */
8441 if ( q_u->buffer ) {
8442 rpcbuf_move(q_u->buffer, &r_u->buffer);
8443 buffer = r_u->buffer;
8446 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8453 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8455 return WERR_UNKNOWN_LEVEL;
8459 /****************************************************************************
8460 enumprintmonitors level 1.
8461 ****************************************************************************/
8463 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8465 PRINTMONITOR_1 *info_1;
8466 WERROR result = WERR_OK;
8469 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8474 init_unistr(&(info_1[0].name), "Local Port");
8475 init_unistr(&(info_1[1].name), "Standard TCP/IP Port");
8477 for ( i=0; i<*returned; i++ ) {
8478 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8481 if (*needed > offered) {
8482 result = WERR_INSUFFICIENT_BUFFER;
8486 if (!rpcbuf_alloc_size(buffer, *needed)) {
8487 result = WERR_NOMEM;
8491 for ( i=0; i<*returned; i++ ) {
8492 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8498 if ( !W_ERROR_IS_OK(result) )
8504 /****************************************************************************
8505 enumprintmonitors level 2.
8506 ****************************************************************************/
8508 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8510 PRINTMONITOR_2 *info_2;
8511 WERROR result = WERR_OK;
8514 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8519 init_unistr(&(info_2[0].name), "Local Port");
8520 init_unistr(&(info_2[0].environment), "Windows NT X86");
8521 init_unistr(&(info_2[0].dll_name), "localmon.dll");
8523 init_unistr(&(info_2[1].name), "Standard TCP/IP Port");
8524 init_unistr(&(info_2[1].environment), "Windows NT X86");
8525 init_unistr(&(info_2[1].dll_name), "tcpmon.dll");
8527 for ( i=0; i<*returned; i++ ) {
8528 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8531 if (*needed > offered) {
8532 result = WERR_INSUFFICIENT_BUFFER;
8536 if (!rpcbuf_alloc_size(buffer, *needed)) {
8537 result = WERR_NOMEM;
8541 for ( i=0; i<*returned; i++ ) {
8542 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8548 if ( !W_ERROR_IS_OK(result) )
8554 /****************************************************************************
8555 ****************************************************************************/
8557 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8559 uint32 level = q_u->level;
8560 RPC_BUFFER *buffer = NULL;
8561 uint32 offered = q_u->offered;
8562 uint32 *needed = &r_u->needed;
8563 uint32 *returned = &r_u->returned;
8565 /* that's an [in out] buffer */
8567 if ( q_u->buffer ) {
8568 rpcbuf_move(q_u->buffer, &r_u->buffer);
8569 buffer = r_u->buffer;
8572 DEBUG(5,("spoolss_enumprintmonitors\n"));
8575 * Enumerate the print monitors ...
8577 * Just reply with "Local Port", to keep NT happy
8578 * and I can use my nice printer checker.
8586 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8588 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8590 return WERR_UNKNOWN_LEVEL;
8594 /****************************************************************************
8595 ****************************************************************************/
8597 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8598 NT_PRINTER_INFO_LEVEL *ntprinter,
8599 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8604 JOB_INFO_1 *info_1=NULL;
8605 WERROR result = WERR_OK;
8607 info_1=SMB_MALLOC_P(JOB_INFO_1);
8609 if (info_1 == NULL) {
8613 for (i=0; i<count && found==False; i++) {
8614 if ((*queue)[i].job==(int)jobid)
8620 /* NT treats not found as bad param... yet another bad choice */
8621 return WERR_INVALID_PARAM;
8624 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8626 *needed += spoolss_size_job_info_1(info_1);
8628 if (*needed > offered) {
8629 result = WERR_INSUFFICIENT_BUFFER;
8633 if (!rpcbuf_alloc_size(buffer, *needed)) {
8634 result = WERR_NOMEM;
8638 smb_io_job_info_1("", buffer, info_1, 0);
8646 /****************************************************************************
8647 ****************************************************************************/
8649 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8650 NT_PRINTER_INFO_LEVEL *ntprinter,
8651 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8658 DEVICEMODE *devmode = NULL;
8659 NT_DEVICEMODE *nt_devmode = NULL;
8661 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8664 ZERO_STRUCTP(info_2);
8666 for ( i=0; i<count && found==False; i++ )
8668 if ((*queue)[i].job == (int)jobid)
8673 /* NT treats not found as bad param... yet another bad
8675 result = WERR_INVALID_PARAM;
8680 * if the print job does not have a DEVMODE associated with it,
8681 * just use the one for the printer. A NULL devicemode is not
8682 * a failure condition
8685 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8686 devmode = construct_dev_mode(snum);
8688 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8689 ZERO_STRUCTP( devmode );
8690 convert_nt_devicemode( devmode, nt_devmode );
8694 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8696 *needed += spoolss_size_job_info_2(info_2);
8698 if (*needed > offered) {
8699 result = WERR_INSUFFICIENT_BUFFER;
8703 if (!rpcbuf_alloc_size(buffer, *needed)) {
8704 result = WERR_NOMEM;
8708 smb_io_job_info_2("", buffer, info_2, 0);
8713 /* Cleanup allocated memory */
8715 free_job_info_2(info_2); /* Also frees devmode */
8721 /****************************************************************************
8722 ****************************************************************************/
8724 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8726 POLICY_HND *handle = &q_u->handle;
8727 uint32 jobid = q_u->jobid;
8728 uint32 level = q_u->level;
8729 RPC_BUFFER *buffer = NULL;
8730 uint32 offered = q_u->offered;
8731 uint32 *needed = &r_u->needed;
8732 WERROR wstatus = WERR_OK;
8733 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8736 print_queue_struct *queue = NULL;
8737 print_status_struct prt_status;
8739 /* that's an [in out] buffer */
8741 if ( q_u->buffer ) {
8742 rpcbuf_move(q_u->buffer, &r_u->buffer);
8743 buffer = r_u->buffer;
8746 DEBUG(5,("spoolss_getjob\n"));
8750 if (!get_printer_snum(p, handle, &snum))
8753 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8754 if ( !W_ERROR_IS_OK(wstatus) )
8757 count = print_queue_status(snum, &queue, &prt_status);
8759 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8760 count, prt_status.status, prt_status.message));
8764 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8765 buffer, offered, needed);
8768 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8769 buffer, offered, needed);
8772 wstatus = WERR_UNKNOWN_LEVEL;
8777 free_a_printer( &ntprinter, 2 );
8782 /********************************************************************
8783 spoolss_getprinterdataex
8785 From MSDN documentation of GetPrinterDataEx: pass request
8786 to GetPrinterData if key is "PrinterDriverData".
8787 ********************************************************************/
8789 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8791 POLICY_HND *handle = &q_u->handle;
8792 uint32 in_size = q_u->size;
8793 uint32 *type = &r_u->type;
8794 uint32 *out_size = &r_u->size;
8795 uint8 **data = &r_u->data;
8796 uint32 *needed = &r_u->needed;
8797 fstring keyname, valuename;
8799 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8801 NT_PRINTER_INFO_LEVEL *printer = NULL;
8803 WERROR status = WERR_OK;
8805 DEBUG(4,("_spoolss_getprinterdataex\n"));
8807 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8808 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8810 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8811 keyname, valuename));
8813 /* in case of problem, return some default values */
8817 *out_size = in_size;
8820 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8821 status = WERR_BADFID;
8825 /* Is the handle to a printer or to the server? */
8827 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8828 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8829 status = WERR_INVALID_PARAM;
8833 if ( !get_printer_snum(p,handle, &snum) )
8836 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8837 if ( !W_ERROR_IS_OK(status) )
8840 /* check to see if the keyname is valid */
8841 if ( !strlen(keyname) ) {
8842 status = WERR_INVALID_PARAM;
8846 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8847 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8848 free_a_printer( &printer, 2 );
8849 status = WERR_BADFILE;
8853 /* When given a new keyname, we should just create it */
8855 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8857 if (*needed > *out_size)
8858 status = WERR_MORE_DATA;
8861 if ( !W_ERROR_IS_OK(status) )
8863 DEBUG(5, ("error: allocating %d\n", *out_size));
8865 /* reply this param doesn't exist */
8869 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8870 status = WERR_NOMEM;
8880 free_a_printer( &printer, 2 );
8885 /********************************************************************
8886 * spoolss_setprinterdataex
8887 ********************************************************************/
8889 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8891 POLICY_HND *handle = &q_u->handle;
8892 uint32 type = q_u->type;
8893 uint8 *data = q_u->data;
8894 uint32 real_len = q_u->real_len;
8896 NT_PRINTER_INFO_LEVEL *printer = NULL;
8898 WERROR status = WERR_OK;
8899 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8904 DEBUG(4,("_spoolss_setprinterdataex\n"));
8906 /* From MSDN documentation of SetPrinterDataEx: pass request to
8907 SetPrinterData if key is "PrinterDriverData" */
8910 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8914 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8915 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8916 return WERR_INVALID_PARAM;
8919 if ( !get_printer_snum(p,handle, &snum) )
8923 * Access check : NT returns "access denied" if you make a
8924 * SetPrinterData call without the necessary privildge.
8925 * we were originally returning OK if nothing changed
8926 * which made Win2k issue **a lot** of SetPrinterData
8927 * when connecting to a printer --jerry
8930 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8932 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8933 return WERR_ACCESS_DENIED;
8936 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8937 if (!W_ERROR_IS_OK(status))
8940 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8941 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8943 /* check for OID in valuename */
8945 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8951 /* save the registry data */
8953 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8955 if ( W_ERROR_IS_OK(status) )
8957 /* save the OID if one was specified */
8959 fstrcat( keyname, "\\" );
8960 fstrcat( keyname, SPOOL_OID_KEY );
8963 * I'm not checking the status here on purpose. Don't know
8964 * if this is right, but I'm returning the status from the
8965 * previous set_printer_dataex() call. I have no idea if
8966 * this is right. --jerry
8969 set_printer_dataex( printer, keyname, valuename,
8970 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8973 status = mod_a_printer(printer, 2);
8976 free_a_printer(&printer, 2);
8982 /********************************************************************
8983 * spoolss_deleteprinterdataex
8984 ********************************************************************/
8986 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8988 POLICY_HND *handle = &q_u->handle;
8989 UNISTR2 *value = &q_u->valuename;
8990 UNISTR2 *key = &q_u->keyname;
8992 NT_PRINTER_INFO_LEVEL *printer = NULL;
8994 WERROR status = WERR_OK;
8995 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8996 pstring valuename, keyname;
8998 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9001 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9005 if (!get_printer_snum(p, handle, &snum))
9008 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9009 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9010 return WERR_ACCESS_DENIED;
9013 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9014 if (!W_ERROR_IS_OK(status))
9017 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9018 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9020 status = delete_printer_dataex( printer, keyname, valuename );
9022 if ( W_ERROR_IS_OK(status) )
9023 mod_a_printer( printer, 2 );
9025 free_a_printer(&printer, 2);
9030 /********************************************************************
9031 * spoolss_enumprinterkey
9032 ********************************************************************/
9035 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9038 fstring *keynames = NULL;
9039 uint16 *enumkeys = NULL;
9042 POLICY_HND *handle = &q_u->handle;
9043 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9044 NT_PRINTER_DATA *data;
9045 NT_PRINTER_INFO_LEVEL *printer = NULL;
9047 WERROR status = WERR_BADFILE;
9050 DEBUG(4,("_spoolss_enumprinterkey\n"));
9053 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9057 if ( !get_printer_snum(p,handle, &snum) )
9060 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9061 if (!W_ERROR_IS_OK(status))
9064 /* get the list of subkey names */
9066 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9067 data = printer->info_2->data;
9069 num_keys = get_printer_subkeys( data, key, &keynames );
9071 if ( num_keys == -1 ) {
9072 status = WERR_BADFILE;
9076 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9078 r_u->needed = printerkey_len*2;
9080 if ( q_u->size < r_u->needed ) {
9081 status = WERR_MORE_DATA;
9085 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9086 status = WERR_NOMEM;
9092 if ( q_u->size < r_u->needed )
9093 status = WERR_MORE_DATA;
9096 free_a_printer( &printer, 2 );
9097 SAFE_FREE( keynames );
9102 /********************************************************************
9103 * spoolss_deleteprinterkey
9104 ********************************************************************/
9106 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9108 POLICY_HND *handle = &q_u->handle;
9109 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9111 NT_PRINTER_INFO_LEVEL *printer = NULL;
9115 DEBUG(5,("spoolss_deleteprinterkey\n"));
9118 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9122 /* if keyname == NULL, return error */
9124 if ( !q_u->keyname.buffer )
9125 return WERR_INVALID_PARAM;
9127 if (!get_printer_snum(p, handle, &snum))
9130 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9131 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9132 return WERR_ACCESS_DENIED;
9135 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9136 if (!W_ERROR_IS_OK(status))
9139 /* delete the key and all subneys */
9141 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9143 status = delete_all_printer_data( printer->info_2, key );
9145 if ( W_ERROR_IS_OK(status) )
9146 status = mod_a_printer(printer, 2);
9148 free_a_printer( &printer, 2 );
9154 /********************************************************************
9155 * spoolss_enumprinterdataex
9156 ********************************************************************/
9158 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9160 POLICY_HND *handle = &q_u->handle;
9161 uint32 in_size = q_u->size;
9164 NT_PRINTER_INFO_LEVEL *printer = NULL;
9165 PRINTER_ENUM_VALUES *enum_values = NULL;
9166 NT_PRINTER_DATA *p_data;
9168 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9173 REGISTRY_VALUE *val;
9178 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9181 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9186 * first check for a keyname of NULL or "". Win2k seems to send
9187 * this a lot and we should send back WERR_INVALID_PARAM
9188 * no need to spend time looking up the printer in this case.
9192 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9193 if ( !strlen(key) ) {
9194 result = WERR_INVALID_PARAM;
9198 /* get the printer off of disk */
9200 if (!get_printer_snum(p,handle, &snum))
9203 ZERO_STRUCT(printer);
9204 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9205 if (!W_ERROR_IS_OK(result))
9208 /* now look for a match on the key name */
9210 p_data = printer->info_2->data;
9212 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9213 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9215 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9216 result = WERR_INVALID_PARAM;
9223 /* allocate the memory for the array of pointers -- if necessary */
9225 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9228 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9230 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9231 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9232 result = WERR_NOMEM;
9236 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9240 * loop through all params and build the array to pass
9241 * back to the client
9244 for ( i=0; i<num_entries; i++ )
9246 /* lookup the registry value */
9248 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9249 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9253 value_name = regval_name( val );
9254 init_unistr( &enum_values[i].valuename, value_name );
9255 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9256 enum_values[i].type = regval_type( val );
9258 data_len = regval_size( val );
9260 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9262 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9264 result = WERR_NOMEM;
9268 enum_values[i].data_len = data_len;
9270 /* keep track of the size of the array in bytes */
9272 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9275 /* housekeeping information in the reply */
9277 r_u->needed = needed;
9278 r_u->returned = num_entries;
9280 if (needed > in_size) {
9281 result = WERR_MORE_DATA;
9285 /* copy data into the reply */
9287 r_u->ctr.size = r_u->needed;
9288 r_u->ctr.size_of_array = r_u->returned;
9289 r_u->ctr.values = enum_values;
9295 free_a_printer(&printer, 2);
9300 /****************************************************************************
9301 ****************************************************************************/
9303 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9305 init_unistr(&info->name, name);
9308 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9309 UNISTR2 *environment,
9316 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9317 WERROR result = WERR_OK;
9319 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9321 if (!get_short_archi(long_archi))
9322 return WERR_INVALID_ENVIRONMENT;
9324 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9327 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9329 fill_printprocessordirectory_1(info, path);
9331 *needed += spoolss_size_printprocessordirectory_info_1(info);
9333 if (*needed > offered) {
9334 result = WERR_INSUFFICIENT_BUFFER;
9338 if (!rpcbuf_alloc_size(buffer, *needed)) {
9339 result = WERR_INSUFFICIENT_BUFFER;
9343 smb_io_printprocessordirectory_1("", buffer, info, 0);
9351 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9353 uint32 level = q_u->level;
9354 RPC_BUFFER *buffer = NULL;
9355 uint32 offered = q_u->offered;
9356 uint32 *needed = &r_u->needed;
9359 /* that's an [in out] buffer */
9361 if ( q_u->buffer ) {
9362 rpcbuf_move(q_u->buffer, &r_u->buffer);
9363 buffer = r_u->buffer;
9366 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9372 result = getprintprocessordirectory_level_1
9373 (&q_u->name, &q_u->environment, buffer, offered, needed);
9376 result = WERR_UNKNOWN_LEVEL;
9382 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)