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) {
177 cli_shutdown(notify_cli_pipe->cli);
178 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
179 message_deregister(MSG_PRINTER_NOTIFY2);
181 /* Tell the connections db we're no longer interested in
182 * printer notify messages. */
184 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
190 /****************************************************************************
191 Functions to free a printer entry datastruct.
192 ****************************************************************************/
194 static void free_printer_entry(void *ptr)
196 Printer_entry *Printer = (Printer_entry *)ptr;
198 if (Printer->notify.client_connected==True) {
201 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
203 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
204 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
205 snum = print_queue_snum(Printer->sharename);
207 srv_spoolss_replycloseprinter(snum,
208 &Printer->notify.client_hnd);
212 Printer->notify.flags=0;
213 Printer->notify.options=0;
214 Printer->notify.localmachine[0]='\0';
215 Printer->notify.printerlocal=0;
216 free_spool_notify_option(&Printer->notify.option);
217 Printer->notify.option=NULL;
218 Printer->notify.client_connected=False;
220 free_nt_devicemode( &Printer->nt_devmode );
221 free_a_printer( &Printer->printer_info, 2 );
223 talloc_destroy( Printer->ctx );
225 /* Remove from the internal list. */
226 DLIST_REMOVE(printers_list, Printer);
231 /****************************************************************************
232 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
233 ****************************************************************************/
235 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
237 SPOOL_NOTIFY_OPTION *new_sp = NULL;
242 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
249 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
251 if (!new_sp->ctr.type) {
260 /****************************************************************************
261 find printer index by handle
262 ****************************************************************************/
264 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
266 Printer_entry *find_printer = NULL;
268 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
269 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
276 /****************************************************************************
277 Close printer index by handle.
278 ****************************************************************************/
280 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
282 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
285 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
289 close_policy_hnd(p, hnd);
294 /****************************************************************************
295 Delete a printer given a handle.
296 ****************************************************************************/
297 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
299 char *cmd = lp_deleteprinter_cmd();
302 SE_PRIV se_printop = SE_PRINT_OPERATOR;
303 BOOL is_print_op = False;
305 /* can't fail if we don't try */
310 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
313 is_print_op = user_has_privileges( token, &se_printop );
315 DEBUG(10,("Running [%s]\n", command));
317 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
322 if ( (ret = smbrun(command, NULL)) == 0 ) {
323 /* Tell everyone we updated smb.conf. */
324 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
330 /********** END SePrintOperatorPrivlege BLOCK **********/
332 DEBUGADD(10,("returned [%d]\n", ret));
335 return WERR_BADFID; /* What to return here? */
337 /* go ahead and re-read the services immediately */
338 reload_services( False );
340 if ( lp_servicenumber( sharename ) < 0 )
341 return WERR_ACCESS_DENIED;
346 /****************************************************************************
347 Delete a printer given a handle.
348 ****************************************************************************/
350 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
355 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
360 * It turns out that Windows allows delete printer on a handle
361 * opened by an admin user, then used on a pipe handle created
362 * by an anonymous user..... but they're working on security.... riiight !
366 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
367 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368 return WERR_ACCESS_DENIED;
371 /* this does not need a become root since the access check has been
372 done on the handle already */
374 if (del_a_printer( Printer->sharename ) != 0) {
375 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
379 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
382 /****************************************************************************
383 Return the snum of a printer corresponding to an handle.
384 ****************************************************************************/
386 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
388 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
391 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
395 switch (Printer->printer_type) {
396 case PRINTER_HANDLE_IS_PRINTER:
397 DEBUG(4,("short name:%s\n", Printer->sharename));
398 *number = print_queue_snum(Printer->sharename);
399 return (*number != -1);
400 case PRINTER_HANDLE_IS_PRINTSERVER:
407 /****************************************************************************
408 Set printer handle type.
409 Check if it's \\server or \\server\printer
410 ****************************************************************************/
412 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
414 DEBUG(3,("Setting printer type=%s\n", handlename));
416 if ( strlen(handlename) < 3 ) {
417 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
421 /* it's a print server */
422 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
423 DEBUGADD(4,("Printer is a print server\n"));
424 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
428 DEBUGADD(4,("Printer is a printer\n"));
429 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
435 /****************************************************************************
436 Set printer handle name.
437 ****************************************************************************/
439 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
442 int n_services=lp_numservices();
443 char *aprinter, *printername;
444 const char *servername;
447 NT_PRINTER_INFO_LEVEL *printer;
450 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
452 aprinter = handlename;
453 if ( *handlename == '\\' ) {
454 servername = handlename + 2;
455 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
464 /* save the servername to fill in replies on this handle */
466 if ( !is_myname_or_ipaddr( servername ) )
469 fstrcpy( Printer->servername, servername );
471 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
474 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
477 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
479 /* Search all sharenames first as this is easier than pulling
480 the printer_info_2 off of disk */
482 snum = find_service(aprinter);
484 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
486 fstrcpy( sname, aprinter );
489 /* do another loop to look for printernames */
491 for (snum=0; !found && snum<n_services; snum++) {
493 /* no point in checking if this is not a printer or
494 we aren't allowing printername != sharename */
496 if ( !(lp_snum_ok(snum)
498 && !lp_force_printername(snum)) )
503 fstrcpy(sname, lp_servicename(snum));
506 result = get_a_printer( NULL, &printer, 2, sname );
507 if ( !W_ERROR_IS_OK(result) ) {
508 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
509 sname, dos_errstr(result)));
513 /* printername is always returned as \\server\printername */
514 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
515 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
516 printer->info_2->printername));
517 free_a_printer( &printer, 2);
523 if ( strequal(printername, aprinter) ) {
527 DEBUGADD(10, ("printername: %s\n", printername));
529 free_a_printer( &printer, 2);
533 DEBUGADD(4,("Printer not found\n"));
537 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
539 fstrcpy(Printer->sharename, sname);
544 /****************************************************************************
545 Find first available printer slot. creates a printer handle for you.
546 ****************************************************************************/
548 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
550 Printer_entry *new_printer;
552 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
554 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
557 ZERO_STRUCTP(new_printer);
559 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
560 SAFE_FREE(new_printer);
564 /* Add to the internal list. */
565 DLIST_ADD(printers_list, new_printer);
567 new_printer->notify.option=NULL;
569 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
570 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
571 close_printer_handle(p, hnd);
575 if (!set_printer_hnd_printertype(new_printer, name)) {
576 close_printer_handle(p, hnd);
580 if (!set_printer_hnd_name(new_printer, name)) {
581 close_printer_handle(p, hnd);
585 new_printer->access_granted = access_granted;
587 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
592 /***************************************************************************
593 check to see if the client motify handle is monitoring the notification
594 given by (notify_type, notify_field).
595 **************************************************************************/
597 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
603 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
606 SPOOL_NOTIFY_OPTION *option = p->notify.option;
610 * Flags should always be zero when the change notify
611 * is registered by the client's spooler. A user Win32 app
612 * might use the flags though instead of the NOTIFY_OPTION_INFO
621 return is_monitoring_event_flags(
622 p->notify.flags, notify_type, notify_field);
624 for (i = 0; i < option->count; i++) {
626 /* Check match for notify_type */
628 if (option->ctr.type[i].type != notify_type)
631 /* Check match for field */
633 for (j = 0; j < option->ctr.type[i].count; j++) {
634 if (option->ctr.type[i].fields[j] == notify_field) {
640 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
641 p->servername, p->sharename, notify_type, notify_field));
646 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
648 static void notify_one_value(struct spoolss_notify_msg *msg,
649 SPOOL_NOTIFY_INFO_DATA *data,
652 data->notify_data.value[0] = msg->notify.value[0];
653 data->notify_data.value[1] = 0;
656 static void notify_string(struct spoolss_notify_msg *msg,
657 SPOOL_NOTIFY_INFO_DATA *data,
662 /* The length of the message includes the trailing \0 */
664 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
666 data->notify_data.data.length = msg->len * 2;
667 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
669 if (!data->notify_data.data.string) {
670 data->notify_data.data.length = 0;
674 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
677 static void notify_system_time(struct spoolss_notify_msg *msg,
678 SPOOL_NOTIFY_INFO_DATA *data,
684 if (msg->len != sizeof(time_t)) {
685 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
690 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
691 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
695 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
696 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
700 if (!spoolss_io_system_time("", &ps, 0, &systime))
703 data->notify_data.data.length = prs_offset(&ps);
704 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
706 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
711 struct notify2_message_table {
713 void (*fn)(struct spoolss_notify_msg *msg,
714 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
717 static struct notify2_message_table printer_notify_table[] = {
718 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
719 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
720 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
721 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
722 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
723 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
724 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
725 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
726 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
727 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
728 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
729 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
730 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
731 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
732 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
733 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
734 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
735 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
736 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
739 static struct notify2_message_table job_notify_table[] = {
740 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
741 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
742 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
743 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
744 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
745 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
746 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
747 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
748 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
749 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
750 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
751 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
752 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
753 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
754 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
755 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
756 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
757 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
758 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
759 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
760 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
761 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
762 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
763 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
767 /***********************************************************************
768 Allocate talloc context for container object
769 **********************************************************************/
771 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
776 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
781 /***********************************************************************
782 release all allocated memory and zero out structure
783 **********************************************************************/
785 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
791 talloc_destroy(ctr->ctx);
798 /***********************************************************************
799 **********************************************************************/
801 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
809 /***********************************************************************
810 **********************************************************************/
812 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
814 if ( !ctr || !ctr->msg_groups )
817 if ( idx >= ctr->num_groups )
820 return &ctr->msg_groups[idx];
824 /***********************************************************************
825 How many groups of change messages do we have ?
826 **********************************************************************/
828 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
833 return ctr->num_groups;
836 /***********************************************************************
837 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
838 **********************************************************************/
840 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
842 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
843 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
844 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
850 /* loop over all groups looking for a matching printer name */
852 for ( i=0; i<ctr->num_groups; i++ ) {
853 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
857 /* add a new group? */
859 if ( i == ctr->num_groups ) {
862 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
863 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
866 ctr->msg_groups = groups;
868 /* clear the new entry and set the printer name */
870 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
871 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
874 /* add the change messages; 'i' is the correct index now regardless */
876 msg_grp = &ctr->msg_groups[i];
880 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
881 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
884 msg_grp->msgs = msg_list;
886 new_slot = msg_grp->num_msgs-1;
887 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
889 /* need to allocate own copy of data */
892 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
894 return ctr->num_groups;
897 /***********************************************************************
898 Send a change notication message on all handles which have a call
900 **********************************************************************/
902 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
905 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
906 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
907 SPOOLSS_NOTIFY_MSG *messages;
908 int sending_msg_count;
911 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
915 messages = msg_group->msgs;
918 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
922 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
924 /* loop over all printers */
926 for (p = printers_list; p; p = p->next) {
927 SPOOL_NOTIFY_INFO_DATA *data;
932 /* Is there notification on this handle? */
934 if ( !p->notify.client_connected )
937 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
939 /* For this printer? Print servers always receive
942 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
943 ( !strequal(msg_group->printername, p->sharename) ) )
946 DEBUG(10,("Our printer\n"));
948 /* allocate the max entries possible */
950 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
953 /* build the array of change notifications */
955 sending_msg_count = 0;
957 for ( i=0; i<msg_group->num_msgs; i++ ) {
958 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
960 /* Are we monitoring this event? */
962 if (!is_monitoring_event(p, msg->type, msg->field))
968 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
969 msg->type, msg->field, p->sharename));
972 * if the is a printer notification handle and not a job notification
973 * type, then set the id to 0. Other wise just use what was specified
976 * When registering change notification on a print server handle
977 * we always need to send back the id (snum) matching the printer
978 * for which the change took place. For change notify registered
979 * on a printer handle, this does not matter and the id should be 0.
984 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
990 /* Convert unix jobid to smb jobid */
992 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
993 id = sysjob_to_jobid(msg->id);
996 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1001 construct_info_data( &data[data_len], msg->type, msg->field, id );
1004 case PRINTER_NOTIFY_TYPE:
1005 if ( printer_notify_table[msg->field].fn )
1006 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1009 case JOB_NOTIFY_TYPE:
1010 if ( job_notify_table[msg->field].fn )
1011 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1015 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1022 if ( sending_msg_count ) {
1023 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1024 data_len, data, p->notify.change, 0 );
1029 DEBUG(8,("send_notify2_changes: Exit...\n"));
1033 /***********************************************************************
1034 **********************************************************************/
1036 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1039 uint32 tv_sec, tv_usec;
1042 /* Unpack message */
1044 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1047 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1049 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1052 tdb_unpack((char *)buf + offset, len - offset, "dd",
1053 &msg->notify.value[0], &msg->notify.value[1]);
1055 tdb_unpack((char *)buf + offset, len - offset, "B",
1056 &msg->len, &msg->notify.data);
1058 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1059 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1061 tv->tv_sec = tv_sec;
1062 tv->tv_usec = tv_usec;
1065 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1066 msg->notify.value[1]));
1068 dump_data(3, msg->notify.data, msg->len);
1073 /********************************************************************
1074 Receive a notify2 message list
1075 ********************************************************************/
1077 static void receive_notify2_message_list(int msg_type, struct process_id src,
1078 void *msg, size_t len)
1080 size_t msg_count, i;
1081 char *buf = (char *)msg;
1084 SPOOLSS_NOTIFY_MSG notify;
1085 SPOOLSS_NOTIFY_MSG_CTR messages;
1089 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1093 msg_count = IVAL(buf, 0);
1096 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1098 if (msg_count == 0) {
1099 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1103 /* initialize the container */
1105 ZERO_STRUCT( messages );
1106 notify_msg_ctr_init( &messages );
1109 * build message groups for each printer identified
1110 * in a change_notify msg. Remember that a PCN message
1111 * includes the handle returned for the srv_spoolss_replyopenprinter()
1112 * call. Therefore messages are grouped according to printer handle.
1115 for ( i=0; i<msg_count; i++ ) {
1116 struct timeval msg_tv;
1118 if (msg_ptr + 4 - buf > len) {
1119 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1123 msg_len = IVAL(msg_ptr,0);
1126 if (msg_ptr + msg_len - buf > len) {
1127 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1131 /* unpack messages */
1133 ZERO_STRUCT( notify );
1134 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1137 /* add to correct list in container */
1139 notify_msg_ctr_addmsg( &messages, ¬ify );
1141 /* free memory that might have been allocated by notify2_unpack_msg() */
1143 if ( notify.len != 0 )
1144 SAFE_FREE( notify.notify.data );
1147 /* process each group of messages */
1149 num_groups = notify_msg_ctr_numgroups( &messages );
1150 for ( i=0; i<num_groups; i++ )
1151 send_notify2_changes( &messages, i );
1156 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1158 notify_msg_ctr_destroy( &messages );
1163 /********************************************************************
1164 Send a message to ourself about new driver being installed
1165 so we can upgrade the information for each printer bound to this
1167 ********************************************************************/
1169 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1171 int len = strlen(drivername);
1176 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1179 message_send_pid(pid_to_procid(sys_getpid()),
1180 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1185 /**********************************************************************
1186 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1187 over all printers, upgrading ones as necessary
1188 **********************************************************************/
1190 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1194 int n_services = lp_numservices();
1196 len = MIN(len,sizeof(drivername)-1);
1197 strncpy(drivername, buf, len);
1199 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1201 /* Iterate the printer list */
1203 for (snum=0; snum<n_services; snum++)
1205 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1208 NT_PRINTER_INFO_LEVEL *printer = NULL;
1210 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1211 if (!W_ERROR_IS_OK(result))
1214 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1216 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1218 /* all we care about currently is the change_id */
1220 result = mod_a_printer(printer, 2);
1221 if (!W_ERROR_IS_OK(result)) {
1222 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1223 dos_errstr(result)));
1227 free_a_printer(&printer, 2);
1234 /********************************************************************
1235 Update the cache for all printq's with a registered client
1237 ********************************************************************/
1239 void update_monitored_printq_cache( void )
1241 Printer_entry *printer = printers_list;
1244 /* loop through all printers and update the cache where
1245 client_connected == True */
1248 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1249 && printer->notify.client_connected )
1251 snum = print_queue_snum(printer->sharename);
1252 print_queue_status( snum, NULL, NULL );
1255 printer = printer->next;
1260 /********************************************************************
1261 Send a message to ourself about new driver being installed
1262 so we can upgrade the information for each printer bound to this
1264 ********************************************************************/
1266 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1268 int len = strlen(drivername);
1273 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1276 message_send_pid(pid_to_procid(sys_getpid()),
1277 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1282 /**********************************************************************
1283 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1284 over all printers, resetting printer data as neessary
1285 **********************************************************************/
1287 void reset_all_printerdata(int msg_type, struct process_id src,
1288 void *buf, size_t len)
1292 int n_services = lp_numservices();
1294 len = MIN( len, sizeof(drivername)-1 );
1295 strncpy( drivername, buf, len );
1297 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1299 /* Iterate the printer list */
1301 for ( snum=0; snum<n_services; snum++ )
1303 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1306 NT_PRINTER_INFO_LEVEL *printer = NULL;
1308 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1309 if ( !W_ERROR_IS_OK(result) )
1313 * if the printer is bound to the driver,
1314 * then reset to the new driver initdata
1317 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1319 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1321 if ( !set_driver_init(printer, 2) ) {
1322 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1323 printer->info_2->printername, printer->info_2->drivername));
1326 result = mod_a_printer( printer, 2 );
1327 if ( !W_ERROR_IS_OK(result) ) {
1328 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1329 get_dos_error_msg(result)));
1333 free_a_printer( &printer, 2 );
1342 /********************************************************************
1343 Copy routines used by convert_to_openprinterex()
1344 *******************************************************************/
1346 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1354 DEBUG (8,("dup_devmode\n"));
1356 /* bulk copy first */
1358 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1362 /* dup the pointer members separately */
1364 len = unistrlen(devmode->devicename.buffer);
1366 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1367 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1372 len = unistrlen(devmode->formname.buffer);
1374 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1375 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1379 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1384 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1386 if (!new_ctr || !ctr)
1389 DEBUG(8,("copy_devmode_ctr\n"));
1391 new_ctr->size = ctr->size;
1392 new_ctr->devmode_ptr = ctr->devmode_ptr;
1394 if(ctr->devmode_ptr)
1395 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1398 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1400 if (!new_def || !def)
1403 DEBUG(8,("copy_printer_defaults\n"));
1405 new_def->datatype_ptr = def->datatype_ptr;
1407 if (def->datatype_ptr)
1408 copy_unistr2(&new_def->datatype, &def->datatype);
1410 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1412 new_def->access_required = def->access_required;
1415 /********************************************************************
1416 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1417 * SPOOL_Q_OPEN_PRINTER_EX structure
1418 ********************************************************************/
1420 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1422 if (!q_u_ex || !q_u)
1425 DEBUG(8,("convert_to_openprinterex\n"));
1427 if ( q_u->printername ) {
1428 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1429 if (q_u_ex->printername == NULL)
1431 copy_unistr2(q_u_ex->printername, q_u->printername);
1434 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1439 /********************************************************************
1440 * spoolss_open_printer
1442 * called from the spoolss dispatcher
1443 ********************************************************************/
1445 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1447 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1448 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1453 ZERO_STRUCT(q_u_ex);
1454 ZERO_STRUCT(r_u_ex);
1456 /* convert the OpenPrinter() call to OpenPrinterEx() */
1458 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1459 if (!W_ERROR_IS_OK(r_u_ex.status))
1460 return r_u_ex.status;
1462 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1464 /* convert back to OpenPrinter() */
1466 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1471 /********************************************************************
1472 * spoolss_open_printer
1474 * If the openprinterex rpc call contains a devmode,
1475 * it's a per-user one. This per-user devmode is derivated
1476 * from the global devmode. Openprinterex() contains a per-user
1477 * devmode for when you do EMF printing and spooling.
1478 * In the EMF case, the NT workstation is only doing half the job
1479 * of rendering the page. The other half is done by running the printer
1480 * driver on the server.
1481 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1482 * The EMF file only contains what is to be printed on the page.
1483 * So in order for the server to know how to print, the NT client sends
1484 * a devicemode attached to the openprinterex call.
1485 * But this devicemode is short lived, it's only valid for the current print job.
1487 * If Samba would have supported EMF spooling, this devicemode would
1488 * have been attached to the handle, to sent it to the driver to correctly
1489 * rasterize the EMF file.
1491 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1492 * we just act as a pass-thru between windows and the printer.
1494 * In order to know that Samba supports only RAW spooling, NT has to call
1495 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1496 * and until NT sends a RAW job, we refuse it.
1498 * But to call getprinter() or startdoc(), you first need a valid handle,
1499 * and to get an handle you have to call openprintex(). Hence why you have
1500 * a devicemode in the openprinterex() call.
1503 * Differences between NT4 and NT 2000.
1506 * On NT4, you only have a global devicemode. This global devicemode can be changed
1507 * by the administrator (or by a user with enough privs). Everytime a user
1508 * wants to print, the devicemode is resetted to the default. In Word, everytime
1509 * you print, the printer's characteristics are always reset to the global devicemode.
1513 * In W2K, there is the notion of per-user devicemode. The first time you use
1514 * a printer, a per-user devicemode is build from the global devicemode.
1515 * If you change your per-user devicemode, it is saved in the registry, under the
1516 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1517 * printer preferences available.
1519 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1520 * on the General Tab of the printer properties windows.
1522 * To change the global devicemode: it's the "Printing Defaults..." button
1523 * on the Advanced Tab of the printer properties window.
1526 ********************************************************************/
1528 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1530 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1531 POLICY_HND *handle = &r_u->handle;
1535 struct current_user user;
1536 Printer_entry *Printer=NULL;
1538 if ( !q_u->printername )
1539 return WERR_INVALID_PRINTER_NAME;
1541 /* some sanity check because you can open a printer or a print server */
1542 /* aka: \\server\printer or \\server */
1544 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1546 DEBUGADD(3,("checking name: %s\n",name));
1548 if (!open_printer_hnd(p, handle, name, 0))
1549 return WERR_INVALID_PRINTER_NAME;
1551 Printer=find_printer_index_by_hnd(p, handle);
1553 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1554 "handle we created for printer %s\n", name ));
1555 close_printer_handle(p,handle);
1556 return WERR_INVALID_PRINTER_NAME;
1559 get_current_user(&user, p);
1562 * First case: the user is opening the print server:
1564 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1565 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1567 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1568 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1569 * or if the user is listed in the smb.conf printer admin parameter.
1571 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1572 * client view printer folder, but does not show the MSAPW.
1574 * Note: this test needs code to check access rights here too. Jeremy
1575 * could you look at this?
1577 * Second case: the user is opening a printer:
1578 * NT doesn't let us connect to a printer if the connecting user
1579 * doesn't have print permission.
1582 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1584 /* Printserver handles use global struct... */
1588 /* Map standard access rights to object specific access rights */
1590 se_map_standard(&printer_default->access_required,
1591 &printserver_std_mapping);
1593 /* Deny any object specific bits that don't apply to print
1594 servers (i.e printer and job specific bits) */
1596 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1598 if (printer_default->access_required &
1599 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1600 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1601 close_printer_handle(p, handle);
1602 return WERR_ACCESS_DENIED;
1605 /* Allow admin access */
1607 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1609 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1611 if (!lp_ms_add_printer_wizard()) {
1612 close_printer_handle(p, handle);
1613 return WERR_ACCESS_DENIED;
1616 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1617 and not a printer admin, then fail */
1620 && !user_has_privileges( user.nt_user_token, &se_printop )
1621 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1623 close_printer_handle(p, handle);
1624 return WERR_ACCESS_DENIED;
1627 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1631 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1634 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1635 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1637 /* We fall through to return WERR_OK */
1642 /* NT doesn't let us connect to a printer if the connecting user
1643 doesn't have print permission. */
1645 if (!get_printer_snum(p, handle, &snum)) {
1646 close_printer_handle(p, handle);
1650 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1652 /* map an empty access mask to the minimum access mask */
1653 if (printer_default->access_required == 0x0)
1654 printer_default->access_required = PRINTER_ACCESS_USE;
1657 * If we are not serving the printer driver for this printer,
1658 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1659 * will keep NT clients happy --jerry
1662 if (lp_use_client_driver(snum)
1663 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1665 printer_default->access_required = PRINTER_ACCESS_USE;
1668 /* check smb.conf parameters and the the sec_desc */
1670 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1671 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1672 return WERR_ACCESS_DENIED;
1675 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1676 DEBUG(3, ("access DENIED for printer open\n"));
1677 close_printer_handle(p, handle);
1678 return WERR_ACCESS_DENIED;
1681 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1682 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1683 close_printer_handle(p, handle);
1684 return WERR_ACCESS_DENIED;
1687 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1688 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1690 printer_default->access_required = PRINTER_ACCESS_USE;
1692 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1693 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1697 Printer->access_granted = printer_default->access_required;
1700 * If the client sent a devmode in the OpenPrinter() call, then
1701 * save it here in case we get a job submission on this handle
1704 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1705 && q_u->printer_default.devmode_cont.devmode_ptr )
1707 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1708 &Printer->nt_devmode );
1711 #if 0 /* JERRY -- I'm doubtful this is really effective */
1712 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1713 optimization in Windows 2000 clients --jerry */
1715 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1716 && (RA_WIN2K == get_remote_arch()) )
1718 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1719 sys_usleep( 500000 );
1726 /****************************************************************************
1727 ****************************************************************************/
1729 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1730 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1736 /* allocate memory if needed. Messy because
1737 convert_printer_info is used to update an existing
1738 printer or build a new one */
1740 if ( !printer->info_2 ) {
1741 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1742 if ( !printer->info_2 ) {
1743 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1748 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1749 printer->info_2->setuptime = time(NULL);
1757 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1758 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1764 printer->info_3=NULL;
1765 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1769 printer->info_6=NULL;
1770 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1780 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1781 NT_DEVICEMODE **pp_nt_devmode)
1783 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1786 * Ensure nt_devmode is a valid pointer
1787 * as we will be overwriting it.
1790 if (nt_devmode == NULL) {
1791 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1792 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1796 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1797 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1799 nt_devmode->specversion=devmode->specversion;
1800 nt_devmode->driverversion=devmode->driverversion;
1801 nt_devmode->size=devmode->size;
1802 nt_devmode->fields=devmode->fields;
1803 nt_devmode->orientation=devmode->orientation;
1804 nt_devmode->papersize=devmode->papersize;
1805 nt_devmode->paperlength=devmode->paperlength;
1806 nt_devmode->paperwidth=devmode->paperwidth;
1807 nt_devmode->scale=devmode->scale;
1808 nt_devmode->copies=devmode->copies;
1809 nt_devmode->defaultsource=devmode->defaultsource;
1810 nt_devmode->printquality=devmode->printquality;
1811 nt_devmode->color=devmode->color;
1812 nt_devmode->duplex=devmode->duplex;
1813 nt_devmode->yresolution=devmode->yresolution;
1814 nt_devmode->ttoption=devmode->ttoption;
1815 nt_devmode->collate=devmode->collate;
1817 nt_devmode->logpixels=devmode->logpixels;
1818 nt_devmode->bitsperpel=devmode->bitsperpel;
1819 nt_devmode->pelswidth=devmode->pelswidth;
1820 nt_devmode->pelsheight=devmode->pelsheight;
1821 nt_devmode->displayflags=devmode->displayflags;
1822 nt_devmode->displayfrequency=devmode->displayfrequency;
1823 nt_devmode->icmmethod=devmode->icmmethod;
1824 nt_devmode->icmintent=devmode->icmintent;
1825 nt_devmode->mediatype=devmode->mediatype;
1826 nt_devmode->dithertype=devmode->dithertype;
1827 nt_devmode->reserved1=devmode->reserved1;
1828 nt_devmode->reserved2=devmode->reserved2;
1829 nt_devmode->panningwidth=devmode->panningwidth;
1830 nt_devmode->panningheight=devmode->panningheight;
1833 * Only change private and driverextra if the incoming devmode
1834 * has a new one. JRA.
1837 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1838 SAFE_FREE(nt_devmode->nt_dev_private);
1839 nt_devmode->driverextra=devmode->driverextra;
1840 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1842 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1845 *pp_nt_devmode = nt_devmode;
1850 /********************************************************************
1851 * _spoolss_enddocprinter_internal.
1852 ********************************************************************/
1854 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1856 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1860 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1864 if (!get_printer_snum(p, handle, &snum))
1867 Printer->document_started=False;
1868 print_job_end(snum, Printer->jobid,True);
1869 /* error codes unhandled so far ... */
1874 /********************************************************************
1875 * api_spoolss_closeprinter
1876 ********************************************************************/
1878 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1880 POLICY_HND *handle = &q_u->handle;
1882 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1884 if (Printer && Printer->document_started)
1885 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1887 if (!close_printer_handle(p, handle))
1890 /* clear the returned printer handle. Observed behavior
1891 from Win2k server. Don't think this really matters.
1892 Previous code just copied the value of the closed
1895 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1900 /********************************************************************
1901 * api_spoolss_deleteprinter
1903 ********************************************************************/
1905 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1907 POLICY_HND *handle = &q_u->handle;
1908 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1911 if (Printer && Printer->document_started)
1912 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1914 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1916 result = delete_printer_handle(p, handle);
1918 update_c_setprinter(False);
1923 /*******************************************************************
1924 * static function to lookup the version id corresponding to an
1925 * long architecture string
1926 ******************************************************************/
1928 static int get_version_id (char * arch)
1931 struct table_node archi_table[]= {
1933 {"Windows 4.0", "WIN40", 0 },
1934 {"Windows NT x86", "W32X86", 2 },
1935 {"Windows NT R4000", "W32MIPS", 2 },
1936 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1937 {"Windows NT PowerPC", "W32PPC", 2 },
1938 {"Windows IA64", "IA64", 3 },
1939 {"Windows x64", "x64", 3 },
1943 for (i=0; archi_table[i].long_archi != NULL; i++)
1945 if (strcmp(arch, archi_table[i].long_archi) == 0)
1946 return (archi_table[i].version);
1952 /********************************************************************
1953 * _spoolss_deleteprinterdriver
1954 ********************************************************************/
1956 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1960 NT_PRINTER_DRIVER_INFO_LEVEL info;
1961 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1963 struct current_user user;
1965 WERROR status_win2k = WERR_ACCESS_DENIED;
1967 get_current_user(&user, p);
1969 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1970 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1972 /* check that we have a valid driver name first */
1974 if ((version=get_version_id(arch)) == -1)
1975 return WERR_INVALID_ENVIRONMENT;
1978 ZERO_STRUCT(info_win2k);
1980 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1982 /* try for Win2k driver if "Windows NT x86" */
1984 if ( version == 2 ) {
1986 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1987 status = WERR_UNKNOWN_PRINTER_DRIVER;
1991 /* otherwise it was a failure */
1993 status = WERR_UNKNOWN_PRINTER_DRIVER;
1999 if (printer_driver_in_use(info.info_3)) {
2000 status = WERR_PRINTER_DRIVER_IN_USE;
2006 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2008 /* if we get to here, we now have 2 driver info structures to remove */
2009 /* remove the Win2k driver first*/
2011 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2012 free_a_printer_driver( info_win2k, 3 );
2014 /* this should not have failed---if it did, report to client */
2015 if ( !W_ERROR_IS_OK(status_win2k) )
2017 status = status_win2k;
2023 status = delete_printer_driver(info.info_3, &user, version, False);
2025 /* if at least one of the deletes succeeded return OK */
2027 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2031 free_a_printer_driver( info, 3 );
2036 /********************************************************************
2037 * spoolss_deleteprinterdriverex
2038 ********************************************************************/
2040 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2044 NT_PRINTER_DRIVER_INFO_LEVEL info;
2045 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2047 uint32 flags = q_u->delete_flags;
2049 struct current_user user;
2051 WERROR status_win2k = WERR_ACCESS_DENIED;
2053 get_current_user(&user, p);
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 cli_state *the_cli, struct rpc_pipe_client **pp_pipe,
2498 struct in_addr *client_ip, const char *remote_machine)
2501 ZERO_STRUCTP(the_cli);
2503 if(cli_initialise(the_cli) == NULL) {
2504 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2508 if ( is_zero_ip(*client_ip) ) {
2509 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2510 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2511 cli_shutdown(the_cli);
2515 if (ismyip(the_cli->dest_ip)) {
2516 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2517 cli_shutdown(the_cli);
2522 the_cli->dest_ip.s_addr = client_ip->s_addr;
2523 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2524 inet_ntoa(*client_ip) ));
2527 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2528 DEBUG(0,("spoolss_connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2529 cli_shutdown(the_cli);
2533 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2534 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2536 cli_shutdown(the_cli);
2540 the_cli->protocol = PROTOCOL_NT1;
2541 cli_setup_signing_state(the_cli, lp_client_signing());
2543 if (!cli_negprot(the_cli)) {
2544 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2545 cli_shutdown(the_cli);
2549 if (the_cli->protocol != PROTOCOL_NT1) {
2550 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2551 cli_shutdown(the_cli);
2556 * Do an anonymous session setup.
2559 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2560 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2561 cli_shutdown(the_cli);
2565 if (!(the_cli->sec_mode & 1)) {
2566 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2567 cli_shutdown(the_cli);
2571 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2572 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2573 cli_shutdown(the_cli);
2578 * Ok - we have an anonymous connection to the IPC$ share.
2579 * Now start the NT Domain stuff :-).
2582 *pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret);
2584 DEBUG(0,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2585 remote_machine, nt_errstr(ret)));
2586 cli_shutdown(the_cli);
2593 /***************************************************************************
2594 Connect to the client.
2595 ****************************************************************************/
2597 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2598 uint32 localprinter, uint32 type,
2599 POLICY_HND *handle, struct in_addr *client_ip)
2604 * If it's the first connection, contact the client
2605 * and connect to the IPC$ share anonymously
2607 if (smb_connections==0) {
2608 struct cli_state notify_cli; /* print notify back-channel */
2609 fstring unix_printer;
2611 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2613 ZERO_STRUCT(notify_cli);
2615 if(!spoolss_connect_to_client(¬ify_cli, ¬ify_cli_pipe, client_ip, unix_printer))
2618 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2619 /* Tell the connections db we're now interested in printer
2620 * notify messages. */
2621 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2625 * Tell the specific printing tdb we want messages for this printer
2626 * by registering our PID.
2629 if (!print_notify_register_pid(snum))
2630 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2634 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2637 if (!W_ERROR_IS_OK(result))
2638 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2639 dos_errstr(result)));
2641 return (W_ERROR_IS_OK(result));
2644 /********************************************************************
2646 * ReplyFindFirstPrinterChangeNotifyEx
2648 * before replying OK: status=0 a rpc call is made to the workstation
2649 * asking ReplyOpenPrinter
2651 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2652 * called from api_spoolss_rffpcnex
2653 ********************************************************************/
2655 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2657 POLICY_HND *handle = &q_u->handle;
2658 uint32 flags = q_u->flags;
2659 uint32 options = q_u->options;
2660 UNISTR2 *localmachine = &q_u->localmachine;
2661 uint32 printerlocal = q_u->printerlocal;
2663 SPOOL_NOTIFY_OPTION *option = q_u->option;
2664 struct in_addr client_ip;
2666 /* store the notify value in the printer struct */
2668 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2671 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2675 Printer->notify.flags=flags;
2676 Printer->notify.options=options;
2677 Printer->notify.printerlocal=printerlocal;
2679 if (Printer->notify.option)
2680 free_spool_notify_option(&Printer->notify.option);
2682 Printer->notify.option=dup_spool_notify_option(option);
2684 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2685 sizeof(Printer->notify.localmachine)-1);
2687 /* Connect to the client machine and send a ReplyOpenPrinter */
2689 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2691 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2692 !get_printer_snum(p, handle, &snum) )
2695 client_ip.s_addr = inet_addr(p->conn->client_address);
2697 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2698 Printer->notify.printerlocal, 1,
2699 &Printer->notify.client_hnd, &client_ip))
2700 return WERR_SERVER_UNAVAILABLE;
2702 Printer->notify.client_connected=True;
2707 /*******************************************************************
2708 * fill a notify_info_data with the servername
2709 ********************************************************************/
2711 void spoolss_notify_server_name(int snum,
2712 SPOOL_NOTIFY_INFO_DATA *data,
2713 print_queue_struct *queue,
2714 NT_PRINTER_INFO_LEVEL *printer,
2715 TALLOC_CTX *mem_ctx)
2720 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2722 data->notify_data.data.length = len;
2723 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2725 if (!data->notify_data.data.string) {
2726 data->notify_data.data.length = 0;
2730 memcpy(data->notify_data.data.string, temp, len);
2733 /*******************************************************************
2734 * fill a notify_info_data with the printername (not including the servername).
2735 ********************************************************************/
2737 void spoolss_notify_printer_name(int snum,
2738 SPOOL_NOTIFY_INFO_DATA *data,
2739 print_queue_struct *queue,
2740 NT_PRINTER_INFO_LEVEL *printer,
2741 TALLOC_CTX *mem_ctx)
2746 /* the notify name should not contain the \\server\ part */
2747 char *p = strrchr(printer->info_2->printername, '\\');
2750 p = printer->info_2->printername;
2755 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2757 data->notify_data.data.length = len;
2758 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2760 if (!data->notify_data.data.string) {
2761 data->notify_data.data.length = 0;
2765 memcpy(data->notify_data.data.string, temp, len);
2768 /*******************************************************************
2769 * fill a notify_info_data with the servicename
2770 ********************************************************************/
2772 void spoolss_notify_share_name(int snum,
2773 SPOOL_NOTIFY_INFO_DATA *data,
2774 print_queue_struct *queue,
2775 NT_PRINTER_INFO_LEVEL *printer,
2776 TALLOC_CTX *mem_ctx)
2781 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2783 data->notify_data.data.length = len;
2784 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2786 if (!data->notify_data.data.string) {
2787 data->notify_data.data.length = 0;
2791 memcpy(data->notify_data.data.string, temp, len);
2794 /*******************************************************************
2795 * fill a notify_info_data with the port name
2796 ********************************************************************/
2798 void spoolss_notify_port_name(int snum,
2799 SPOOL_NOTIFY_INFO_DATA *data,
2800 print_queue_struct *queue,
2801 NT_PRINTER_INFO_LEVEL *printer,
2802 TALLOC_CTX *mem_ctx)
2807 /* even if it's strange, that's consistant in all the code */
2809 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2811 data->notify_data.data.length = len;
2812 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2814 if (!data->notify_data.data.string) {
2815 data->notify_data.data.length = 0;
2819 memcpy(data->notify_data.data.string, temp, len);
2822 /*******************************************************************
2823 * fill a notify_info_data with the printername
2824 * but it doesn't exist, have to see what to do
2825 ********************************************************************/
2827 void spoolss_notify_driver_name(int snum,
2828 SPOOL_NOTIFY_INFO_DATA *data,
2829 print_queue_struct *queue,
2830 NT_PRINTER_INFO_LEVEL *printer,
2831 TALLOC_CTX *mem_ctx)
2836 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2838 data->notify_data.data.length = len;
2839 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2841 if (!data->notify_data.data.string) {
2842 data->notify_data.data.length = 0;
2846 memcpy(data->notify_data.data.string, temp, len);
2849 /*******************************************************************
2850 * fill a notify_info_data with the comment
2851 ********************************************************************/
2853 void spoolss_notify_comment(int snum,
2854 SPOOL_NOTIFY_INFO_DATA *data,
2855 print_queue_struct *queue,
2856 NT_PRINTER_INFO_LEVEL *printer,
2857 TALLOC_CTX *mem_ctx)
2862 if (*printer->info_2->comment == '\0')
2863 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2865 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2867 data->notify_data.data.length = len;
2868 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2870 if (!data->notify_data.data.string) {
2871 data->notify_data.data.length = 0;
2875 memcpy(data->notify_data.data.string, temp, len);
2878 /*******************************************************************
2879 * fill a notify_info_data with the comment
2880 * location = "Room 1, floor 2, building 3"
2881 ********************************************************************/
2883 void spoolss_notify_location(int snum,
2884 SPOOL_NOTIFY_INFO_DATA *data,
2885 print_queue_struct *queue,
2886 NT_PRINTER_INFO_LEVEL *printer,
2887 TALLOC_CTX *mem_ctx)
2892 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2894 data->notify_data.data.length = len;
2895 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2897 if (!data->notify_data.data.string) {
2898 data->notify_data.data.length = 0;
2902 memcpy(data->notify_data.data.string, temp, len);
2905 /*******************************************************************
2906 * fill a notify_info_data with the device mode
2907 * jfm:xxxx don't to it for know but that's a real problem !!!
2908 ********************************************************************/
2910 static void spoolss_notify_devmode(int snum,
2911 SPOOL_NOTIFY_INFO_DATA *data,
2912 print_queue_struct *queue,
2913 NT_PRINTER_INFO_LEVEL *printer,
2914 TALLOC_CTX *mem_ctx)
2918 /*******************************************************************
2919 * fill a notify_info_data with the separator file name
2920 ********************************************************************/
2922 void spoolss_notify_sepfile(int snum,
2923 SPOOL_NOTIFY_INFO_DATA *data,
2924 print_queue_struct *queue,
2925 NT_PRINTER_INFO_LEVEL *printer,
2926 TALLOC_CTX *mem_ctx)
2931 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2933 data->notify_data.data.length = len;
2934 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2936 if (!data->notify_data.data.string) {
2937 data->notify_data.data.length = 0;
2941 memcpy(data->notify_data.data.string, temp, len);
2944 /*******************************************************************
2945 * fill a notify_info_data with the print processor
2946 * jfm:xxxx return always winprint to indicate we don't do anything to it
2947 ********************************************************************/
2949 void spoolss_notify_print_processor(int snum,
2950 SPOOL_NOTIFY_INFO_DATA *data,
2951 print_queue_struct *queue,
2952 NT_PRINTER_INFO_LEVEL *printer,
2953 TALLOC_CTX *mem_ctx)
2958 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2960 data->notify_data.data.length = len;
2961 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2963 if (!data->notify_data.data.string) {
2964 data->notify_data.data.length = 0;
2968 memcpy(data->notify_data.data.string, temp, len);
2971 /*******************************************************************
2972 * fill a notify_info_data with the print processor options
2973 * jfm:xxxx send an empty string
2974 ********************************************************************/
2976 void spoolss_notify_parameters(int snum,
2977 SPOOL_NOTIFY_INFO_DATA *data,
2978 print_queue_struct *queue,
2979 NT_PRINTER_INFO_LEVEL *printer,
2980 TALLOC_CTX *mem_ctx)
2985 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2987 data->notify_data.data.length = len;
2988 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2990 if (!data->notify_data.data.string) {
2991 data->notify_data.data.length = 0;
2995 memcpy(data->notify_data.data.string, temp, len);
2998 /*******************************************************************
2999 * fill a notify_info_data with the data type
3000 * jfm:xxxx always send RAW as data type
3001 ********************************************************************/
3003 void spoolss_notify_datatype(int snum,
3004 SPOOL_NOTIFY_INFO_DATA *data,
3005 print_queue_struct *queue,
3006 NT_PRINTER_INFO_LEVEL *printer,
3007 TALLOC_CTX *mem_ctx)
3012 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3014 data->notify_data.data.length = len;
3015 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3017 if (!data->notify_data.data.string) {
3018 data->notify_data.data.length = 0;
3022 memcpy(data->notify_data.data.string, temp, len);
3025 /*******************************************************************
3026 * fill a notify_info_data with the security descriptor
3027 * jfm:xxxx send an null pointer to say no security desc
3028 * have to implement security before !
3029 ********************************************************************/
3031 static void spoolss_notify_security_desc(int snum,
3032 SPOOL_NOTIFY_INFO_DATA *data,
3033 print_queue_struct *queue,
3034 NT_PRINTER_INFO_LEVEL *printer,
3035 TALLOC_CTX *mem_ctx)
3037 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3038 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3041 /*******************************************************************
3042 * fill a notify_info_data with the attributes
3043 * jfm:xxxx a samba printer is always shared
3044 ********************************************************************/
3046 void spoolss_notify_attributes(int snum,
3047 SPOOL_NOTIFY_INFO_DATA *data,
3048 print_queue_struct *queue,
3049 NT_PRINTER_INFO_LEVEL *printer,
3050 TALLOC_CTX *mem_ctx)
3052 data->notify_data.value[0] = printer->info_2->attributes;
3053 data->notify_data.value[1] = 0;
3056 /*******************************************************************
3057 * fill a notify_info_data with the priority
3058 ********************************************************************/
3060 static void spoolss_notify_priority(int snum,
3061 SPOOL_NOTIFY_INFO_DATA *data,
3062 print_queue_struct *queue,
3063 NT_PRINTER_INFO_LEVEL *printer,
3064 TALLOC_CTX *mem_ctx)
3066 data->notify_data.value[0] = printer->info_2->priority;
3067 data->notify_data.value[1] = 0;
3070 /*******************************************************************
3071 * fill a notify_info_data with the default priority
3072 ********************************************************************/
3074 static void spoolss_notify_default_priority(int snum,
3075 SPOOL_NOTIFY_INFO_DATA *data,
3076 print_queue_struct *queue,
3077 NT_PRINTER_INFO_LEVEL *printer,
3078 TALLOC_CTX *mem_ctx)
3080 data->notify_data.value[0] = printer->info_2->default_priority;
3081 data->notify_data.value[1] = 0;
3084 /*******************************************************************
3085 * fill a notify_info_data with the start time
3086 ********************************************************************/
3088 static void spoolss_notify_start_time(int snum,
3089 SPOOL_NOTIFY_INFO_DATA *data,
3090 print_queue_struct *queue,
3091 NT_PRINTER_INFO_LEVEL *printer,
3092 TALLOC_CTX *mem_ctx)
3094 data->notify_data.value[0] = printer->info_2->starttime;
3095 data->notify_data.value[1] = 0;
3098 /*******************************************************************
3099 * fill a notify_info_data with the until time
3100 ********************************************************************/
3102 static void spoolss_notify_until_time(int snum,
3103 SPOOL_NOTIFY_INFO_DATA *data,
3104 print_queue_struct *queue,
3105 NT_PRINTER_INFO_LEVEL *printer,
3106 TALLOC_CTX *mem_ctx)
3108 data->notify_data.value[0] = printer->info_2->untiltime;
3109 data->notify_data.value[1] = 0;
3112 /*******************************************************************
3113 * fill a notify_info_data with the status
3114 ********************************************************************/
3116 static void spoolss_notify_status(int snum,
3117 SPOOL_NOTIFY_INFO_DATA *data,
3118 print_queue_struct *queue,
3119 NT_PRINTER_INFO_LEVEL *printer,
3120 TALLOC_CTX *mem_ctx)
3122 print_status_struct status;
3124 print_queue_length(snum, &status);
3125 data->notify_data.value[0]=(uint32) status.status;
3126 data->notify_data.value[1] = 0;
3129 /*******************************************************************
3130 * fill a notify_info_data with the number of jobs queued
3131 ********************************************************************/
3133 void spoolss_notify_cjobs(int snum,
3134 SPOOL_NOTIFY_INFO_DATA *data,
3135 print_queue_struct *queue,
3136 NT_PRINTER_INFO_LEVEL *printer,
3137 TALLOC_CTX *mem_ctx)
3139 data->notify_data.value[0] = print_queue_length(snum, NULL);
3140 data->notify_data.value[1] = 0;
3143 /*******************************************************************
3144 * fill a notify_info_data with the average ppm
3145 ********************************************************************/
3147 static void spoolss_notify_average_ppm(int snum,
3148 SPOOL_NOTIFY_INFO_DATA *data,
3149 print_queue_struct *queue,
3150 NT_PRINTER_INFO_LEVEL *printer,
3151 TALLOC_CTX *mem_ctx)
3153 /* always respond 8 pages per minutes */
3154 /* a little hard ! */
3155 data->notify_data.value[0] = printer->info_2->averageppm;
3156 data->notify_data.value[1] = 0;
3159 /*******************************************************************
3160 * fill a notify_info_data with username
3161 ********************************************************************/
3163 static void spoolss_notify_username(int snum,
3164 SPOOL_NOTIFY_INFO_DATA *data,
3165 print_queue_struct *queue,
3166 NT_PRINTER_INFO_LEVEL *printer,
3167 TALLOC_CTX *mem_ctx)
3172 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3174 data->notify_data.data.length = len;
3175 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3177 if (!data->notify_data.data.string) {
3178 data->notify_data.data.length = 0;
3182 memcpy(data->notify_data.data.string, temp, len);
3185 /*******************************************************************
3186 * fill a notify_info_data with job status
3187 ********************************************************************/
3189 static void spoolss_notify_job_status(int snum,
3190 SPOOL_NOTIFY_INFO_DATA *data,
3191 print_queue_struct *queue,
3192 NT_PRINTER_INFO_LEVEL *printer,
3193 TALLOC_CTX *mem_ctx)
3195 data->notify_data.value[0]=nt_printj_status(queue->status);
3196 data->notify_data.value[1] = 0;
3199 /*******************************************************************
3200 * fill a notify_info_data with job name
3201 ********************************************************************/
3203 static void spoolss_notify_job_name(int snum,
3204 SPOOL_NOTIFY_INFO_DATA *data,
3205 print_queue_struct *queue,
3206 NT_PRINTER_INFO_LEVEL *printer,
3207 TALLOC_CTX *mem_ctx)
3212 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3214 data->notify_data.data.length = len;
3215 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3217 if (!data->notify_data.data.string) {
3218 data->notify_data.data.length = 0;
3222 memcpy(data->notify_data.data.string, temp, len);
3225 /*******************************************************************
3226 * fill a notify_info_data with job status
3227 ********************************************************************/
3229 static void spoolss_notify_job_status_string(int snum,
3230 SPOOL_NOTIFY_INFO_DATA *data,
3231 print_queue_struct *queue,
3232 NT_PRINTER_INFO_LEVEL *printer,
3233 TALLOC_CTX *mem_ctx)
3236 * Now we're returning job status codes we just return a "" here. JRA.
3243 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3246 switch (queue->status) {
3251 p = ""; /* NT provides the paused string */
3260 #endif /* NO LONGER NEEDED. */
3262 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3264 data->notify_data.data.length = len;
3265 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3267 if (!data->notify_data.data.string) {
3268 data->notify_data.data.length = 0;
3272 memcpy(data->notify_data.data.string, temp, len);
3275 /*******************************************************************
3276 * fill a notify_info_data with job time
3277 ********************************************************************/
3279 static void spoolss_notify_job_time(int snum,
3280 SPOOL_NOTIFY_INFO_DATA *data,
3281 print_queue_struct *queue,
3282 NT_PRINTER_INFO_LEVEL *printer,
3283 TALLOC_CTX *mem_ctx)
3285 data->notify_data.value[0]=0x0;
3286 data->notify_data.value[1]=0;
3289 /*******************************************************************
3290 * fill a notify_info_data with job size
3291 ********************************************************************/
3293 static void spoolss_notify_job_size(int snum,
3294 SPOOL_NOTIFY_INFO_DATA *data,
3295 print_queue_struct *queue,
3296 NT_PRINTER_INFO_LEVEL *printer,
3297 TALLOC_CTX *mem_ctx)
3299 data->notify_data.value[0]=queue->size;
3300 data->notify_data.value[1]=0;
3303 /*******************************************************************
3304 * fill a notify_info_data with page info
3305 ********************************************************************/
3306 static void spoolss_notify_total_pages(int snum,
3307 SPOOL_NOTIFY_INFO_DATA *data,
3308 print_queue_struct *queue,
3309 NT_PRINTER_INFO_LEVEL *printer,
3310 TALLOC_CTX *mem_ctx)
3312 data->notify_data.value[0]=queue->page_count;
3313 data->notify_data.value[1]=0;
3316 /*******************************************************************
3317 * fill a notify_info_data with pages printed info.
3318 ********************************************************************/
3319 static void spoolss_notify_pages_printed(int snum,
3320 SPOOL_NOTIFY_INFO_DATA *data,
3321 print_queue_struct *queue,
3322 NT_PRINTER_INFO_LEVEL *printer,
3323 TALLOC_CTX *mem_ctx)
3325 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3326 data->notify_data.value[1]=0;
3329 /*******************************************************************
3330 Fill a notify_info_data with job position.
3331 ********************************************************************/
3333 static void spoolss_notify_job_position(int snum,
3334 SPOOL_NOTIFY_INFO_DATA *data,
3335 print_queue_struct *queue,
3336 NT_PRINTER_INFO_LEVEL *printer,
3337 TALLOC_CTX *mem_ctx)
3339 data->notify_data.value[0]=queue->job;
3340 data->notify_data.value[1]=0;
3343 /*******************************************************************
3344 Fill a notify_info_data with submitted time.
3345 ********************************************************************/
3347 static void spoolss_notify_submitted_time(int snum,
3348 SPOOL_NOTIFY_INFO_DATA *data,
3349 print_queue_struct *queue,
3350 NT_PRINTER_INFO_LEVEL *printer,
3351 TALLOC_CTX *mem_ctx)
3358 t=gmtime(&queue->time);
3360 len = sizeof(SYSTEMTIME);
3362 data->notify_data.data.length = len;
3363 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3365 if (!data->notify_data.data.string) {
3366 data->notify_data.data.length = 0;
3370 make_systemtime(&st, t);
3373 * Systemtime must be linearized as a set of UINT16's.
3374 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3377 p = (char *)data->notify_data.data.string;
3378 SSVAL(p, 0, st.year);
3379 SSVAL(p, 2, st.month);
3380 SSVAL(p, 4, st.dayofweek);
3381 SSVAL(p, 6, st.day);
3382 SSVAL(p, 8, st.hour);
3383 SSVAL(p, 10, st.minute);
3384 SSVAL(p, 12, st.second);
3385 SSVAL(p, 14, st.milliseconds);
3388 struct s_notify_info_data_table
3394 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3395 print_queue_struct *queue,
3396 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3399 /* A table describing the various print notification constants and
3400 whether the notification data is a pointer to a variable sized
3401 buffer, a one value uint32 or a two value uint32. */
3403 static const struct s_notify_info_data_table notify_info_data_table[] =
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3445 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3446 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3447 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3448 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3449 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3450 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3452 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3453 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3454 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3457 /*******************************************************************
3458 Return the size of info_data structure.
3459 ********************************************************************/
3461 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3465 for (i = 0; i < sizeof(notify_info_data_table); i++)
3467 if ( (notify_info_data_table[i].type == type)
3468 && (notify_info_data_table[i].field == field) )
3470 switch(notify_info_data_table[i].size)
3472 case NOTIFY_ONE_VALUE:
3473 case NOTIFY_TWO_VALUE:
3478 /* The only pointer notify data I have seen on
3479 the wire is the submitted time and this has
3480 the notify size set to 4. -tpot */
3482 case NOTIFY_POINTER:
3485 case NOTIFY_SECDESC:
3491 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3496 /*******************************************************************
3497 Return the type of notify_info_data.
3498 ********************************************************************/
3500 static int type_of_notify_info_data(uint16 type, uint16 field)
3504 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3505 if (notify_info_data_table[i].type == type &&
3506 notify_info_data_table[i].field == field)
3507 return notify_info_data_table[i].size;
3513 /****************************************************************************
3514 ****************************************************************************/
3516 static int search_notify(uint16 type, uint16 field, int *value)
3520 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3521 if (notify_info_data_table[i].type == type &&
3522 notify_info_data_table[i].field == field &&
3523 notify_info_data_table[i].fn != NULL) {
3532 /****************************************************************************
3533 ****************************************************************************/
3535 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3537 info_data->type = type;
3538 info_data->field = field;
3539 info_data->reserved = 0;
3541 info_data->size = size_of_notify_info_data(type, field);
3542 info_data->enc_type = type_of_notify_info_data(type, field);
3549 /*******************************************************************
3551 * fill a notify_info struct with info asked
3553 ********************************************************************/
3555 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3556 snum, SPOOL_NOTIFY_OPTION_TYPE
3557 *option_type, uint32 id,
3558 TALLOC_CTX *mem_ctx)
3564 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3565 NT_PRINTER_INFO_LEVEL *printer = NULL;
3566 print_queue_struct *queue=NULL;
3568 type=option_type->type;
3570 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3571 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3572 option_type->count, lp_servicename(snum)));
3574 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3577 for(field_num=0; field_num<option_type->count; field_num++) {
3578 field = option_type->fields[field_num];
3580 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3582 if (!search_notify(type, field, &j) )
3585 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3586 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3591 current_data = &info->data[info->count];
3593 construct_info_data(current_data, type, field, id);
3595 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3596 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3598 notify_info_data_table[j].fn(snum, current_data, queue,
3604 free_a_printer(&printer, 2);
3608 /*******************************************************************
3610 * fill a notify_info struct with info asked
3612 ********************************************************************/
3614 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3615 SPOOL_NOTIFY_INFO *info,
3616 NT_PRINTER_INFO_LEVEL *printer,
3617 int snum, SPOOL_NOTIFY_OPTION_TYPE
3618 *option_type, uint32 id,
3619 TALLOC_CTX *mem_ctx)
3625 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3627 DEBUG(4,("construct_notify_jobs_info\n"));
3629 type = option_type->type;
3631 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3632 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3633 option_type->count));
3635 for(field_num=0; field_num<option_type->count; field_num++) {
3636 field = option_type->fields[field_num];
3638 if (!search_notify(type, field, &j) )
3641 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3642 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3645 else info->data = tid;
3647 current_data=&(info->data[info->count]);
3649 construct_info_data(current_data, type, field, id);
3650 notify_info_data_table[j].fn(snum, current_data, queue,
3659 * JFM: The enumeration is not that simple, it's even non obvious.
3661 * let's take an example: I want to monitor the PRINTER SERVER for
3662 * the printer's name and the number of jobs currently queued.
3663 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3664 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3666 * I have 3 printers on the back of my server.
3668 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3671 * 1 printer 1 name 1
3672 * 2 printer 1 cjob 1
3673 * 3 printer 2 name 2
3674 * 4 printer 2 cjob 2
3675 * 5 printer 3 name 3
3676 * 6 printer 3 name 3
3678 * that's the print server case, the printer case is even worse.
3681 /*******************************************************************
3683 * enumerate all printers on the printserver
3684 * fill a notify_info struct with info asked
3686 ********************************************************************/
3688 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3689 SPOOL_NOTIFY_INFO *info,
3690 TALLOC_CTX *mem_ctx)
3693 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3694 int n_services=lp_numservices();
3696 SPOOL_NOTIFY_OPTION *option;
3697 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3699 DEBUG(4,("printserver_notify_info\n"));
3704 option=Printer->notify.option;
3709 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3710 sending a ffpcn() request first */
3715 for (i=0; i<option->count; i++) {
3716 option_type=&(option->ctr.type[i]);
3718 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3721 for (snum=0; snum<n_services; snum++)
3723 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3724 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3730 * Debugging information, don't delete.
3733 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3734 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3735 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3737 for (i=0; i<info->count; i++) {
3738 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3739 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3740 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3747 /*******************************************************************
3749 * fill a notify_info struct with info asked
3751 ********************************************************************/
3753 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3754 TALLOC_CTX *mem_ctx)
3757 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3760 SPOOL_NOTIFY_OPTION *option;
3761 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3763 print_queue_struct *queue=NULL;
3764 print_status_struct status;
3766 DEBUG(4,("printer_notify_info\n"));
3771 option=Printer->notify.option;
3777 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3778 sending a ffpcn() request first */
3783 get_printer_snum(p, hnd, &snum);
3785 for (i=0; i<option->count; i++) {
3786 option_type=&option->ctr.type[i];
3788 switch ( option_type->type ) {
3789 case PRINTER_NOTIFY_TYPE:
3790 if(construct_notify_printer_info(Printer, info, snum,
3796 case JOB_NOTIFY_TYPE: {
3797 NT_PRINTER_INFO_LEVEL *printer = NULL;
3799 count = print_queue_status(snum, &queue, &status);
3801 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3804 for (j=0; j<count; j++) {
3805 construct_notify_jobs_info(&queue[j], info,
3812 free_a_printer(&printer, 2);
3822 * Debugging information, don't delete.
3825 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3826 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3827 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3829 for (i=0; i<info->count; i++) {
3830 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3831 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3832 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3838 /********************************************************************
3840 ********************************************************************/
3842 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3844 POLICY_HND *handle = &q_u->handle;
3845 SPOOL_NOTIFY_INFO *info = &r_u->info;
3847 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3848 WERROR result = WERR_BADFID;
3850 /* we always have a NOTIFY_INFO struct */
3854 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3855 OUR_HANDLE(handle)));
3859 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3862 * We are now using the change value, and
3863 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3864 * I don't have a global notification system, I'm sending back all the
3865 * informations even when _NOTHING_ has changed.
3868 /* We need to keep track of the change value to send back in
3869 RRPCN replies otherwise our updates are ignored. */
3871 Printer->notify.fnpcn = True;
3873 if (Printer->notify.client_connected) {
3874 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3875 Printer->notify.change = q_u->change;
3878 /* just ignore the SPOOL_NOTIFY_OPTION */
3880 switch (Printer->printer_type) {
3881 case PRINTER_HANDLE_IS_PRINTSERVER:
3882 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3885 case PRINTER_HANDLE_IS_PRINTER:
3886 result = printer_notify_info(p, handle, info, p->mem_ctx);
3890 Printer->notify.fnpcn = False;
3896 /********************************************************************
3897 * construct_printer_info_0
3898 * fill a printer_info_0 struct
3899 ********************************************************************/
3901 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3905 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3906 counter_printer_0 *session_counter;
3907 uint32 global_counter;
3910 print_status_struct status;
3912 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3915 count = print_queue_length(snum, &status);
3917 /* check if we already have a counter for this printer */
3918 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3919 if (session_counter->snum == snum)
3923 /* it's the first time, add it to the list */
3924 if (session_counter==NULL) {
3925 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3926 free_a_printer(&ntprinter, 2);
3929 ZERO_STRUCTP(session_counter);
3930 session_counter->snum=snum;
3931 session_counter->counter=0;
3932 DLIST_ADD(counter_list, session_counter);
3936 session_counter->counter++;
3939 * the global_counter should be stored in a TDB as it's common to all the clients
3940 * and should be zeroed on samba startup
3942 global_counter=session_counter->counter;
3944 pstrcpy(chaine,ntprinter->info_2->printername);
3946 init_unistr(&printer->printername, chaine);
3948 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3949 init_unistr(&printer->servername, chaine);
3951 printer->cjobs = count;
3952 printer->total_jobs = 0;
3953 printer->total_bytes = 0;
3955 setuptime = (time_t)ntprinter->info_2->setuptime;
3956 t=gmtime(&setuptime);
3958 printer->year = t->tm_year+1900;
3959 printer->month = t->tm_mon+1;
3960 printer->dayofweek = t->tm_wday;
3961 printer->day = t->tm_mday;
3962 printer->hour = t->tm_hour;
3963 printer->minute = t->tm_min;
3964 printer->second = t->tm_sec;
3965 printer->milliseconds = 0;
3967 printer->global_counter = global_counter;
3968 printer->total_pages = 0;
3970 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3971 printer->major_version = 0x0005; /* NT 5 */
3972 printer->build_version = 0x0893; /* build 2195 */
3974 printer->unknown7 = 0x1;
3975 printer->unknown8 = 0x0;
3976 printer->unknown9 = 0x0;
3977 printer->session_counter = session_counter->counter;
3978 printer->unknown11 = 0x0;
3979 printer->printer_errors = 0x0; /* number of print failure */
3980 printer->unknown13 = 0x0;
3981 printer->unknown14 = 0x1;
3982 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3983 printer->unknown16 = 0x0;
3984 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3985 printer->unknown18 = 0x0;
3986 printer->status = nt_printq_status(status.status);
3987 printer->unknown20 = 0x0;
3988 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3989 printer->unknown22 = 0x0;
3990 printer->unknown23 = 0x6; /* 6 ???*/
3991 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3992 printer->unknown25 = 0;
3993 printer->unknown26 = 0;
3994 printer->unknown27 = 0;
3995 printer->unknown28 = 0;
3996 printer->unknown29 = 0;
3998 free_a_printer(&ntprinter,2);
4002 /********************************************************************
4003 * construct_printer_info_1
4004 * fill a printer_info_1 struct
4005 ********************************************************************/
4006 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4010 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4012 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4015 printer->flags=flags;
4017 if (*ntprinter->info_2->comment == '\0') {
4018 init_unistr(&printer->comment, lp_comment(snum));
4019 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4020 ntprinter->info_2->drivername, lp_comment(snum));
4023 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4024 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4025 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4028 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4030 init_unistr(&printer->description, chaine);
4031 init_unistr(&printer->name, chaine2);
4033 free_a_printer(&ntprinter,2);
4038 /****************************************************************************
4039 Free a DEVMODE struct.
4040 ****************************************************************************/
4042 static void free_dev_mode(DEVICEMODE *dev)
4047 SAFE_FREE(dev->dev_private);
4052 /****************************************************************************
4053 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4054 should be valid upon entry
4055 ****************************************************************************/
4057 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4059 if ( !devmode || !ntdevmode )
4062 init_unistr(&devmode->devicename, ntdevmode->devicename);
4064 init_unistr(&devmode->formname, ntdevmode->formname);
4066 devmode->specversion = ntdevmode->specversion;
4067 devmode->driverversion = ntdevmode->driverversion;
4068 devmode->size = ntdevmode->size;
4069 devmode->driverextra = ntdevmode->driverextra;
4070 devmode->fields = ntdevmode->fields;
4072 devmode->orientation = ntdevmode->orientation;
4073 devmode->papersize = ntdevmode->papersize;
4074 devmode->paperlength = ntdevmode->paperlength;
4075 devmode->paperwidth = ntdevmode->paperwidth;
4076 devmode->scale = ntdevmode->scale;
4077 devmode->copies = ntdevmode->copies;
4078 devmode->defaultsource = ntdevmode->defaultsource;
4079 devmode->printquality = ntdevmode->printquality;
4080 devmode->color = ntdevmode->color;
4081 devmode->duplex = ntdevmode->duplex;
4082 devmode->yresolution = ntdevmode->yresolution;
4083 devmode->ttoption = ntdevmode->ttoption;
4084 devmode->collate = ntdevmode->collate;
4085 devmode->icmmethod = ntdevmode->icmmethod;
4086 devmode->icmintent = ntdevmode->icmintent;
4087 devmode->mediatype = ntdevmode->mediatype;
4088 devmode->dithertype = ntdevmode->dithertype;
4090 if (ntdevmode->nt_dev_private != NULL) {
4091 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4098 /****************************************************************************
4099 Create a DEVMODE struct. Returns malloced memory.
4100 ****************************************************************************/
4102 DEVICEMODE *construct_dev_mode(int snum)
4104 NT_PRINTER_INFO_LEVEL *printer = NULL;
4105 DEVICEMODE *devmode = NULL;
4107 DEBUG(7,("construct_dev_mode\n"));
4109 DEBUGADD(8,("getting printer characteristics\n"));
4111 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4114 if ( !printer->info_2->devmode ) {
4115 DEBUG(5, ("BONG! There was no device mode!\n"));
4119 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4120 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4124 ZERO_STRUCTP(devmode);
4126 DEBUGADD(8,("loading DEVICEMODE\n"));
4128 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4129 free_dev_mode( devmode );
4134 free_a_printer(&printer,2);
4139 /********************************************************************
4140 * construct_printer_info_2
4141 * fill a printer_info_2 struct
4142 ********************************************************************/
4144 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4147 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4149 print_status_struct status;
4151 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4154 count = print_queue_length(snum, &status);
4156 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4157 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4158 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4159 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4160 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4162 if (*ntprinter->info_2->comment == '\0')
4163 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4165 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4167 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4168 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4169 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4170 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4171 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4173 printer->attributes = ntprinter->info_2->attributes;
4175 printer->priority = ntprinter->info_2->priority; /* priority */
4176 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4177 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4178 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4179 printer->status = nt_printq_status(status.status); /* status */
4180 printer->cjobs = count; /* jobs */
4181 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4183 if ( !(printer->devmode = construct_dev_mode(snum)) )
4184 DEBUG(8, ("Returning NULL Devicemode!\n"));
4186 printer->secdesc = NULL;
4188 if ( ntprinter->info_2->secdesc_buf
4189 && ntprinter->info_2->secdesc_buf->len != 0 )
4191 /* don't use talloc_steal() here unless you do a deep steal of all
4192 the SEC_DESC members */
4194 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4195 ntprinter->info_2->secdesc_buf->sec );
4198 free_a_printer(&ntprinter, 2);
4203 /********************************************************************
4204 * construct_printer_info_3
4205 * fill a printer_info_3 struct
4206 ********************************************************************/
4208 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4210 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4211 PRINTER_INFO_3 *printer = NULL;
4213 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4217 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4218 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4222 ZERO_STRUCTP(printer);
4224 /* These are the components of the SD we are returning. */
4226 printer->flags = 0x4;
4228 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4229 /* don't use talloc_steal() here unless you do a deep steal of all
4230 the SEC_DESC members */
4232 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4233 ntprinter->info_2->secdesc_buf->sec );
4236 free_a_printer(&ntprinter, 2);
4238 *pp_printer = printer;
4242 /********************************************************************
4243 * construct_printer_info_4
4244 * fill a printer_info_4 struct
4245 ********************************************************************/
4247 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4249 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4251 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4254 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4255 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4256 printer->attributes = ntprinter->info_2->attributes;
4258 free_a_printer(&ntprinter, 2);
4262 /********************************************************************
4263 * construct_printer_info_5
4264 * fill a printer_info_5 struct
4265 ********************************************************************/
4267 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4269 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4271 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4274 init_unistr(&printer->printername, ntprinter->info_2->printername);
4275 init_unistr(&printer->portname, ntprinter->info_2->portname);
4276 printer->attributes = ntprinter->info_2->attributes;
4278 /* these two are not used by NT+ according to MSDN */
4280 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4281 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4283 free_a_printer(&ntprinter, 2);
4288 /********************************************************************
4289 * construct_printer_info_7
4290 * fill a printer_info_7 struct
4291 ********************************************************************/
4293 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4295 char *guid_str = NULL;
4298 if (is_printer_published(print_hnd, snum, &guid)) {
4299 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4300 strupper_m(guid_str);
4301 init_unistr(&printer->guid, guid_str);
4302 printer->action = SPOOL_DS_PUBLISH;
4304 init_unistr(&printer->guid, "");
4305 printer->action = SPOOL_DS_UNPUBLISH;
4311 /********************************************************************
4312 Spoolss_enumprinters.
4313 ********************************************************************/
4315 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4319 int n_services=lp_numservices();
4320 PRINTER_INFO_1 *tp, *printers=NULL;
4321 PRINTER_INFO_1 current_prt;
4322 WERROR result = WERR_OK;
4324 DEBUG(4,("enum_all_printers_info_1\n"));
4326 for (snum=0; snum<n_services; snum++) {
4327 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4328 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4330 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4331 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4332 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4333 SAFE_FREE(printers);
4338 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4340 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4346 /* check the required size. */
4347 for (i=0; i<*returned; i++)
4348 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4350 if (*needed > offered) {
4351 result = WERR_INSUFFICIENT_BUFFER;
4355 if (!rpcbuf_alloc_size(buffer, *needed)) {
4356 result = WERR_NOMEM;
4360 /* fill the buffer with the structures */
4361 for (i=0; i<*returned; i++)
4362 smb_io_printer_info_1("", buffer, &printers[i], 0);
4367 SAFE_FREE(printers);
4369 if ( !W_ERROR_IS_OK(result) )
4375 /********************************************************************
4376 enum_all_printers_info_1_local.
4377 *********************************************************************/
4379 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4381 DEBUG(4,("enum_all_printers_info_1_local\n"));
4383 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4386 /********************************************************************
4387 enum_all_printers_info_1_name.
4388 *********************************************************************/
4390 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4394 DEBUG(4,("enum_all_printers_info_1_name\n"));
4396 if ((name[0] == '\\') && (name[1] == '\\'))
4399 if (is_myname_or_ipaddr(s)) {
4400 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4403 return WERR_INVALID_NAME;
4406 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4407 /********************************************************************
4408 enum_all_printers_info_1_remote.
4409 *********************************************************************/
4411 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4413 PRINTER_INFO_1 *printer;
4414 fstring printername;
4417 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4418 WERROR result = WERR_OK;
4420 /* JFM: currently it's more a place holder than anything else.
4421 * In the spooler world there is a notion of server registration.
4422 * the print servers are registered on the PDC (in the same domain)
4424 * We should have a TDB here. The registration is done thru an
4425 * undocumented RPC call.
4428 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4433 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4434 slprintf(desc, sizeof(desc)-1,"%s", name);
4435 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4437 init_unistr(&printer->description, desc);
4438 init_unistr(&printer->name, printername);
4439 init_unistr(&printer->comment, comment);
4440 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4442 /* check the required size. */
4443 *needed += spoolss_size_printer_info_1(printer);
4445 if (*needed > offered) {
4446 result = WERR_INSUFFICIENT_BUFFER;
4450 if (!rpcbuf_alloc_size(buffer, *needed)) {
4451 result = WERR_NOMEM;
4455 /* fill the buffer with the structures */
4456 smb_io_printer_info_1("", buffer, printer, 0);
4462 if ( !W_ERROR_IS_OK(result) )
4470 /********************************************************************
4471 enum_all_printers_info_1_network.
4472 *********************************************************************/
4474 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4478 DEBUG(4,("enum_all_printers_info_1_network\n"));
4480 /* If we respond to a enum_printers level 1 on our name with flags
4481 set to PRINTER_ENUM_REMOTE with a list of printers then these
4482 printers incorrectly appear in the APW browse list.
4483 Specifically the printers for the server appear at the workgroup
4484 level where all the other servers in the domain are
4485 listed. Windows responds to this call with a
4486 WERR_CAN_NOT_COMPLETE so we should do the same. */
4488 if (name[0] == '\\' && name[1] == '\\')
4491 if (is_myname_or_ipaddr(s))
4492 return WERR_CAN_NOT_COMPLETE;
4494 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4497 /********************************************************************
4498 * api_spoolss_enumprinters
4500 * called from api_spoolss_enumprinters (see this to understand)
4501 ********************************************************************/
4503 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4507 int n_services=lp_numservices();
4508 PRINTER_INFO_2 *tp, *printers=NULL;
4509 PRINTER_INFO_2 current_prt;
4510 WERROR result = WERR_OK;
4512 for (snum=0; snum<n_services; snum++) {
4513 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4514 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4516 if (construct_printer_info_2(NULL, ¤t_prt, snum))
4518 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4519 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4520 SAFE_FREE(printers);
4525 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4528 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4535 /* check the required size. */
4536 for (i=0; i<*returned; i++)
4537 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4539 if (*needed > offered) {
4540 result = WERR_INSUFFICIENT_BUFFER;
4544 if (!rpcbuf_alloc_size(buffer, *needed)) {
4545 result = WERR_NOMEM;
4549 /* fill the buffer with the structures */
4550 for (i=0; i<*returned; i++)
4551 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4556 for (i=0; i<*returned; i++)
4557 free_devmode(printers[i].devmode);
4559 SAFE_FREE(printers);
4561 if ( !W_ERROR_IS_OK(result) )
4567 /********************************************************************
4568 * handle enumeration of printers at level 1
4569 ********************************************************************/
4571 static WERROR enumprinters_level1( uint32 flags, fstring name,
4572 RPC_BUFFER *buffer, uint32 offered,
4573 uint32 *needed, uint32 *returned)
4575 /* Not all the flags are equals */
4577 if (flags & PRINTER_ENUM_LOCAL)
4578 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4580 if (flags & PRINTER_ENUM_NAME)
4581 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4583 #if 0 /* JERRY - disabled for now */
4584 if (flags & PRINTER_ENUM_REMOTE)
4585 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4588 if (flags & PRINTER_ENUM_NETWORK)
4589 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4591 return WERR_OK; /* NT4sp5 does that */
4594 /********************************************************************
4595 * handle enumeration of printers at level 2
4596 ********************************************************************/
4598 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4599 RPC_BUFFER *buffer, uint32 offered,
4600 uint32 *needed, uint32 *returned)
4602 char *s = servername;
4604 if (flags & PRINTER_ENUM_LOCAL) {
4605 return enum_all_printers_info_2(buffer, offered, needed, returned);
4608 if (flags & PRINTER_ENUM_NAME) {
4609 if ((servername[0] == '\\') && (servername[1] == '\\'))
4611 if (is_myname_or_ipaddr(s))
4612 return enum_all_printers_info_2(buffer, offered, needed, returned);
4614 return WERR_INVALID_NAME;
4617 if (flags & PRINTER_ENUM_REMOTE)
4618 return WERR_UNKNOWN_LEVEL;
4623 /********************************************************************
4624 * handle enumeration of printers at level 5
4625 ********************************************************************/
4627 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4628 RPC_BUFFER *buffer, uint32 offered,
4629 uint32 *needed, uint32 *returned)
4631 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4635 /********************************************************************
4636 * api_spoolss_enumprinters
4638 * called from api_spoolss_enumprinters (see this to understand)
4639 ********************************************************************/
4641 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4643 uint32 flags = q_u->flags;
4644 UNISTR2 *servername = &q_u->servername;
4645 uint32 level = q_u->level;
4646 RPC_BUFFER *buffer = NULL;
4647 uint32 offered = q_u->offered;
4648 uint32 *needed = &r_u->needed;
4649 uint32 *returned = &r_u->returned;
4653 /* that's an [in out] buffer */
4655 if ( q_u->buffer ) {
4656 rpcbuf_move(q_u->buffer, &r_u->buffer);
4657 buffer = r_u->buffer;
4660 DEBUG(4,("_spoolss_enumprinters\n"));
4667 * flags==PRINTER_ENUM_NAME
4668 * if name=="" then enumerates all printers
4669 * if name!="" then enumerate the printer
4670 * flags==PRINTER_ENUM_REMOTE
4671 * name is NULL, enumerate printers
4672 * Level 2: name!="" enumerates printers, name can't be NULL
4673 * Level 3: doesn't exist
4674 * Level 4: does a local registry lookup
4675 * Level 5: same as Level 2
4678 unistr2_to_ascii(name, servername, sizeof(name)-1);
4683 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4685 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4687 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4692 return WERR_UNKNOWN_LEVEL;
4695 /****************************************************************************
4696 ****************************************************************************/
4698 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4700 PRINTER_INFO_0 *printer=NULL;
4701 WERROR result = WERR_OK;
4703 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4706 construct_printer_info_0(print_hnd, printer, snum);
4708 /* check the required size. */
4709 *needed += spoolss_size_printer_info_0(printer);
4711 if (*needed > offered) {
4712 result = WERR_INSUFFICIENT_BUFFER;
4716 if (!rpcbuf_alloc_size(buffer, *needed)) {
4717 result = WERR_NOMEM;
4721 /* fill the buffer with the structures */
4722 smb_io_printer_info_0("", buffer, printer, 0);
4732 /****************************************************************************
4733 ****************************************************************************/
4735 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4737 PRINTER_INFO_1 *printer=NULL;
4738 WERROR result = WERR_OK;
4740 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4743 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4745 /* check the required size. */
4746 *needed += spoolss_size_printer_info_1(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 smb_io_printer_info_1("", buffer, printer, 0);
4768 /****************************************************************************
4769 ****************************************************************************/
4771 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4773 PRINTER_INFO_2 *printer=NULL;
4774 WERROR result = WERR_OK;
4776 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4779 construct_printer_info_2(print_hnd, printer, snum);
4781 /* check the required size. */
4782 *needed += spoolss_size_printer_info_2(printer);
4784 if (*needed > offered) {
4785 result = WERR_INSUFFICIENT_BUFFER;
4789 if (!rpcbuf_alloc_size(buffer, *needed)) {
4790 result = WERR_NOMEM;
4794 /* fill the buffer with the structures */
4795 if (!smb_io_printer_info_2("", buffer, printer, 0))
4796 result = WERR_NOMEM;
4800 free_printer_info_2(printer);
4805 /****************************************************************************
4806 ****************************************************************************/
4808 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4810 PRINTER_INFO_3 *printer=NULL;
4811 WERROR result = WERR_OK;
4813 if (!construct_printer_info_3(print_hnd, &printer, snum))
4816 /* check the required size. */
4817 *needed += spoolss_size_printer_info_3(printer);
4819 if (*needed > offered) {
4820 result = WERR_INSUFFICIENT_BUFFER;
4824 if (!rpcbuf_alloc_size(buffer, *needed)) {
4825 result = WERR_NOMEM;
4829 /* fill the buffer with the structures */
4830 smb_io_printer_info_3("", buffer, printer, 0);
4834 free_printer_info_3(printer);
4839 /****************************************************************************
4840 ****************************************************************************/
4842 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4844 PRINTER_INFO_4 *printer=NULL;
4845 WERROR result = WERR_OK;
4847 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4850 if (!construct_printer_info_4(print_hnd, printer, snum))
4853 /* check the required size. */
4854 *needed += spoolss_size_printer_info_4(printer);
4856 if (*needed > offered) {
4857 result = WERR_INSUFFICIENT_BUFFER;
4861 if (!rpcbuf_alloc_size(buffer, *needed)) {
4862 result = WERR_NOMEM;
4866 /* fill the buffer with the structures */
4867 smb_io_printer_info_4("", buffer, printer, 0);
4871 free_printer_info_4(printer);
4876 /****************************************************************************
4877 ****************************************************************************/
4879 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4881 PRINTER_INFO_5 *printer=NULL;
4882 WERROR result = WERR_OK;
4884 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4887 if (!construct_printer_info_5(print_hnd, printer, snum))
4890 /* check the required size. */
4891 *needed += spoolss_size_printer_info_5(printer);
4893 if (*needed > offered) {
4894 result = WERR_INSUFFICIENT_BUFFER;
4898 if (!rpcbuf_alloc_size(buffer, *needed)) {
4899 result = WERR_NOMEM;
4903 /* fill the buffer with the structures */
4904 smb_io_printer_info_5("", buffer, printer, 0);
4908 free_printer_info_5(printer);
4913 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4915 PRINTER_INFO_7 *printer=NULL;
4916 WERROR result = WERR_OK;
4918 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4921 if (!construct_printer_info_7(print_hnd, printer, snum))
4924 /* check the required size. */
4925 *needed += spoolss_size_printer_info_7(printer);
4927 if (*needed > offered) {
4928 result = WERR_INSUFFICIENT_BUFFER;
4932 if (!rpcbuf_alloc_size(buffer, *needed)) {
4933 result = WERR_NOMEM;
4938 /* fill the buffer with the structures */
4939 smb_io_printer_info_7("", buffer, printer, 0);
4943 free_printer_info_7(printer);
4948 /****************************************************************************
4949 ****************************************************************************/
4951 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4953 POLICY_HND *handle = &q_u->handle;
4954 uint32 level = q_u->level;
4955 RPC_BUFFER *buffer = NULL;
4956 uint32 offered = q_u->offered;
4957 uint32 *needed = &r_u->needed;
4958 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4962 /* that's an [in out] buffer */
4964 if ( q_u->buffer ) {
4965 rpcbuf_move(q_u->buffer, &r_u->buffer);
4966 buffer = r_u->buffer;
4971 if (!get_printer_snum(p, handle, &snum))
4976 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4978 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4980 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4982 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4984 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4986 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4988 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4990 return WERR_UNKNOWN_LEVEL;
4993 /********************************************************************
4994 * fill a DRIVER_INFO_1 struct
4995 ********************************************************************/
4997 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4999 init_unistr( &info->name, driver.info_3->name);
5002 /********************************************************************
5003 * construct_printer_driver_info_1
5004 ********************************************************************/
5006 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5008 NT_PRINTER_INFO_LEVEL *printer = NULL;
5009 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5011 ZERO_STRUCT(driver);
5013 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5014 return WERR_INVALID_PRINTER_NAME;
5016 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5017 return WERR_UNKNOWN_PRINTER_DRIVER;
5019 fill_printer_driver_info_1(info, driver, servername, architecture);
5021 free_a_printer(&printer,2);
5026 /********************************************************************
5027 * construct_printer_driver_info_2
5028 * fill a printer_info_2 struct
5029 ********************************************************************/
5031 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5035 info->version=driver.info_3->cversion;
5037 init_unistr( &info->name, driver.info_3->name );
5038 init_unistr( &info->architecture, driver.info_3->environment );
5041 if (strlen(driver.info_3->driverpath)) {
5042 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5043 init_unistr( &info->driverpath, temp );
5045 init_unistr( &info->driverpath, "" );
5047 if (strlen(driver.info_3->datafile)) {
5048 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5049 init_unistr( &info->datafile, temp );
5051 init_unistr( &info->datafile, "" );
5053 if (strlen(driver.info_3->configfile)) {
5054 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5055 init_unistr( &info->configfile, temp );
5057 init_unistr( &info->configfile, "" );
5060 /********************************************************************
5061 * construct_printer_driver_info_2
5062 * fill a printer_info_2 struct
5063 ********************************************************************/
5065 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5067 NT_PRINTER_INFO_LEVEL *printer = NULL;
5068 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5070 ZERO_STRUCT(printer);
5071 ZERO_STRUCT(driver);
5073 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5074 return WERR_INVALID_PRINTER_NAME;
5076 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5077 return WERR_UNKNOWN_PRINTER_DRIVER;
5079 fill_printer_driver_info_2(info, driver, servername);
5081 free_a_printer(&printer,2);
5086 /********************************************************************
5087 * copy a strings array and convert to UNICODE
5089 * convert an array of ascii string to a UNICODE string
5090 ********************************************************************/
5092 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5100 DEBUG(6,("init_unistr_array\n"));
5111 v = ""; /* hack to handle null lists */
5114 /* hack to allow this to be used in places other than when generating
5115 the list of dependent files */
5118 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5122 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5124 /* add one extra unit16 for the second terminating NULL */
5126 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5127 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5135 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5140 /* special case for ""; we need to add both NULL's here */
5142 (*uni_array)[j++]=0x0000;
5143 (*uni_array)[j]=0x0000;
5146 DEBUGADD(6,("last one:done\n"));
5148 /* return size of array in uint16's */
5153 /********************************************************************
5154 * construct_printer_info_3
5155 * fill a printer_info_3 struct
5156 ********************************************************************/
5158 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5164 info->version=driver.info_3->cversion;
5166 init_unistr( &info->name, driver.info_3->name );
5167 init_unistr( &info->architecture, driver.info_3->environment );
5169 if (strlen(driver.info_3->driverpath)) {
5170 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5171 init_unistr( &info->driverpath, temp );
5173 init_unistr( &info->driverpath, "" );
5175 if (strlen(driver.info_3->datafile)) {
5176 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5177 init_unistr( &info->datafile, temp );
5179 init_unistr( &info->datafile, "" );
5181 if (strlen(driver.info_3->configfile)) {
5182 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5183 init_unistr( &info->configfile, temp );
5185 init_unistr( &info->configfile, "" );
5187 if (strlen(driver.info_3->helpfile)) {
5188 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5189 init_unistr( &info->helpfile, temp );
5191 init_unistr( &info->helpfile, "" );
5193 init_unistr( &info->monitorname, driver.info_3->monitorname );
5194 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5196 info->dependentfiles=NULL;
5197 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5200 /********************************************************************
5201 * construct_printer_info_3
5202 * fill a printer_info_3 struct
5203 ********************************************************************/
5205 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5207 NT_PRINTER_INFO_LEVEL *printer = NULL;
5208 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5210 ZERO_STRUCT(driver);
5212 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5213 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5214 if (!W_ERROR_IS_OK(status))
5215 return WERR_INVALID_PRINTER_NAME;
5217 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5218 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5223 * I put this code in during testing. Helpful when commenting out the
5224 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5225 * as win2k always queries the driver using an infor level of 6.
5226 * I've left it in (but ifdef'd out) because I'll probably
5227 * use it in experimentation again in the future. --jerry 22/01/2002
5230 if (!W_ERROR_IS_OK(status)) {
5232 * Is this a W2k client ?
5235 /* Yes - try again with a WinNT driver. */
5237 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5238 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5242 if (!W_ERROR_IS_OK(status)) {
5243 free_a_printer(&printer,2);
5244 return WERR_UNKNOWN_PRINTER_DRIVER;
5252 fill_printer_driver_info_3(info, driver, servername);
5254 free_a_printer(&printer,2);
5259 /********************************************************************
5260 * construct_printer_info_6
5261 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5262 ********************************************************************/
5264 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5270 memset(&nullstr, '\0', sizeof(fstring));
5272 info->version=driver.info_3->cversion;
5274 init_unistr( &info->name, driver.info_3->name );
5275 init_unistr( &info->architecture, driver.info_3->environment );
5277 if (strlen(driver.info_3->driverpath)) {
5278 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5279 init_unistr( &info->driverpath, temp );
5281 init_unistr( &info->driverpath, "" );
5283 if (strlen(driver.info_3->datafile)) {
5284 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5285 init_unistr( &info->datafile, temp );
5287 init_unistr( &info->datafile, "" );
5289 if (strlen(driver.info_3->configfile)) {
5290 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5291 init_unistr( &info->configfile, temp );
5293 init_unistr( &info->configfile, "" );
5295 if (strlen(driver.info_3->helpfile)) {
5296 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5297 init_unistr( &info->helpfile, temp );
5299 init_unistr( &info->helpfile, "" );
5301 init_unistr( &info->monitorname, driver.info_3->monitorname );
5302 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5304 info->dependentfiles = NULL;
5305 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5307 info->previousdrivernames=NULL;
5308 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5310 info->driver_date.low=0;
5311 info->driver_date.high=0;
5314 info->driver_version_low=0;
5315 info->driver_version_high=0;
5317 init_unistr( &info->mfgname, "");
5318 init_unistr( &info->oem_url, "");
5319 init_unistr( &info->hardware_id, "");
5320 init_unistr( &info->provider, "");
5323 /********************************************************************
5324 * construct_printer_info_6
5325 * fill a printer_info_6 struct
5326 ********************************************************************/
5328 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5329 fstring servername, fstring architecture, uint32 version)
5331 NT_PRINTER_INFO_LEVEL *printer = NULL;
5332 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5335 ZERO_STRUCT(driver);
5337 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5339 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5341 if (!W_ERROR_IS_OK(status))
5342 return WERR_INVALID_PRINTER_NAME;
5344 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5346 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5348 if (!W_ERROR_IS_OK(status))
5351 * Is this a W2k client ?
5355 free_a_printer(&printer,2);
5356 return WERR_UNKNOWN_PRINTER_DRIVER;
5359 /* Yes - try again with a WinNT driver. */
5361 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5362 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5363 if (!W_ERROR_IS_OK(status)) {
5364 free_a_printer(&printer,2);
5365 return WERR_UNKNOWN_PRINTER_DRIVER;
5369 fill_printer_driver_info_6(info, driver, servername);
5371 free_a_printer(&printer,2);
5372 free_a_printer_driver(driver, 3);
5377 /****************************************************************************
5378 ****************************************************************************/
5380 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5382 SAFE_FREE(info->dependentfiles);
5385 /****************************************************************************
5386 ****************************************************************************/
5388 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5390 SAFE_FREE(info->dependentfiles);
5393 /****************************************************************************
5394 ****************************************************************************/
5396 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5398 DRIVER_INFO_1 *info=NULL;
5401 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5404 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5405 if (!W_ERROR_IS_OK(result))
5408 /* check the required size. */
5409 *needed += spoolss_size_printer_driver_info_1(info);
5411 if (*needed > offered) {
5412 result = WERR_INSUFFICIENT_BUFFER;
5416 if (!rpcbuf_alloc_size(buffer, *needed)) {
5417 result = WERR_NOMEM;
5421 /* fill the buffer with the structures */
5422 smb_io_printer_driver_info_1("", buffer, info, 0);
5431 /****************************************************************************
5432 ****************************************************************************/
5434 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5436 DRIVER_INFO_2 *info=NULL;
5439 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5442 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5443 if (!W_ERROR_IS_OK(result))
5446 /* check the required size. */
5447 *needed += spoolss_size_printer_driver_info_2(info);
5449 if (*needed > offered) {
5450 result = WERR_INSUFFICIENT_BUFFER;
5454 if (!rpcbuf_alloc_size(buffer, *needed)) {
5455 result = WERR_NOMEM;
5459 /* fill the buffer with the structures */
5460 smb_io_printer_driver_info_2("", buffer, info, 0);
5469 /****************************************************************************
5470 ****************************************************************************/
5472 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5479 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5480 if (!W_ERROR_IS_OK(result))
5483 /* check the required size. */
5484 *needed += spoolss_size_printer_driver_info_3(&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_3("", buffer, &info, 0);
5500 free_printer_driver_info_3(&info);
5505 /****************************************************************************
5506 ****************************************************************************/
5508 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5515 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5516 if (!W_ERROR_IS_OK(result))
5519 /* check the required size. */
5520 *needed += spoolss_size_printer_driver_info_6(&info);
5522 if (*needed > offered) {
5523 result = WERR_INSUFFICIENT_BUFFER;
5527 if (!rpcbuf_alloc_size(buffer, *needed)) {
5528 result = WERR_NOMEM;
5532 /* fill the buffer with the structures */
5533 smb_io_printer_driver_info_6("", buffer, &info, 0);
5536 free_printer_driver_info_6(&info);
5541 /****************************************************************************
5542 ****************************************************************************/
5544 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5546 POLICY_HND *handle = &q_u->handle;
5547 UNISTR2 *uni_arch = &q_u->architecture;
5548 uint32 level = q_u->level;
5549 uint32 clientmajorversion = q_u->clientmajorversion;
5550 RPC_BUFFER *buffer = NULL;
5551 uint32 offered = q_u->offered;
5552 uint32 *needed = &r_u->needed;
5553 uint32 *servermajorversion = &r_u->servermajorversion;
5554 uint32 *serverminorversion = &r_u->serverminorversion;
5555 Printer_entry *printer;
5558 fstring architecture;
5561 /* that's an [in out] buffer */
5563 if ( q_u->buffer ) {
5564 rpcbuf_move(q_u->buffer, &r_u->buffer);
5565 buffer = r_u->buffer;
5568 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5570 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5571 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5572 return WERR_INVALID_PRINTER_NAME;
5576 *servermajorversion = 0;
5577 *serverminorversion = 0;
5579 fstrcpy(servername, get_server_name( printer ));
5580 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5582 if (!get_printer_snum(p, handle, &snum))
5587 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5589 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5591 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5593 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5596 /* apparently this call is the equivalent of
5597 EnumPrinterDataEx() for the DsDriver key */
5602 return WERR_UNKNOWN_LEVEL;
5605 /****************************************************************************
5606 ****************************************************************************/
5608 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5610 POLICY_HND *handle = &q_u->handle;
5612 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5615 DEBUG(3,("Error in startpageprinter printer handle\n"));
5619 Printer->page_started=True;
5623 /****************************************************************************
5624 ****************************************************************************/
5626 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5628 POLICY_HND *handle = &q_u->handle;
5631 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5634 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5638 if (!get_printer_snum(p, handle, &snum))
5641 Printer->page_started=False;
5642 print_job_endpage(snum, Printer->jobid);
5647 /********************************************************************
5648 * api_spoolss_getprinter
5649 * called from the spoolss dispatcher
5651 ********************************************************************/
5653 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5655 POLICY_HND *handle = &q_u->handle;
5656 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5657 uint32 *jobid = &r_u->jobid;
5659 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5663 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5664 struct current_user user;
5667 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5671 get_current_user(&user, p);
5674 * a nice thing with NT is it doesn't listen to what you tell it.
5675 * when asked to send _only_ RAW datas, it tries to send datas
5678 * So I add checks like in NT Server ...
5681 if (info_1->p_datatype != 0) {
5682 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5683 if (strcmp(datatype, "RAW") != 0) {
5685 return WERR_INVALID_DATATYPE;
5689 /* get the share number of the printer */
5690 if (!get_printer_snum(p, handle, &snum)) {
5694 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5696 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5698 /* An error occured in print_job_start() so return an appropriate
5701 if (Printer->jobid == -1) {
5702 return map_werror_from_unix(errno);
5705 Printer->document_started=True;
5706 (*jobid) = Printer->jobid;
5711 /********************************************************************
5712 * api_spoolss_getprinter
5713 * called from the spoolss dispatcher
5715 ********************************************************************/
5717 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5719 POLICY_HND *handle = &q_u->handle;
5721 return _spoolss_enddocprinter_internal(p, handle);
5724 /****************************************************************************
5725 ****************************************************************************/
5727 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5729 POLICY_HND *handle = &q_u->handle;
5730 uint32 buffer_size = q_u->buffer_size;
5731 uint8 *buffer = q_u->buffer;
5732 uint32 *buffer_written = &q_u->buffer_size2;
5734 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5737 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5738 r_u->buffer_written = q_u->buffer_size2;
5742 if (!get_printer_snum(p, handle, &snum))
5745 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5746 (SMB_OFF_T)-1, (size_t)buffer_size);
5747 if (*buffer_written == (uint32)-1) {
5748 r_u->buffer_written = 0;
5749 if (errno == ENOSPC)
5750 return WERR_NO_SPOOL_SPACE;
5752 return WERR_ACCESS_DENIED;
5755 r_u->buffer_written = q_u->buffer_size2;
5760 /********************************************************************
5761 * api_spoolss_getprinter
5762 * called from the spoolss dispatcher
5764 ********************************************************************/
5766 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5769 struct current_user user;
5771 WERROR errcode = WERR_BADFUNC;
5772 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5774 get_current_user(&user, p);
5777 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5781 if (!get_printer_snum(p, handle, &snum))
5785 case PRINTER_CONTROL_PAUSE:
5786 if (print_queue_pause(&user, snum, &errcode)) {
5790 case PRINTER_CONTROL_RESUME:
5791 case PRINTER_CONTROL_UNPAUSE:
5792 if (print_queue_resume(&user, snum, &errcode)) {
5796 case PRINTER_CONTROL_PURGE:
5797 if (print_queue_purge(&user, snum, &errcode)) {
5802 return WERR_UNKNOWN_LEVEL;
5808 /********************************************************************
5809 * api_spoolss_abortprinter
5810 * From MSDN: "Deletes printer's spool file if printer is configured
5812 ********************************************************************/
5814 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5816 POLICY_HND *handle = &q_u->handle;
5817 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5819 struct current_user user;
5820 WERROR errcode = WERR_OK;
5823 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5827 if (!get_printer_snum(p, handle, &snum))
5830 get_current_user( &user, p );
5832 print_job_delete( &user, snum, Printer->jobid, &errcode );
5837 /********************************************************************
5838 * called by spoolss_api_setprinter
5839 * when updating a printer description
5840 ********************************************************************/
5842 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5843 const SPOOL_PRINTER_INFO_LEVEL *info,
5844 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5846 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5850 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5852 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5853 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5854 OUR_HANDLE(handle)));
5856 result = WERR_BADFID;
5860 /* Check the user has permissions to change the security
5861 descriptor. By experimentation with two NT machines, the user
5862 requires Full Access to the printer to change security
5865 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5866 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5867 result = WERR_ACCESS_DENIED;
5871 /* NT seems to like setting the security descriptor even though
5872 nothing may have actually changed. */
5874 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5876 if (DEBUGLEVEL >= 10) {
5880 the_acl = old_secdesc_ctr->sec->dacl;
5881 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5882 PRINTERNAME(snum), the_acl->num_aces));
5884 for (i = 0; i < the_acl->num_aces; i++) {
5887 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5889 DEBUG(10, ("%s 0x%08x\n", sid_str,
5890 the_acl->ace[i].info.mask));
5893 the_acl = secdesc_ctr->sec->dacl;
5896 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5897 PRINTERNAME(snum), the_acl->num_aces));
5899 for (i = 0; i < the_acl->num_aces; i++) {
5902 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5904 DEBUG(10, ("%s 0x%08x\n", sid_str,
5905 the_acl->ace[i].info.mask));
5908 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5912 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5914 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5919 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5926 /********************************************************************
5927 Canonicalize printer info from a client
5929 ATTN: It does not matter what we set the servername to hear
5930 since we do the necessary work in get_a_printer() to set it to
5931 the correct value based on what the client sent in the
5932 _spoolss_open_printer_ex().
5933 ********************************************************************/
5935 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5937 fstring printername;
5940 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5941 "portname=%s drivername=%s comment=%s location=%s\n",
5942 info->servername, info->printername, info->sharename,
5943 info->portname, info->drivername, info->comment, info->location));
5945 /* we force some elements to "correct" values */
5946 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5947 fstrcpy(info->sharename, lp_servicename(snum));
5949 /* check to see if we allow printername != sharename */
5951 if ( lp_force_printername(snum) ) {
5952 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5953 global_myname(), info->sharename );
5956 /* make sure printername is in \\server\printername format */
5958 fstrcpy( printername, info->printername );
5960 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5961 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5965 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5966 global_myname(), p );
5969 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5970 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5977 /****************************************************************************
5978 ****************************************************************************/
5980 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5982 char *cmd = lp_addprinter_cmd();
5988 fstring remote_machine = "%m";
5989 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5990 BOOL is_print_op = False;
5992 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5994 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5995 cmd, printer->info_2->printername, printer->info_2->sharename,
5996 printer->info_2->portname, printer->info_2->drivername,
5997 printer->info_2->location, printer->info_2->comment, remote_machine);
6000 is_print_op = user_has_privileges( token, &se_printop );
6002 DEBUG(10,("Running [%s]\n", command));
6004 /********* BEGIN SePrintOperatorPrivilege **********/
6009 if ( (ret = smbrun(command, &fd)) == 0 ) {
6010 /* Tell everyone we updated smb.conf. */
6011 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6017 /********* END SePrintOperatorPrivilege **********/
6019 DEBUGADD(10,("returned [%d]\n", ret));
6027 /* reload our services immediately */
6028 reload_services( False );
6031 /* Get lines and convert them back to dos-codepage */
6032 qlines = fd_lines_load(fd, &numlines);
6033 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6036 /* Set the portname to what the script says the portname should be. */
6037 /* but don't require anything to be return from the script exit a good error code */
6040 /* Set the portname to what the script says the portname should be. */
6041 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6042 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6045 file_lines_free(qlines);
6049 /********************************************************************
6050 * Called by spoolss_api_setprinter
6051 * when updating a printer description.
6052 ********************************************************************/
6054 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6055 const SPOOL_PRINTER_INFO_LEVEL *info,
6056 DEVICEMODE *devmode)
6059 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6060 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6065 DEBUG(8,("update_printer\n"));
6070 result = WERR_BADFID;
6074 if (!get_printer_snum(p, handle, &snum)) {
6075 result = WERR_BADFID;
6079 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6080 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6081 result = WERR_BADFID;
6085 DEBUGADD(8,("Converting info_2 struct\n"));
6088 * convert_printer_info converts the incoming
6089 * info from the client and overwrites the info
6090 * just read from the tdb in the pointer 'printer'.
6093 if (!convert_printer_info(info, printer, level)) {
6094 result = WERR_NOMEM;
6099 /* we have a valid devmode
6100 convert it and link it*/
6102 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6103 if (!convert_devicemode(printer->info_2->printername, devmode,
6104 &printer->info_2->devmode)) {
6105 result = WERR_NOMEM;
6110 /* Do sanity check on the requested changes for Samba */
6112 if (!check_printer_ok(printer->info_2, snum)) {
6113 result = WERR_INVALID_PARAM;
6117 /* FIXME!!! If the driver has changed we really should verify that
6118 it is installed before doing much else --jerry */
6120 /* Check calling user has permission to update printer description */
6122 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6123 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6124 result = WERR_ACCESS_DENIED;
6128 /* Call addprinter hook */
6129 /* Check changes to see if this is really needed */
6131 if ( *lp_addprinter_cmd()
6132 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6133 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6134 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6135 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6137 /* add_printer_hook() will call reload_services() */
6139 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6140 result = WERR_ACCESS_DENIED;
6146 * When a *new* driver is bound to a printer, the drivername is used to
6147 * lookup previously saved driver initialization info, which is then
6148 * bound to the printer, simulating what happens in the Windows arch.
6150 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6152 if (!set_driver_init(printer, 2))
6154 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6155 printer->info_2->drivername));
6158 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6159 printer->info_2->drivername));
6161 notify_printer_driver(snum, printer->info_2->drivername);
6165 * flag which changes actually occured. This is a small subset of
6166 * all the possible changes. We also have to update things in the
6170 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6171 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6172 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6173 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6175 notify_printer_comment(snum, printer->info_2->comment);
6178 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6179 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6180 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6181 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6183 notify_printer_sharename(snum, printer->info_2->sharename);
6186 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6189 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6192 pname = printer->info_2->printername;
6195 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6196 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6197 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6199 notify_printer_printername( snum, pname );
6202 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6203 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6204 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6205 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6207 notify_printer_port(snum, printer->info_2->portname);
6210 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6211 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6212 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6213 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6215 notify_printer_location(snum, printer->info_2->location);
6218 /* here we need to update some more DsSpooler keys */
6219 /* uNCName, serverName, shortServerName */
6221 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6222 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6223 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6224 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6225 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6227 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6228 global_myname(), printer->info_2->sharename );
6229 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6230 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6231 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6233 /* Update printer info */
6234 result = mod_a_printer(printer, 2);
6237 free_a_printer(&printer, 2);
6238 free_a_printer(&old_printer, 2);
6244 /****************************************************************************
6245 ****************************************************************************/
6246 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6247 const SPOOL_PRINTER_INFO_LEVEL *info)
6250 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6252 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6254 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6259 if (!get_printer_snum(p, handle, &snum))
6262 nt_printer_publish(Printer, snum, info7->action);
6266 return WERR_UNKNOWN_LEVEL;
6269 /****************************************************************************
6270 ****************************************************************************/
6272 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6274 POLICY_HND *handle = &q_u->handle;
6275 uint32 level = q_u->level;
6276 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6277 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6278 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6279 uint32 command = q_u->command;
6282 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6285 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6289 /* check the level */
6292 return control_printer(handle, command, p);
6294 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6295 if (!W_ERROR_IS_OK(result))
6298 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6301 return update_printer_sec(handle, level, info, p,
6304 return publish_or_unpublish_printer(p, handle, info);
6306 return WERR_UNKNOWN_LEVEL;
6310 /****************************************************************************
6311 ****************************************************************************/
6313 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6315 POLICY_HND *handle = &q_u->handle;
6316 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6319 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6323 if (Printer->notify.client_connected==True) {
6326 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6328 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6329 !get_printer_snum(p, handle, &snum) )
6332 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6335 Printer->notify.flags=0;
6336 Printer->notify.options=0;
6337 Printer->notify.localmachine[0]='\0';
6338 Printer->notify.printerlocal=0;
6339 if (Printer->notify.option)
6340 free_spool_notify_option(&Printer->notify.option);
6341 Printer->notify.client_connected=False;
6346 /****************************************************************************
6347 ****************************************************************************/
6349 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6351 /* that's an [in out] buffer */
6354 rpcbuf_move(q_u->buffer, &r_u->buffer);
6357 return WERR_INVALID_PARAM; /* this is what a NT server
6358 returns for AddJob. AddJob
6359 must fail on non-local
6363 /****************************************************************************
6364 ****************************************************************************/
6366 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6367 int position, int snum,
6368 NT_PRINTER_INFO_LEVEL *ntprinter)
6372 t=gmtime(&queue->time);
6374 job_info->jobid=queue->job;
6375 init_unistr(&job_info->printername, lp_servicename(snum));
6376 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6377 init_unistr(&job_info->username, queue->fs_user);
6378 init_unistr(&job_info->document, queue->fs_file);
6379 init_unistr(&job_info->datatype, "RAW");
6380 init_unistr(&job_info->text_status, "");
6381 job_info->status=nt_printj_status(queue->status);
6382 job_info->priority=queue->priority;
6383 job_info->position=position;
6384 job_info->totalpages=queue->page_count;
6385 job_info->pagesprinted=0;
6387 make_systemtime(&job_info->submitted, t);
6390 /****************************************************************************
6391 ****************************************************************************/
6393 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6394 int position, int snum,
6395 NT_PRINTER_INFO_LEVEL *ntprinter,
6396 DEVICEMODE *devmode)
6400 t=gmtime(&queue->time);
6402 job_info->jobid=queue->job;
6404 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6406 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6407 init_unistr(&job_info->username, queue->fs_user);
6408 init_unistr(&job_info->document, queue->fs_file);
6409 init_unistr(&job_info->notifyname, queue->fs_user);
6410 init_unistr(&job_info->datatype, "RAW");
6411 init_unistr(&job_info->printprocessor, "winprint");
6412 init_unistr(&job_info->parameters, "");
6413 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6414 init_unistr(&job_info->text_status, "");
6416 /* and here the security descriptor */
6418 job_info->status=nt_printj_status(queue->status);
6419 job_info->priority=queue->priority;
6420 job_info->position=position;
6421 job_info->starttime=0;
6422 job_info->untiltime=0;
6423 job_info->totalpages=queue->page_count;
6424 job_info->size=queue->size;
6425 make_systemtime(&(job_info->submitted), t);
6426 job_info->timeelapsed=0;
6427 job_info->pagesprinted=0;
6429 job_info->devmode = devmode;
6434 /****************************************************************************
6435 Enumjobs at level 1.
6436 ****************************************************************************/
6438 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6439 NT_PRINTER_INFO_LEVEL *ntprinter,
6440 RPC_BUFFER *buffer, uint32 offered,
6441 uint32 *needed, uint32 *returned)
6445 WERROR result = WERR_OK;
6447 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6454 for (i=0; i<*returned; i++)
6455 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6459 /* check the required size. */
6460 for (i=0; i<*returned; i++)
6461 (*needed) += spoolss_size_job_info_1(&info[i]);
6463 if (*needed > offered) {
6464 result = WERR_INSUFFICIENT_BUFFER;
6468 if (!rpcbuf_alloc_size(buffer, *needed)) {
6469 result = WERR_NOMEM;
6473 /* fill the buffer with the structures */
6474 for (i=0; i<*returned; i++)
6475 smb_io_job_info_1("", buffer, &info[i], 0);
6481 if ( !W_ERROR_IS_OK(result) )
6487 /****************************************************************************
6488 Enumjobs at level 2.
6489 ****************************************************************************/
6491 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6492 NT_PRINTER_INFO_LEVEL *ntprinter,
6493 RPC_BUFFER *buffer, uint32 offered,
6494 uint32 *needed, uint32 *returned)
6496 JOB_INFO_2 *info = NULL;
6498 WERROR result = WERR_OK;
6499 DEVICEMODE *devmode = NULL;
6501 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6506 /* this should not be a failure condition if the devmode is NULL */
6508 devmode = construct_dev_mode(snum);
6510 for (i=0; i<*returned; i++)
6511 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6513 free_a_printer(&ntprinter, 2);
6516 /* check the required size. */
6517 for (i=0; i<*returned; i++)
6518 (*needed) += spoolss_size_job_info_2(&info[i]);
6520 if (*needed > offered) {
6521 result = WERR_INSUFFICIENT_BUFFER;
6525 if (!rpcbuf_alloc_size(buffer, *needed)) {
6526 result = WERR_NOMEM;
6530 /* fill the buffer with the structures */
6531 for (i=0; i<*returned; i++)
6532 smb_io_job_info_2("", buffer, &info[i], 0);
6535 free_devmode(devmode);
6538 if ( !W_ERROR_IS_OK(result) )
6545 /****************************************************************************
6547 ****************************************************************************/
6549 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6551 POLICY_HND *handle = &q_u->handle;
6552 uint32 level = q_u->level;
6553 RPC_BUFFER *buffer = NULL;
6554 uint32 offered = q_u->offered;
6555 uint32 *needed = &r_u->needed;
6556 uint32 *returned = &r_u->returned;
6558 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6560 print_status_struct prt_status;
6561 print_queue_struct *queue=NULL;
6563 /* that's an [in out] buffer */
6565 if ( q_u->buffer ) {
6566 rpcbuf_move(q_u->buffer, &r_u->buffer);
6567 buffer = r_u->buffer;
6570 DEBUG(4,("_spoolss_enumjobs\n"));
6575 /* lookup the printer snum and tdb entry */
6577 if (!get_printer_snum(p, handle, &snum))
6580 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6581 if ( !W_ERROR_IS_OK(wret) )
6584 *returned = print_queue_status(snum, &queue, &prt_status);
6585 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6587 if (*returned == 0) {
6594 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6597 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6602 wret = WERR_UNKNOWN_LEVEL;
6605 free_a_printer( &ntprinter, 2 );
6609 /****************************************************************************
6610 ****************************************************************************/
6612 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6617 /****************************************************************************
6618 ****************************************************************************/
6620 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6622 POLICY_HND *handle = &q_u->handle;
6623 uint32 jobid = q_u->jobid;
6624 uint32 command = q_u->command;
6626 struct current_user user;
6628 WERROR errcode = WERR_BADFUNC;
6630 if (!get_printer_snum(p, handle, &snum)) {
6634 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6635 return WERR_INVALID_PRINTER_NAME;
6638 get_current_user(&user, p);
6641 case JOB_CONTROL_CANCEL:
6642 case JOB_CONTROL_DELETE:
6643 if (print_job_delete(&user, snum, jobid, &errcode)) {
6647 case JOB_CONTROL_PAUSE:
6648 if (print_job_pause(&user, snum, jobid, &errcode)) {
6652 case JOB_CONTROL_RESTART:
6653 case JOB_CONTROL_RESUME:
6654 if (print_job_resume(&user, snum, jobid, &errcode)) {
6659 return WERR_UNKNOWN_LEVEL;
6665 /****************************************************************************
6666 Enumerates all printer drivers at level 1.
6667 ****************************************************************************/
6669 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6674 fstring *list = NULL;
6675 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6676 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6677 WERROR result = WERR_OK;
6681 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6683 ndrivers=get_ntdrivers(&list, architecture, version);
6684 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6690 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6691 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6692 SAFE_FREE(driver_info_1);
6696 else driver_info_1 = tdi1;
6699 for (i=0; i<ndrivers; i++) {
6701 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6702 ZERO_STRUCT(driver);
6703 status = get_a_printer_driver(&driver, 3, list[i],
6704 architecture, version);
6705 if (!W_ERROR_IS_OK(status)) {
6709 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6710 free_a_printer_driver(driver, 3);
6713 *returned+=ndrivers;
6717 /* check the required size. */
6718 for (i=0; i<*returned; i++) {
6719 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6720 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6723 if (*needed > offered) {
6724 result = WERR_INSUFFICIENT_BUFFER;
6728 if (!rpcbuf_alloc_size(buffer, *needed)) {
6729 result = WERR_NOMEM;
6733 /* fill the buffer with the driver structures */
6734 for (i=0; i<*returned; i++) {
6735 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6736 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6740 SAFE_FREE(driver_info_1);
6742 if ( !W_ERROR_IS_OK(result) )
6748 /****************************************************************************
6749 Enumerates all printer drivers at level 2.
6750 ****************************************************************************/
6752 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6757 fstring *list = NULL;
6758 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6759 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6760 WERROR result = WERR_OK;
6764 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6766 ndrivers=get_ntdrivers(&list, architecture, version);
6767 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6773 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6774 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6775 SAFE_FREE(driver_info_2);
6779 else driver_info_2 = tdi2;
6782 for (i=0; i<ndrivers; i++) {
6785 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6786 ZERO_STRUCT(driver);
6787 status = get_a_printer_driver(&driver, 3, list[i],
6788 architecture, version);
6789 if (!W_ERROR_IS_OK(status)) {
6793 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6794 free_a_printer_driver(driver, 3);
6797 *returned+=ndrivers;
6801 /* check the required size. */
6802 for (i=0; i<*returned; i++) {
6803 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6804 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6807 if (*needed > offered) {
6808 result = WERR_INSUFFICIENT_BUFFER;
6812 if (!rpcbuf_alloc_size(buffer, *needed)) {
6813 result = WERR_NOMEM;
6817 /* fill the buffer with the form structures */
6818 for (i=0; i<*returned; i++) {
6819 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6820 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6824 SAFE_FREE(driver_info_2);
6826 if ( !W_ERROR_IS_OK(result) )
6832 /****************************************************************************
6833 Enumerates all printer drivers at level 3.
6834 ****************************************************************************/
6836 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6841 fstring *list = NULL;
6842 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6843 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6844 WERROR result = WERR_OK;
6848 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6850 ndrivers=get_ntdrivers(&list, architecture, version);
6851 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6857 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6858 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6859 SAFE_FREE(driver_info_3);
6863 else driver_info_3 = tdi3;
6866 for (i=0; i<ndrivers; i++) {
6869 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6870 ZERO_STRUCT(driver);
6871 status = get_a_printer_driver(&driver, 3, list[i],
6872 architecture, version);
6873 if (!W_ERROR_IS_OK(status)) {
6877 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6878 free_a_printer_driver(driver, 3);
6881 *returned+=ndrivers;
6885 /* check the required size. */
6886 for (i=0; i<*returned; i++) {
6887 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6888 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6891 if (*needed > offered) {
6892 result = WERR_INSUFFICIENT_BUFFER;
6896 if (!rpcbuf_alloc_size(buffer, *needed)) {
6897 result = WERR_NOMEM;
6901 /* fill the buffer with the driver structures */
6902 for (i=0; i<*returned; i++) {
6903 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6904 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6908 for (i=0; i<*returned; i++)
6909 SAFE_FREE(driver_info_3[i].dependentfiles);
6911 SAFE_FREE(driver_info_3);
6913 if ( !W_ERROR_IS_OK(result) )
6919 /****************************************************************************
6920 Enumerates all printer drivers.
6921 ****************************************************************************/
6923 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6925 uint32 level = q_u->level;
6926 RPC_BUFFER *buffer = NULL;
6927 uint32 offered = q_u->offered;
6928 uint32 *needed = &r_u->needed;
6929 uint32 *returned = &r_u->returned;
6932 fstring architecture;
6934 /* that's an [in out] buffer */
6936 if ( q_u->buffer ) {
6937 rpcbuf_move(q_u->buffer, &r_u->buffer);
6938 buffer = r_u->buffer;
6941 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6946 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6947 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6949 if ( !is_myname_or_ipaddr( servername ) )
6950 return WERR_UNKNOWN_PRINTER_DRIVER;
6954 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6956 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6958 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6960 return WERR_UNKNOWN_LEVEL;
6964 /****************************************************************************
6965 ****************************************************************************/
6967 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6969 form->flag=list->flag;
6970 init_unistr(&form->name, list->name);
6971 form->width=list->width;
6972 form->length=list->length;
6973 form->left=list->left;
6974 form->top=list->top;
6975 form->right=list->right;
6976 form->bottom=list->bottom;
6979 /****************************************************************************
6980 ****************************************************************************/
6982 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6984 uint32 level = q_u->level;
6985 RPC_BUFFER *buffer = NULL;
6986 uint32 offered = q_u->offered;
6987 uint32 *needed = &r_u->needed;
6988 uint32 *numofforms = &r_u->numofforms;
6989 uint32 numbuiltinforms;
6991 nt_forms_struct *list=NULL;
6992 nt_forms_struct *builtinlist=NULL;
6997 /* that's an [in out] buffer */
6999 if ( q_u->buffer ) {
7000 rpcbuf_move(q_u->buffer, &r_u->buffer);
7001 buffer = r_u->buffer;
7004 DEBUG(4,("_spoolss_enumforms\n"));
7005 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7006 DEBUGADD(5,("Info level [%d]\n", level));
7008 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7009 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7010 *numofforms = get_ntforms(&list);
7011 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7012 *numofforms += numbuiltinforms;
7014 if (*numofforms == 0)
7015 return WERR_NO_MORE_ITEMS;
7019 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7024 /* construct the list of form structures */
7025 for (i=0; i<numbuiltinforms; i++) {
7026 DEBUGADD(6,("Filling form number [%d]\n",i));
7027 fill_form_1(&forms_1[i], &builtinlist[i]);
7030 SAFE_FREE(builtinlist);
7032 for (; i<*numofforms; i++) {
7033 DEBUGADD(6,("Filling form number [%d]\n",i));
7034 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7039 /* check the required size. */
7040 for (i=0; i<numbuiltinforms; i++) {
7041 DEBUGADD(6,("adding form [%d]'s size\n",i));
7042 buffer_size += spoolss_size_form_1(&forms_1[i]);
7044 for (; i<*numofforms; i++) {
7045 DEBUGADD(6,("adding form [%d]'s size\n",i));
7046 buffer_size += spoolss_size_form_1(&forms_1[i]);
7049 *needed=buffer_size;
7051 if (*needed > offered) {
7054 return WERR_INSUFFICIENT_BUFFER;
7057 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7063 /* fill the buffer with the form structures */
7064 for (i=0; i<numbuiltinforms; i++) {
7065 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7066 smb_io_form_1("", buffer, &forms_1[i], 0);
7068 for (; i<*numofforms; i++) {
7069 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7070 smb_io_form_1("", buffer, &forms_1[i], 0);
7079 SAFE_FREE(builtinlist);
7080 return WERR_UNKNOWN_LEVEL;
7085 /****************************************************************************
7086 ****************************************************************************/
7088 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7090 uint32 level = q_u->level;
7091 UNISTR2 *uni_formname = &q_u->formname;
7092 RPC_BUFFER *buffer = NULL;
7093 uint32 offered = q_u->offered;
7094 uint32 *needed = &r_u->needed;
7096 nt_forms_struct *list=NULL;
7097 nt_forms_struct builtin_form;
7102 int numofforms=0, i=0;
7104 /* that's an [in out] buffer */
7106 if ( q_u->buffer ) {
7107 rpcbuf_move(q_u->buffer, &r_u->buffer);
7108 buffer = r_u->buffer;
7111 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7113 DEBUG(4,("_spoolss_getform\n"));
7114 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7115 DEBUGADD(5,("Info level [%d]\n", level));
7117 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7118 if (!foundBuiltin) {
7119 numofforms = get_ntforms(&list);
7120 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7122 if (numofforms == 0)
7129 fill_form_1(&form_1, &builtin_form);
7132 /* Check if the requested name is in the list of form structures */
7133 for (i=0; i<numofforms; i++) {
7135 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7137 if (strequal(form_name, list[i].name)) {
7138 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7139 fill_form_1(&form_1, &list[i]);
7145 if (i == numofforms) {
7149 /* check the required size. */
7151 *needed=spoolss_size_form_1(&form_1);
7153 if (*needed > offered)
7154 return WERR_INSUFFICIENT_BUFFER;
7156 if (!rpcbuf_alloc_size(buffer, buffer_size))
7159 /* fill the buffer with the form structures */
7160 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7161 smb_io_form_1("", buffer, &form_1, 0);
7167 return WERR_UNKNOWN_LEVEL;
7171 /****************************************************************************
7172 ****************************************************************************/
7174 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7176 init_unistr(&port->port_name, name);
7179 /****************************************************************************
7180 ****************************************************************************/
7182 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7184 init_unistr(&port->port_name, name);
7185 init_unistr(&port->monitor_name, "Local Monitor");
7186 init_unistr(&port->description, "Local Port");
7187 port->port_type=PORT_TYPE_WRITE;
7192 /****************************************************************************
7193 wrapper around the enumer ports command
7194 ****************************************************************************/
7196 WERROR enumports_hook( int *count, char ***lines )
7198 char *cmd = lp_enumports_cmd();
7206 /* if no hook then just fill in the default port */
7209 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7210 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7215 /* we have a valid enumport command */
7217 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7219 DEBUG(10,("Running [%s]\n", command));
7220 ret = smbrun(command, &fd);
7221 DEBUG(10,("Returned [%d]\n", ret));
7226 return WERR_ACCESS_DENIED;
7230 qlines = fd_lines_load(fd, &numlines);
7231 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7241 /****************************************************************************
7243 ****************************************************************************/
7245 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7247 PORT_INFO_1 *ports=NULL;
7249 WERROR result = WERR_OK;
7253 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7257 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7258 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7259 dos_errstr(WERR_NOMEM)));
7260 file_lines_free(qlines);
7264 for (i=0; i<numlines; i++) {
7265 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7266 fill_port_1(&ports[i], qlines[i]);
7269 file_lines_free(qlines);
7272 *returned = numlines;
7274 /* check the required size. */
7275 for (i=0; i<*returned; i++) {
7276 DEBUGADD(6,("adding port [%d]'s size\n", i));
7277 *needed += spoolss_size_port_info_1(&ports[i]);
7280 if (*needed > offered) {
7281 result = WERR_INSUFFICIENT_BUFFER;
7285 if (!rpcbuf_alloc_size(buffer, *needed)) {
7286 result = WERR_NOMEM;
7290 /* fill the buffer with the ports structures */
7291 for (i=0; i<*returned; i++) {
7292 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7293 smb_io_port_1("", buffer, &ports[i], 0);
7299 if ( !W_ERROR_IS_OK(result) )
7305 /****************************************************************************
7307 ****************************************************************************/
7309 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7311 PORT_INFO_2 *ports=NULL;
7313 WERROR result = WERR_OK;
7317 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7322 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7323 file_lines_free(qlines);
7327 for (i=0; i<numlines; i++) {
7328 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7329 fill_port_2(&(ports[i]), qlines[i]);
7332 file_lines_free(qlines);
7335 *returned = numlines;
7337 /* check the required size. */
7338 for (i=0; i<*returned; i++) {
7339 DEBUGADD(6,("adding port [%d]'s size\n", i));
7340 *needed += spoolss_size_port_info_2(&ports[i]);
7343 if (*needed > offered) {
7344 result = WERR_INSUFFICIENT_BUFFER;
7348 if (!rpcbuf_alloc_size(buffer, *needed)) {
7349 result = WERR_NOMEM;
7353 /* fill the buffer with the ports structures */
7354 for (i=0; i<*returned; i++) {
7355 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7356 smb_io_port_2("", buffer, &ports[i], 0);
7362 if ( !W_ERROR_IS_OK(result) )
7368 /****************************************************************************
7370 ****************************************************************************/
7372 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7374 uint32 level = q_u->level;
7375 RPC_BUFFER *buffer = NULL;
7376 uint32 offered = q_u->offered;
7377 uint32 *needed = &r_u->needed;
7378 uint32 *returned = &r_u->returned;
7380 /* that's an [in out] buffer */
7382 if ( q_u->buffer ) {
7383 rpcbuf_move(q_u->buffer, &r_u->buffer);
7384 buffer = r_u->buffer;
7387 DEBUG(4,("_spoolss_enumports\n"));
7394 return enumports_level_1(buffer, offered, needed, returned);
7396 return enumports_level_2(buffer, offered, needed, returned);
7398 return WERR_UNKNOWN_LEVEL;
7402 /****************************************************************************
7403 ****************************************************************************/
7405 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7406 const SPOOL_PRINTER_INFO_LEVEL *info,
7407 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7408 uint32 user_switch, const SPOOL_USER_CTR *user,
7411 NT_PRINTER_INFO_LEVEL *printer = NULL;
7414 WERROR err = WERR_OK;
7416 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7417 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7421 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7422 if (!convert_printer_info(info, printer, 2)) {
7423 free_a_printer(&printer, 2);
7427 /* check to see if the printer already exists */
7429 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7430 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7431 printer->info_2->sharename));
7432 free_a_printer(&printer, 2);
7433 return WERR_PRINTER_ALREADY_EXISTS;
7436 /* FIXME!!! smbd should check to see if the driver is installed before
7437 trying to add a printer like this --jerry */
7439 if (*lp_addprinter_cmd() ) {
7440 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7441 free_a_printer(&printer,2);
7442 return WERR_ACCESS_DENIED;
7445 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7446 "smb.conf parameter \"addprinter command\" is defined. This"
7447 "parameter must exist for this call to succeed\n",
7448 printer->info_2->sharename ));
7451 /* use our primary netbios name since get_a_printer() will convert
7452 it to what the client expects on a case by case basis */
7454 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7455 printer->info_2->sharename);
7458 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7459 free_a_printer(&printer,2);
7460 return WERR_ACCESS_DENIED;
7463 /* you must be a printer admin to add a new printer */
7464 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7465 free_a_printer(&printer,2);
7466 return WERR_ACCESS_DENIED;
7470 * Do sanity check on the requested changes for Samba.
7473 if (!check_printer_ok(printer->info_2, snum)) {
7474 free_a_printer(&printer,2);
7475 return WERR_INVALID_PARAM;
7479 * When a printer is created, the drivername bound to the printer is used
7480 * to lookup previously saved driver initialization info, which is then
7481 * bound to the new printer, simulating what happens in the Windows arch.
7486 set_driver_init(printer, 2);
7490 /* A valid devmode was included, convert and link it
7492 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7494 if (!convert_devicemode(printer->info_2->printername, devmode,
7495 &printer->info_2->devmode))
7499 /* write the ASCII on disk */
7500 err = mod_a_printer(printer, 2);
7501 if (!W_ERROR_IS_OK(err)) {
7502 free_a_printer(&printer,2);
7506 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7507 /* Handle open failed - remove addition. */
7508 del_a_printer(printer->info_2->sharename);
7509 free_a_printer(&printer,2);
7510 return WERR_ACCESS_DENIED;
7513 update_c_setprinter(False);
7514 free_a_printer(&printer,2);
7519 /****************************************************************************
7520 ****************************************************************************/
7522 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7524 UNISTR2 *uni_srv_name = q_u->server_name;
7525 uint32 level = q_u->level;
7526 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7527 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7528 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7529 uint32 user_switch = q_u->user_switch;
7530 SPOOL_USER_CTR *user = &q_u->user_ctr;
7531 POLICY_HND *handle = &r_u->handle;
7535 /* we don't handle yet */
7536 /* but I know what to do ... */
7537 return WERR_UNKNOWN_LEVEL;
7539 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7541 user_switch, user, handle);
7543 return WERR_UNKNOWN_LEVEL;
7547 /****************************************************************************
7548 ****************************************************************************/
7550 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7552 uint32 level = q_u->level;
7553 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7554 WERROR err = WERR_OK;
7555 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7556 struct current_user user;
7557 fstring driver_name;
7560 ZERO_STRUCT(driver);
7562 get_current_user(&user, p);
7564 if (!convert_printer_driver_info(info, &driver, level)) {
7569 DEBUG(5,("Cleaning driver's information\n"));
7570 err = clean_up_driver_struct(driver, level, &user);
7571 if (!W_ERROR_IS_OK(err))
7574 DEBUG(5,("Moving driver to final destination\n"));
7575 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7579 if (add_a_printer_driver(driver, level)!=0) {
7580 err = WERR_ACCESS_DENIED;
7584 /* BEGIN_ADMIN_LOG */
7587 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7588 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7589 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7592 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7593 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7594 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7600 * I think this is where he DrvUpgradePrinter() hook would be
7601 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7602 * server. Right now, we just need to send ourselves a message
7603 * to update each printer bound to this driver. --jerry
7606 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7607 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7612 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7613 * decide if the driver init data should be deleted. The rules are:
7614 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7615 * 2) delete init data only if there is no 2k/Xp driver
7616 * 3) always delete init data
7617 * The generalized rule is always use init data from the highest order driver.
7618 * It is necessary to follow the driver install by an initialization step to
7619 * finish off this process.
7622 version = driver.info_3->cversion;
7623 else if (level == 6)
7624 version = driver.info_6->version;
7629 * 9x printer driver - never delete init data
7632 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7637 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7638 * there is no 2k/Xp driver init data for this driver name.
7642 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7644 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7646 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7648 if (!del_driver_init(driver_name))
7649 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7652 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7654 free_a_printer_driver(driver1,3);
7655 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7662 * 2k or Xp printer driver - always delete init data
7665 if (!del_driver_init(driver_name))
7666 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7670 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7676 free_a_printer_driver(driver, level);
7680 /********************************************************************
7681 * spoolss_addprinterdriverex
7682 ********************************************************************/
7684 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7686 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7687 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7690 * we only support the semantics of AddPrinterDriver()
7691 * i.e. only copy files that are newer than existing ones
7694 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7695 return WERR_ACCESS_DENIED;
7697 ZERO_STRUCT(q_u_local);
7698 ZERO_STRUCT(r_u_local);
7700 /* just pass the information off to _spoolss_addprinterdriver() */
7701 q_u_local.server_name_ptr = q_u->server_name_ptr;
7702 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7703 q_u_local.level = q_u->level;
7704 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7706 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7709 /****************************************************************************
7710 ****************************************************************************/
7712 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7714 init_unistr(&info->name, name);
7717 /****************************************************************************
7718 ****************************************************************************/
7720 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7726 const char *short_archi;
7727 DRIVER_DIRECTORY_1 *info=NULL;
7728 WERROR result = WERR_OK;
7730 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7731 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7733 /* check for beginning double '\'s and that the server
7736 pservername = servername;
7737 if ( *pservername == '\\' && strlen(servername)>2 ) {
7741 if ( !is_myname_or_ipaddr( pservername ) )
7742 return WERR_INVALID_PARAM;
7744 if (!(short_archi = get_short_archi(long_archi)))
7745 return WERR_INVALID_ENVIRONMENT;
7747 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7750 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7752 DEBUG(4,("printer driver directory: [%s]\n", path));
7754 fill_driverdir_1(info, path);
7756 *needed += spoolss_size_driverdir_info_1(info);
7758 if (*needed > offered) {
7759 result = WERR_INSUFFICIENT_BUFFER;
7763 if (!rpcbuf_alloc_size(buffer, *needed)) {
7764 result = WERR_NOMEM;
7768 smb_io_driverdir_1("", buffer, info, 0);
7776 /****************************************************************************
7777 ****************************************************************************/
7779 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7781 UNISTR2 *name = &q_u->name;
7782 UNISTR2 *uni_environment = &q_u->environment;
7783 uint32 level = q_u->level;
7784 RPC_BUFFER *buffer = NULL;
7785 uint32 offered = q_u->offered;
7786 uint32 *needed = &r_u->needed;
7788 /* that's an [in out] buffer */
7790 if ( q_u->buffer ) {
7791 rpcbuf_move(q_u->buffer, &r_u->buffer);
7792 buffer = r_u->buffer;
7795 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7801 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7803 return WERR_UNKNOWN_LEVEL;
7807 /****************************************************************************
7808 ****************************************************************************/
7810 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7812 POLICY_HND *handle = &q_u->handle;
7813 uint32 idx = q_u->index;
7814 uint32 in_value_len = q_u->valuesize;
7815 uint32 in_data_len = q_u->datasize;
7816 uint32 *out_max_value_len = &r_u->valuesize;
7817 uint16 **out_value = &r_u->value;
7818 uint32 *out_value_len = &r_u->realvaluesize;
7819 uint32 *out_type = &r_u->type;
7820 uint32 *out_max_data_len = &r_u->datasize;
7821 uint8 **data_out = &r_u->data;
7822 uint32 *out_data_len = &r_u->realdatasize;
7824 NT_PRINTER_INFO_LEVEL *printer = NULL;
7826 uint32 biggest_valuesize;
7827 uint32 biggest_datasize;
7829 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7832 REGISTRY_VALUE *val = NULL;
7833 NT_PRINTER_DATA *p_data;
7834 int i, key_index, num_values;
7839 *out_max_data_len = 0;
7843 DEBUG(5,("spoolss_enumprinterdata\n"));
7846 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7850 if (!get_printer_snum(p,handle, &snum))
7853 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7854 if (!W_ERROR_IS_OK(result))
7857 p_data = printer->info_2->data;
7858 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7863 * The NT machine wants to know the biggest size of value and data
7865 * cf: MSDN EnumPrinterData remark section
7868 if ( !in_value_len && !in_data_len && (key_index != -1) )
7870 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7872 biggest_valuesize = 0;
7873 biggest_datasize = 0;
7875 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7877 for ( i=0; i<num_values; i++ )
7879 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7881 name_length = strlen(val->valuename);
7882 if ( strlen(val->valuename) > biggest_valuesize )
7883 biggest_valuesize = name_length;
7885 if ( val->size > biggest_datasize )
7886 biggest_datasize = val->size;
7888 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7892 /* the value is an UNICODE string but real_value_size is the length
7893 in bytes including the trailing 0 */
7895 *out_value_len = 2 * (1+biggest_valuesize);
7896 *out_data_len = biggest_datasize;
7898 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7904 * the value len is wrong in NT sp3
7905 * that's the number of bytes not the number of unicode chars
7908 if ( key_index != -1 )
7909 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7914 /* out_value should default to "" or else NT4 has
7915 problems unmarshalling the response */
7917 *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, "", in_value_len, 0);
7927 /* the data is counted in bytes */
7929 *out_max_data_len = in_data_len;
7930 *out_data_len = in_data_len;
7932 /* only allocate when given a non-zero 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;
7940 result = WERR_NO_MORE_ITEMS;
7946 * - counted in bytes in the request
7947 * - counted in UNICODE chars in the max reply
7948 * - counted in bytes in the real size
7950 * take a pause *before* coding not *during* coding
7954 *out_max_value_len=(in_value_len/sizeof(uint16));
7955 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7957 result = WERR_NOMEM;
7961 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7965 *out_type = regval_type( val );
7967 /* data - counted in bytes */
7969 *out_max_data_len = in_data_len;
7970 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7972 result = WERR_NOMEM;
7975 data_len = regval_size(val);
7977 memcpy( *data_out, regval_data_p(val), data_len );
7978 *out_data_len = data_len;
7982 free_a_printer(&printer, 2);
7986 /****************************************************************************
7987 ****************************************************************************/
7989 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7991 POLICY_HND *handle = &q_u->handle;
7992 UNISTR2 *value = &q_u->value;
7993 uint32 type = q_u->type;
7994 uint8 *data = q_u->data;
7995 uint32 real_len = q_u->real_len;
7997 NT_PRINTER_INFO_LEVEL *printer = NULL;
7999 WERROR status = WERR_OK;
8000 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8003 DEBUG(5,("spoolss_setprinterdata\n"));
8006 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8010 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8011 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8012 return WERR_INVALID_PARAM;
8015 if (!get_printer_snum(p,handle, &snum))
8019 * Access check : NT returns "access denied" if you make a
8020 * SetPrinterData call without the necessary privildge.
8021 * we were originally returning OK if nothing changed
8022 * which made Win2k issue **a lot** of SetPrinterData
8023 * when connecting to a printer --jerry
8026 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8028 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8029 status = WERR_ACCESS_DENIED;
8033 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8034 if (!W_ERROR_IS_OK(status))
8037 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8040 * When client side code sets a magic printer data key, detect it and save
8041 * the current printer data and the magic key's data (its the DEVMODE) for
8042 * future printer/driver initializations.
8044 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8046 /* Set devmode and printer initialization info */
8047 status = save_driver_init( printer, 2, data, real_len );
8049 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8053 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8054 type, data, real_len );
8055 if ( W_ERROR_IS_OK(status) )
8056 status = mod_a_printer(printer, 2);
8060 free_a_printer(&printer, 2);
8065 /****************************************************************************
8066 ****************************************************************************/
8068 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8070 POLICY_HND *handle = &q_u->handle;
8071 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8074 DEBUG(5,("_spoolss_resetprinter\n"));
8077 * All we do is to check to see if the handle and queue is valid.
8078 * This call really doesn't mean anything to us because we only
8079 * support RAW printing. --jerry
8083 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8087 if (!get_printer_snum(p,handle, &snum))
8091 /* blindly return success */
8096 /****************************************************************************
8097 ****************************************************************************/
8099 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8101 POLICY_HND *handle = &q_u->handle;
8102 UNISTR2 *value = &q_u->valuename;
8104 NT_PRINTER_INFO_LEVEL *printer = NULL;
8106 WERROR status = WERR_OK;
8107 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8110 DEBUG(5,("spoolss_deleteprinterdata\n"));
8113 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8117 if (!get_printer_snum(p, handle, &snum))
8120 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8121 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8122 return WERR_ACCESS_DENIED;
8125 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8126 if (!W_ERROR_IS_OK(status))
8129 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8131 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8133 if ( W_ERROR_IS_OK(status) )
8134 mod_a_printer( printer, 2 );
8136 free_a_printer(&printer, 2);
8141 /****************************************************************************
8142 ****************************************************************************/
8144 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8146 POLICY_HND *handle = &q_u->handle;
8147 FORM *form = &q_u->form;
8148 nt_forms_struct tmpForm;
8150 WERROR status = WERR_OK;
8151 NT_PRINTER_INFO_LEVEL *printer = NULL;
8154 nt_forms_struct *list=NULL;
8155 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8157 DEBUG(5,("spoolss_addform\n"));
8160 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8165 /* forms can be added on printer of on the print server handle */
8167 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8169 if (!get_printer_snum(p,handle, &snum))
8172 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8173 if (!W_ERROR_IS_OK(status))
8177 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8178 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8179 status = WERR_ACCESS_DENIED;
8183 /* can't add if builtin */
8185 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8186 status = WERR_ALREADY_EXISTS;
8190 count = get_ntforms(&list);
8192 if(!add_a_form(&list, form, &count)) {
8193 status = WERR_NOMEM;
8197 write_ntforms(&list, count);
8200 * ChangeID must always be set if this is a printer
8203 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8204 status = mod_a_printer(printer, 2);
8208 free_a_printer(&printer, 2);
8214 /****************************************************************************
8215 ****************************************************************************/
8217 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8219 POLICY_HND *handle = &q_u->handle;
8220 UNISTR2 *form_name = &q_u->name;
8221 nt_forms_struct tmpForm;
8223 nt_forms_struct *list=NULL;
8224 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8226 WERROR status = WERR_OK;
8227 NT_PRINTER_INFO_LEVEL *printer = NULL;
8229 DEBUG(5,("spoolss_deleteform\n"));
8232 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8236 /* forms can be deleted on printer of on the print server handle */
8238 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8240 if (!get_printer_snum(p,handle, &snum))
8243 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8244 if (!W_ERROR_IS_OK(status))
8248 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8249 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8250 status = WERR_ACCESS_DENIED;
8254 /* can't delete if builtin */
8256 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8257 status = WERR_INVALID_PARAM;
8261 count = get_ntforms(&list);
8263 if ( !delete_a_form(&list, form_name, &count, &status ))
8267 * ChangeID must always be set if this is a printer
8270 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8271 status = mod_a_printer(printer, 2);
8275 free_a_printer(&printer, 2);
8281 /****************************************************************************
8282 ****************************************************************************/
8284 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8286 POLICY_HND *handle = &q_u->handle;
8287 FORM *form = &q_u->form;
8288 nt_forms_struct tmpForm;
8290 WERROR status = WERR_OK;
8291 NT_PRINTER_INFO_LEVEL *printer = NULL;
8294 nt_forms_struct *list=NULL;
8295 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8297 DEBUG(5,("spoolss_setform\n"));
8300 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8304 /* forms can be modified on printer of on the print server handle */
8306 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8308 if (!get_printer_snum(p,handle, &snum))
8311 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8312 if (!W_ERROR_IS_OK(status))
8316 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8317 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8318 status = WERR_ACCESS_DENIED;
8322 /* can't set if builtin */
8323 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8324 status = WERR_INVALID_PARAM;
8328 count = get_ntforms(&list);
8329 update_a_form(&list, form, count);
8330 write_ntforms(&list, count);
8333 * ChangeID must always be set if this is a printer
8336 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8337 status = mod_a_printer(printer, 2);
8342 free_a_printer(&printer, 2);
8348 /****************************************************************************
8349 enumprintprocessors level 1.
8350 ****************************************************************************/
8352 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8354 PRINTPROCESSOR_1 *info_1=NULL;
8355 WERROR result = WERR_OK;
8357 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8362 init_unistr(&info_1->name, "winprint");
8364 *needed += spoolss_size_printprocessor_info_1(info_1);
8366 if (*needed > offered) {
8367 result = WERR_INSUFFICIENT_BUFFER;
8371 if (!rpcbuf_alloc_size(buffer, *needed)) {
8372 result = WERR_NOMEM;
8376 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8381 if ( !W_ERROR_IS_OK(result) )
8387 /****************************************************************************
8388 ****************************************************************************/
8390 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8392 uint32 level = q_u->level;
8393 RPC_BUFFER *buffer = NULL;
8394 uint32 offered = q_u->offered;
8395 uint32 *needed = &r_u->needed;
8396 uint32 *returned = &r_u->returned;
8398 /* that's an [in out] buffer */
8400 if ( q_u->buffer ) {
8401 rpcbuf_move(q_u->buffer, &r_u->buffer);
8402 buffer = r_u->buffer;
8405 DEBUG(5,("spoolss_enumprintprocessors\n"));
8408 * Enumerate the print processors ...
8410 * Just reply with "winprint", to keep NT happy
8411 * and I can use my nice printer checker.
8419 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8421 return WERR_UNKNOWN_LEVEL;
8425 /****************************************************************************
8426 enumprintprocdatatypes level 1.
8427 ****************************************************************************/
8429 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8431 PRINTPROCDATATYPE_1 *info_1=NULL;
8432 WERROR result = WERR_NOMEM;
8434 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8439 init_unistr(&info_1->name, "RAW");
8441 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8443 if (*needed > offered) {
8444 result = WERR_INSUFFICIENT_BUFFER;
8448 if (!rpcbuf_alloc_size(buffer, *needed)) {
8449 result = WERR_NOMEM;
8453 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8458 if ( !W_ERROR_IS_OK(result) )
8464 /****************************************************************************
8465 ****************************************************************************/
8467 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8469 uint32 level = q_u->level;
8470 RPC_BUFFER *buffer = NULL;
8471 uint32 offered = q_u->offered;
8472 uint32 *needed = &r_u->needed;
8473 uint32 *returned = &r_u->returned;
8475 /* that's an [in out] buffer */
8477 if ( q_u->buffer ) {
8478 rpcbuf_move(q_u->buffer, &r_u->buffer);
8479 buffer = r_u->buffer;
8482 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8489 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8491 return WERR_UNKNOWN_LEVEL;
8495 /****************************************************************************
8496 enumprintmonitors level 1.
8497 ****************************************************************************/
8499 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8501 PRINTMONITOR_1 *info_1=NULL;
8502 WERROR result = WERR_OK;
8504 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8509 init_unistr(&info_1->name, "Local Port");
8511 *needed += spoolss_size_printmonitor_info_1(info_1);
8513 if (*needed > offered) {
8514 result = WERR_INSUFFICIENT_BUFFER;
8518 if (!rpcbuf_alloc_size(buffer, *needed)) {
8519 result = WERR_NOMEM;
8523 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8528 if ( !W_ERROR_IS_OK(result) )
8534 /****************************************************************************
8535 enumprintmonitors level 2.
8536 ****************************************************************************/
8538 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8540 PRINTMONITOR_2 *info_2=NULL;
8541 WERROR result = WERR_OK;
8543 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8548 init_unistr(&info_2->name, "Local Port");
8549 init_unistr(&info_2->environment, "Windows NT X86");
8550 init_unistr(&info_2->dll_name, "localmon.dll");
8552 *needed += spoolss_size_printmonitor_info_2(info_2);
8554 if (*needed > offered) {
8555 result = WERR_INSUFFICIENT_BUFFER;
8559 if (!rpcbuf_alloc_size(buffer, *needed)) {
8560 result = WERR_NOMEM;
8564 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8569 if ( !W_ERROR_IS_OK(result) )
8575 /****************************************************************************
8576 ****************************************************************************/
8578 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8580 uint32 level = q_u->level;
8581 RPC_BUFFER *buffer = NULL;
8582 uint32 offered = q_u->offered;
8583 uint32 *needed = &r_u->needed;
8584 uint32 *returned = &r_u->returned;
8586 /* that's an [in out] buffer */
8588 if ( q_u->buffer ) {
8589 rpcbuf_move(q_u->buffer, &r_u->buffer);
8590 buffer = r_u->buffer;
8593 DEBUG(5,("spoolss_enumprintmonitors\n"));
8596 * Enumerate the print monitors ...
8598 * Just reply with "Local Port", to keep NT happy
8599 * and I can use my nice printer checker.
8607 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8609 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8611 return WERR_UNKNOWN_LEVEL;
8615 /****************************************************************************
8616 ****************************************************************************/
8618 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8619 NT_PRINTER_INFO_LEVEL *ntprinter,
8620 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8625 JOB_INFO_1 *info_1=NULL;
8626 WERROR result = WERR_OK;
8628 info_1=SMB_MALLOC_P(JOB_INFO_1);
8630 if (info_1 == NULL) {
8634 for (i=0; i<count && found==False; i++) {
8635 if ((*queue)[i].job==(int)jobid)
8641 /* NT treats not found as bad param... yet another bad choice */
8642 return WERR_INVALID_PARAM;
8645 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8647 *needed += spoolss_size_job_info_1(info_1);
8649 if (*needed > offered) {
8650 result = WERR_INSUFFICIENT_BUFFER;
8654 if (!rpcbuf_alloc_size(buffer, *needed)) {
8655 result = WERR_NOMEM;
8659 smb_io_job_info_1("", buffer, info_1, 0);
8667 /****************************************************************************
8668 ****************************************************************************/
8670 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8671 NT_PRINTER_INFO_LEVEL *ntprinter,
8672 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8679 DEVICEMODE *devmode = NULL;
8680 NT_DEVICEMODE *nt_devmode = NULL;
8682 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8685 ZERO_STRUCTP(info_2);
8687 for ( i=0; i<count && found==False; i++ )
8689 if ((*queue)[i].job == (int)jobid)
8694 /* NT treats not found as bad param... yet another bad
8696 result = WERR_INVALID_PARAM;
8701 * if the print job does not have a DEVMODE associated with it,
8702 * just use the one for the printer. A NULL devicemode is not
8703 * a failure condition
8706 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8707 devmode = construct_dev_mode(snum);
8709 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8710 ZERO_STRUCTP( devmode );
8711 convert_nt_devicemode( devmode, nt_devmode );
8715 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8717 *needed += spoolss_size_job_info_2(info_2);
8719 if (*needed > offered) {
8720 result = WERR_INSUFFICIENT_BUFFER;
8724 if (!rpcbuf_alloc_size(buffer, *needed)) {
8725 result = WERR_NOMEM;
8729 smb_io_job_info_2("", buffer, info_2, 0);
8734 /* Cleanup allocated memory */
8736 free_job_info_2(info_2); /* Also frees devmode */
8742 /****************************************************************************
8743 ****************************************************************************/
8745 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8747 POLICY_HND *handle = &q_u->handle;
8748 uint32 jobid = q_u->jobid;
8749 uint32 level = q_u->level;
8750 RPC_BUFFER *buffer = NULL;
8751 uint32 offered = q_u->offered;
8752 uint32 *needed = &r_u->needed;
8753 WERROR wstatus = WERR_OK;
8754 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8757 print_queue_struct *queue = NULL;
8758 print_status_struct prt_status;
8760 /* that's an [in out] buffer */
8762 if ( q_u->buffer ) {
8763 rpcbuf_move(q_u->buffer, &r_u->buffer);
8764 buffer = r_u->buffer;
8767 DEBUG(5,("spoolss_getjob\n"));
8771 if (!get_printer_snum(p, handle, &snum))
8774 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8775 if ( !W_ERROR_IS_OK(wstatus) )
8778 count = print_queue_status(snum, &queue, &prt_status);
8780 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8781 count, prt_status.status, prt_status.message));
8785 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8786 buffer, offered, needed);
8789 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8790 buffer, offered, needed);
8793 wstatus = WERR_UNKNOWN_LEVEL;
8798 free_a_printer( &ntprinter, 2 );
8803 /********************************************************************
8804 spoolss_getprinterdataex
8806 From MSDN documentation of GetPrinterDataEx: pass request
8807 to GetPrinterData if key is "PrinterDriverData".
8808 ********************************************************************/
8810 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8812 POLICY_HND *handle = &q_u->handle;
8813 uint32 in_size = q_u->size;
8814 uint32 *type = &r_u->type;
8815 uint32 *out_size = &r_u->size;
8816 uint8 **data = &r_u->data;
8817 uint32 *needed = &r_u->needed;
8818 fstring keyname, valuename;
8820 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8822 NT_PRINTER_INFO_LEVEL *printer = NULL;
8824 WERROR status = WERR_OK;
8826 DEBUG(4,("_spoolss_getprinterdataex\n"));
8828 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8829 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8831 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8832 keyname, valuename));
8834 /* in case of problem, return some default values */
8838 *out_size = in_size;
8841 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8842 status = WERR_BADFID;
8846 /* Is the handle to a printer or to the server? */
8848 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8849 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8850 status = WERR_INVALID_PARAM;
8854 if ( !get_printer_snum(p,handle, &snum) )
8857 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8858 if ( !W_ERROR_IS_OK(status) )
8861 /* check to see if the keyname is valid */
8862 if ( !strlen(keyname) ) {
8863 status = WERR_INVALID_PARAM;
8867 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8868 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8869 free_a_printer( &printer, 2 );
8870 status = WERR_BADFILE;
8874 /* When given a new keyname, we should just create it */
8876 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8878 if (*needed > *out_size)
8879 status = WERR_MORE_DATA;
8882 if ( !W_ERROR_IS_OK(status) )
8884 DEBUG(5, ("error: allocating %d\n", *out_size));
8886 /* reply this param doesn't exist */
8890 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8891 status = WERR_NOMEM;
8901 free_a_printer( &printer, 2 );
8906 /********************************************************************
8907 * spoolss_setprinterdataex
8908 ********************************************************************/
8910 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8912 POLICY_HND *handle = &q_u->handle;
8913 uint32 type = q_u->type;
8914 uint8 *data = q_u->data;
8915 uint32 real_len = q_u->real_len;
8917 NT_PRINTER_INFO_LEVEL *printer = NULL;
8919 WERROR status = WERR_OK;
8920 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8925 DEBUG(4,("_spoolss_setprinterdataex\n"));
8927 /* From MSDN documentation of SetPrinterDataEx: pass request to
8928 SetPrinterData if key is "PrinterDriverData" */
8931 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8935 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8936 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8937 return WERR_INVALID_PARAM;
8940 if ( !get_printer_snum(p,handle, &snum) )
8944 * Access check : NT returns "access denied" if you make a
8945 * SetPrinterData call without the necessary privildge.
8946 * we were originally returning OK if nothing changed
8947 * which made Win2k issue **a lot** of SetPrinterData
8948 * when connecting to a printer --jerry
8951 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8953 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8954 return WERR_ACCESS_DENIED;
8957 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8958 if (!W_ERROR_IS_OK(status))
8961 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8962 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8964 /* check for OID in valuename */
8966 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8972 /* save the registry data */
8974 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8976 if ( W_ERROR_IS_OK(status) )
8978 /* save the OID if one was specified */
8980 fstrcat( keyname, "\\" );
8981 fstrcat( keyname, SPOOL_OID_KEY );
8984 * I'm not checking the status here on purpose. Don't know
8985 * if this is right, but I'm returning the status from the
8986 * previous set_printer_dataex() call. I have no idea if
8987 * this is right. --jerry
8990 set_printer_dataex( printer, keyname, valuename,
8991 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8994 status = mod_a_printer(printer, 2);
8997 free_a_printer(&printer, 2);
9003 /********************************************************************
9004 * spoolss_deleteprinterdataex
9005 ********************************************************************/
9007 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9009 POLICY_HND *handle = &q_u->handle;
9010 UNISTR2 *value = &q_u->valuename;
9011 UNISTR2 *key = &q_u->keyname;
9013 NT_PRINTER_INFO_LEVEL *printer = NULL;
9015 WERROR status = WERR_OK;
9016 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9017 pstring valuename, keyname;
9019 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9022 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9026 if (!get_printer_snum(p, handle, &snum))
9029 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9030 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9031 return WERR_ACCESS_DENIED;
9034 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9035 if (!W_ERROR_IS_OK(status))
9038 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9039 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9041 status = delete_printer_dataex( printer, keyname, valuename );
9043 if ( W_ERROR_IS_OK(status) )
9044 mod_a_printer( printer, 2 );
9046 free_a_printer(&printer, 2);
9051 /********************************************************************
9052 * spoolss_enumprinterkey
9053 ********************************************************************/
9056 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9059 fstring *keynames = NULL;
9060 uint16 *enumkeys = NULL;
9063 POLICY_HND *handle = &q_u->handle;
9064 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9065 NT_PRINTER_DATA *data;
9066 NT_PRINTER_INFO_LEVEL *printer = NULL;
9068 WERROR status = WERR_BADFILE;
9071 DEBUG(4,("_spoolss_enumprinterkey\n"));
9074 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9078 if ( !get_printer_snum(p,handle, &snum) )
9081 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9082 if (!W_ERROR_IS_OK(status))
9085 /* get the list of subkey names */
9087 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9088 data = printer->info_2->data;
9090 num_keys = get_printer_subkeys( data, key, &keynames );
9092 if ( num_keys == -1 ) {
9093 status = WERR_BADFILE;
9097 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9099 r_u->needed = printerkey_len*2;
9101 if ( q_u->size < r_u->needed ) {
9102 status = WERR_MORE_DATA;
9106 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9107 status = WERR_NOMEM;
9113 if ( q_u->size < r_u->needed )
9114 status = WERR_MORE_DATA;
9117 free_a_printer( &printer, 2 );
9118 SAFE_FREE( keynames );
9123 /********************************************************************
9124 * spoolss_deleteprinterkey
9125 ********************************************************************/
9127 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9129 POLICY_HND *handle = &q_u->handle;
9130 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9132 NT_PRINTER_INFO_LEVEL *printer = NULL;
9136 DEBUG(5,("spoolss_deleteprinterkey\n"));
9139 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9143 /* if keyname == NULL, return error */
9145 if ( !q_u->keyname.buffer )
9146 return WERR_INVALID_PARAM;
9148 if (!get_printer_snum(p, handle, &snum))
9151 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9152 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9153 return WERR_ACCESS_DENIED;
9156 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9157 if (!W_ERROR_IS_OK(status))
9160 /* delete the key and all subneys */
9162 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9164 status = delete_all_printer_data( printer->info_2, key );
9166 if ( W_ERROR_IS_OK(status) )
9167 status = mod_a_printer(printer, 2);
9169 free_a_printer( &printer, 2 );
9175 /********************************************************************
9176 * spoolss_enumprinterdataex
9177 ********************************************************************/
9179 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9181 POLICY_HND *handle = &q_u->handle;
9182 uint32 in_size = q_u->size;
9185 NT_PRINTER_INFO_LEVEL *printer = NULL;
9186 PRINTER_ENUM_VALUES *enum_values = NULL;
9187 NT_PRINTER_DATA *p_data;
9189 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9194 REGISTRY_VALUE *val;
9199 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9202 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9207 * first check for a keyname of NULL or "". Win2k seems to send
9208 * this a lot and we should send back WERR_INVALID_PARAM
9209 * no need to spend time looking up the printer in this case.
9213 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9214 if ( !strlen(key) ) {
9215 result = WERR_INVALID_PARAM;
9219 /* get the printer off of disk */
9221 if (!get_printer_snum(p,handle, &snum))
9224 ZERO_STRUCT(printer);
9225 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9226 if (!W_ERROR_IS_OK(result))
9229 /* now look for a match on the key name */
9231 p_data = printer->info_2->data;
9233 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9234 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9236 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9237 result = WERR_INVALID_PARAM;
9244 /* allocate the memory for the array of pointers -- if necessary */
9246 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9249 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9251 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9252 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9253 result = WERR_NOMEM;
9257 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9261 * loop through all params and build the array to pass
9262 * back to the client
9265 for ( i=0; i<num_entries; i++ )
9267 /* lookup the registry value */
9269 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9270 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9274 value_name = regval_name( val );
9275 init_unistr( &enum_values[i].valuename, value_name );
9276 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9277 enum_values[i].type = regval_type( val );
9279 data_len = regval_size( val );
9281 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9283 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9285 result = WERR_NOMEM;
9289 enum_values[i].data_len = data_len;
9291 /* keep track of the size of the array in bytes */
9293 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9296 /* housekeeping information in the reply */
9298 r_u->needed = needed;
9299 r_u->returned = num_entries;
9301 if (needed > in_size) {
9302 result = WERR_MORE_DATA;
9306 /* copy data into the reply */
9308 r_u->ctr.size = r_u->needed;
9309 r_u->ctr.size_of_array = r_u->returned;
9310 r_u->ctr.values = enum_values;
9316 free_a_printer(&printer, 2);
9321 /****************************************************************************
9322 ****************************************************************************/
9324 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9326 init_unistr(&info->name, name);
9329 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9330 UNISTR2 *environment,
9337 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9338 WERROR result = WERR_OK;
9340 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9342 if (!get_short_archi(long_archi))
9343 return WERR_INVALID_ENVIRONMENT;
9345 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9348 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9350 fill_printprocessordirectory_1(info, path);
9352 *needed += spoolss_size_printprocessordirectory_info_1(info);
9354 if (*needed > offered) {
9355 result = WERR_INSUFFICIENT_BUFFER;
9359 if (!rpcbuf_alloc_size(buffer, *needed)) {
9360 result = WERR_INSUFFICIENT_BUFFER;
9364 smb_io_printprocessordirectory_1("", buffer, info, 0);
9372 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9374 uint32 level = q_u->level;
9375 RPC_BUFFER *buffer = NULL;
9376 uint32 offered = q_u->offered;
9377 uint32 *needed = &r_u->needed;
9380 /* that's an [in out] buffer */
9382 if ( q_u->buffer ) {
9383 rpcbuf_move(q_u->buffer, &r_u->buffer);
9384 buffer = r_u->buffer;
9387 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9393 result = getprintprocessordirectory_level_1
9394 (&q_u->name, &q_u->environment, buffer, offered, needed);
9397 result = WERR_UNKNOWN_LEVEL;
9405 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9406 SPOOL_R_REPLYOPENPRINTER *r_u)
9408 DEBUG(5,("_spoolss_replyopenprinter\n"));
9410 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9415 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9416 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9418 DEBUG(5,("_spoolss_replycloseprinter\n"));