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 /* printer->info_2 is already a valid printer */
1737 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1738 printer->info_2->setuptime = time(NULL);
1748 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1749 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1755 printer->info_3=NULL;
1756 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1760 printer->info_6=NULL;
1761 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1771 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1772 NT_DEVICEMODE **pp_nt_devmode)
1774 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1777 * Ensure nt_devmode is a valid pointer
1778 * as we will be overwriting it.
1781 if (nt_devmode == NULL) {
1782 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1783 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1787 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1788 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1790 nt_devmode->specversion=devmode->specversion;
1791 nt_devmode->driverversion=devmode->driverversion;
1792 nt_devmode->size=devmode->size;
1793 nt_devmode->fields=devmode->fields;
1794 nt_devmode->orientation=devmode->orientation;
1795 nt_devmode->papersize=devmode->papersize;
1796 nt_devmode->paperlength=devmode->paperlength;
1797 nt_devmode->paperwidth=devmode->paperwidth;
1798 nt_devmode->scale=devmode->scale;
1799 nt_devmode->copies=devmode->copies;
1800 nt_devmode->defaultsource=devmode->defaultsource;
1801 nt_devmode->printquality=devmode->printquality;
1802 nt_devmode->color=devmode->color;
1803 nt_devmode->duplex=devmode->duplex;
1804 nt_devmode->yresolution=devmode->yresolution;
1805 nt_devmode->ttoption=devmode->ttoption;
1806 nt_devmode->collate=devmode->collate;
1808 nt_devmode->logpixels=devmode->logpixels;
1809 nt_devmode->bitsperpel=devmode->bitsperpel;
1810 nt_devmode->pelswidth=devmode->pelswidth;
1811 nt_devmode->pelsheight=devmode->pelsheight;
1812 nt_devmode->displayflags=devmode->displayflags;
1813 nt_devmode->displayfrequency=devmode->displayfrequency;
1814 nt_devmode->icmmethod=devmode->icmmethod;
1815 nt_devmode->icmintent=devmode->icmintent;
1816 nt_devmode->mediatype=devmode->mediatype;
1817 nt_devmode->dithertype=devmode->dithertype;
1818 nt_devmode->reserved1=devmode->reserved1;
1819 nt_devmode->reserved2=devmode->reserved2;
1820 nt_devmode->panningwidth=devmode->panningwidth;
1821 nt_devmode->panningheight=devmode->panningheight;
1824 * Only change private and driverextra if the incoming devmode
1825 * has a new one. JRA.
1828 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1829 SAFE_FREE(nt_devmode->nt_dev_private);
1830 nt_devmode->driverextra=devmode->driverextra;
1831 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1833 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1836 *pp_nt_devmode = nt_devmode;
1841 /********************************************************************
1842 * _spoolss_enddocprinter_internal.
1843 ********************************************************************/
1845 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1847 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1851 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1855 if (!get_printer_snum(p, handle, &snum))
1858 Printer->document_started=False;
1859 print_job_end(snum, Printer->jobid,True);
1860 /* error codes unhandled so far ... */
1865 /********************************************************************
1866 * api_spoolss_closeprinter
1867 ********************************************************************/
1869 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1871 POLICY_HND *handle = &q_u->handle;
1873 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1875 if (Printer && Printer->document_started)
1876 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1878 if (!close_printer_handle(p, handle))
1881 /* clear the returned printer handle. Observed behavior
1882 from Win2k server. Don't think this really matters.
1883 Previous code just copied the value of the closed
1886 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1891 /********************************************************************
1892 * api_spoolss_deleteprinter
1894 ********************************************************************/
1896 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1898 POLICY_HND *handle = &q_u->handle;
1899 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1902 if (Printer && Printer->document_started)
1903 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1905 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1907 result = delete_printer_handle(p, handle);
1909 update_c_setprinter(False);
1914 /*******************************************************************
1915 * static function to lookup the version id corresponding to an
1916 * long architecture string
1917 ******************************************************************/
1919 static int get_version_id (char * arch)
1922 struct table_node archi_table[]= {
1924 {"Windows 4.0", "WIN40", 0 },
1925 {"Windows NT x86", "W32X86", 2 },
1926 {"Windows NT R4000", "W32MIPS", 2 },
1927 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1928 {"Windows NT PowerPC", "W32PPC", 2 },
1929 {"Windows IA64", "IA64", 3 },
1930 {"Windows x64", "x64", 3 },
1934 for (i=0; archi_table[i].long_archi != NULL; i++)
1936 if (strcmp(arch, archi_table[i].long_archi) == 0)
1937 return (archi_table[i].version);
1943 /********************************************************************
1944 * _spoolss_deleteprinterdriver
1945 ********************************************************************/
1947 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1951 NT_PRINTER_DRIVER_INFO_LEVEL info;
1952 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1954 struct current_user user;
1956 WERROR status_win2k = WERR_ACCESS_DENIED;
1958 get_current_user(&user, p);
1960 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1961 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1963 /* check that we have a valid driver name first */
1965 if ((version=get_version_id(arch)) == -1)
1966 return WERR_INVALID_ENVIRONMENT;
1969 ZERO_STRUCT(info_win2k);
1971 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1973 /* try for Win2k driver if "Windows NT x86" */
1975 if ( version == 2 ) {
1977 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1978 status = WERR_UNKNOWN_PRINTER_DRIVER;
1982 /* otherwise it was a failure */
1984 status = WERR_UNKNOWN_PRINTER_DRIVER;
1990 if (printer_driver_in_use(info.info_3)) {
1991 status = WERR_PRINTER_DRIVER_IN_USE;
1997 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1999 /* if we get to here, we now have 2 driver info structures to remove */
2000 /* remove the Win2k driver first*/
2002 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2003 free_a_printer_driver( info_win2k, 3 );
2005 /* this should not have failed---if it did, report to client */
2006 if ( !W_ERROR_IS_OK(status_win2k) )
2008 status = status_win2k;
2014 status = delete_printer_driver(info.info_3, &user, version, False);
2016 /* if at least one of the deletes succeeded return OK */
2018 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2022 free_a_printer_driver( info, 3 );
2027 /********************************************************************
2028 * spoolss_deleteprinterdriverex
2029 ********************************************************************/
2031 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2035 NT_PRINTER_DRIVER_INFO_LEVEL info;
2036 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2038 uint32 flags = q_u->delete_flags;
2040 struct current_user user;
2042 WERROR status_win2k = WERR_ACCESS_DENIED;
2044 get_current_user(&user, p);
2046 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2047 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2049 /* check that we have a valid driver name first */
2050 if ((version=get_version_id(arch)) == -1) {
2051 /* this is what NT returns */
2052 return WERR_INVALID_ENVIRONMENT;
2055 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2056 version = q_u->version;
2059 ZERO_STRUCT(info_win2k);
2061 status = get_a_printer_driver(&info, 3, driver, arch, version);
2063 if ( !W_ERROR_IS_OK(status) )
2066 * if the client asked for a specific version,
2067 * or this is something other than Windows NT x86,
2071 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2074 /* try for Win2k driver if "Windows NT x86" */
2077 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2078 status = WERR_UNKNOWN_PRINTER_DRIVER;
2083 if ( printer_driver_in_use(info.info_3) ) {
2084 status = WERR_PRINTER_DRIVER_IN_USE;
2089 * we have a couple of cases to consider.
2090 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2091 * then the delete should fail if **any** files overlap with
2093 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2094 * non-overlapping files
2095 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2096 * is set, the do not delete any files
2097 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2100 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2102 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2104 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2105 /* no idea of the correct error here */
2106 status = WERR_ACCESS_DENIED;
2111 /* also check for W32X86/3 if necessary; maybe we already have? */
2113 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2114 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2117 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2118 /* no idea of the correct error here */
2119 free_a_printer_driver( info_win2k, 3 );
2120 status = WERR_ACCESS_DENIED;
2124 /* if we get to here, we now have 2 driver info structures to remove */
2125 /* remove the Win2k driver first*/
2127 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2128 free_a_printer_driver( info_win2k, 3 );
2130 /* this should not have failed---if it did, report to client */
2132 if ( !W_ERROR_IS_OK(status_win2k) )
2137 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2139 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2142 free_a_printer_driver( info, 3 );
2148 /****************************************************************************
2149 Internal routine for retreiving printerdata
2150 ***************************************************************************/
2152 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2153 const char *key, const char *value, uint32 *type, uint8 **data,
2154 uint32 *needed, uint32 in_size )
2156 REGISTRY_VALUE *val;
2160 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2161 return WERR_BADFILE;
2163 *type = regval_type( val );
2165 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2167 size = regval_size( val );
2169 /* copy the min(in_size, len) */
2172 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2174 /* special case for 0 length values */
2176 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2180 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2189 DEBUG(5,("get_printer_dataex: copy done\n"));
2194 /****************************************************************************
2195 Internal routine for removing printerdata
2196 ***************************************************************************/
2198 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2200 return delete_printer_data( printer->info_2, key, value );
2203 /****************************************************************************
2204 Internal routine for storing printerdata
2205 ***************************************************************************/
2207 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2208 uint32 type, uint8 *data, int real_len )
2210 /* the registry objects enforce uniqueness based on value name */
2212 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2215 /********************************************************************
2216 GetPrinterData on a printer server Handle.
2217 ********************************************************************/
2219 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2223 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2225 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2227 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2233 if (!StrCaseCmp(value, "BeepEnabled")) {
2235 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2237 SIVAL(*data, 0, 0x00);
2242 if (!StrCaseCmp(value, "EventLog")) {
2244 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2246 /* formally was 0x1b */
2247 SIVAL(*data, 0, 0x0);
2252 if (!StrCaseCmp(value, "NetPopup")) {
2254 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2256 SIVAL(*data, 0, 0x00);
2261 if (!StrCaseCmp(value, "MajorVersion")) {
2263 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2266 /* Windows NT 4.0 seems to not allow uploading of drivers
2267 to a server that reports 0x3 as the MajorVersion.
2268 need to investigate more how Win2k gets around this .
2271 if ( RA_WINNT == get_remote_arch() )
2280 if (!StrCaseCmp(value, "MinorVersion")) {
2282 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2290 * uint32 size = 0x114
2292 * uint32 minor = [0|1]
2293 * uint32 build = [2195|2600]
2294 * extra unicode string = e.g. "Service Pack 3"
2296 if (!StrCaseCmp(value, "OSVersion")) {
2300 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2303 SIVAL(*data, 0, *needed); /* size */
2304 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2306 SIVAL(*data, 12, 2195); /* build */
2308 /* leave extra string empty */
2314 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2315 const char *string="C:\\PRINTERS";
2317 *needed = 2*(strlen(string)+1);
2318 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2320 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2322 /* it's done by hand ready to go on the wire */
2323 for (i=0; i<strlen(string); i++) {
2324 (*data)[2*i]=string[i];
2325 (*data)[2*i+1]='\0';
2330 if (!StrCaseCmp(value, "Architecture")) {
2331 const char *string="Windows NT x86";
2333 *needed = 2*(strlen(string)+1);
2334 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2336 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2337 for (i=0; i<strlen(string); i++) {
2338 (*data)[2*i]=string[i];
2339 (*data)[2*i+1]='\0';
2344 if (!StrCaseCmp(value, "DsPresent")) {
2346 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2349 /* only show the publish check box if we are a
2350 memeber of a AD domain */
2352 if ( lp_security() == SEC_ADS )
2353 SIVAL(*data, 0, 0x01);
2355 SIVAL(*data, 0, 0x00);
2361 if (!StrCaseCmp(value, "DNSMachineName")) {
2364 if (!get_mydnsfullname(hostname))
2365 return WERR_BADFILE;
2367 *needed = 2*(strlen(hostname)+1);
2368 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2370 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2371 for (i=0; i<strlen(hostname); i++) {
2372 (*data)[2*i]=hostname[i];
2373 (*data)[2*i+1]='\0';
2379 return WERR_BADFILE;
2382 /********************************************************************
2383 * spoolss_getprinterdata
2384 ********************************************************************/
2386 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2388 POLICY_HND *handle = &q_u->handle;
2389 UNISTR2 *valuename = &q_u->valuename;
2390 uint32 in_size = q_u->size;
2391 uint32 *type = &r_u->type;
2392 uint32 *out_size = &r_u->size;
2393 uint8 **data = &r_u->data;
2394 uint32 *needed = &r_u->needed;
2397 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2398 NT_PRINTER_INFO_LEVEL *printer = NULL;
2402 * Reminder: when it's a string, the length is in BYTES
2403 * even if UNICODE is negociated.
2408 *out_size = in_size;
2410 /* in case of problem, return some default values */
2415 DEBUG(4,("_spoolss_getprinterdata\n"));
2418 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2419 status = WERR_BADFID;
2423 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2425 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2426 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2429 if ( !get_printer_snum(p,handle, &snum) ) {
2430 status = WERR_BADFID;
2434 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2435 if ( !W_ERROR_IS_OK(status) )
2438 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2440 if ( strequal(value, "ChangeId") ) {
2442 *needed = sizeof(uint32);
2443 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2444 status = WERR_NOMEM;
2447 SIVAL( *data, 0, printer->info_2->changeid );
2451 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2454 if (*needed > *out_size)
2455 status = WERR_MORE_DATA;
2458 if ( !W_ERROR_IS_OK(status) )
2460 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2462 /* reply this param doesn't exist */
2465 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2467 free_a_printer( &printer, 2 );
2476 /* cleanup & exit */
2479 free_a_printer( &printer, 2 );
2484 /*********************************************************
2485 Connect to the client machine.
2486 **********************************************************/
2488 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, struct rpc_pipe_client **pp_pipe,
2489 struct in_addr *client_ip, const char *remote_machine)
2492 ZERO_STRUCTP(the_cli);
2494 if(cli_initialise(the_cli) == NULL) {
2495 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2499 if ( is_zero_ip(*client_ip) ) {
2500 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2501 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2502 cli_shutdown(the_cli);
2506 if (ismyip(the_cli->dest_ip)) {
2507 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2508 cli_shutdown(the_cli);
2513 the_cli->dest_ip.s_addr = client_ip->s_addr;
2514 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2515 inet_ntoa(*client_ip) ));
2518 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2519 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) ));
2520 cli_shutdown(the_cli);
2524 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2525 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2527 cli_shutdown(the_cli);
2531 the_cli->protocol = PROTOCOL_NT1;
2532 cli_setup_signing_state(the_cli, lp_client_signing());
2534 if (!cli_negprot(the_cli)) {
2535 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2536 cli_shutdown(the_cli);
2540 if (the_cli->protocol != PROTOCOL_NT1) {
2541 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2542 cli_shutdown(the_cli);
2547 * Do an anonymous session setup.
2550 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2551 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2552 cli_shutdown(the_cli);
2556 if (!(the_cli->sec_mode & 1)) {
2557 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2558 cli_shutdown(the_cli);
2562 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2563 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) ));
2564 cli_shutdown(the_cli);
2569 * Ok - we have an anonymous connection to the IPC$ share.
2570 * Now start the NT Domain stuff :-).
2573 *pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret);
2575 DEBUG(0,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2576 remote_machine, nt_errstr(ret)));
2577 cli_shutdown(the_cli);
2584 /***************************************************************************
2585 Connect to the client.
2586 ****************************************************************************/
2588 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2589 uint32 localprinter, uint32 type,
2590 POLICY_HND *handle, struct in_addr *client_ip)
2595 * If it's the first connection, contact the client
2596 * and connect to the IPC$ share anonymously
2598 if (smb_connections==0) {
2599 struct cli_state notify_cli; /* print notify back-channel */
2600 fstring unix_printer;
2602 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2604 ZERO_STRUCT(notify_cli);
2606 if(!spoolss_connect_to_client(¬ify_cli, ¬ify_cli_pipe, client_ip, unix_printer))
2609 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2610 /* Tell the connections db we're now interested in printer
2611 * notify messages. */
2612 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2616 * Tell the specific printing tdb we want messages for this printer
2617 * by registering our PID.
2620 if (!print_notify_register_pid(snum))
2621 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2625 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2628 if (!W_ERROR_IS_OK(result))
2629 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2630 dos_errstr(result)));
2632 return (W_ERROR_IS_OK(result));
2635 /********************************************************************
2637 * ReplyFindFirstPrinterChangeNotifyEx
2639 * before replying OK: status=0 a rpc call is made to the workstation
2640 * asking ReplyOpenPrinter
2642 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2643 * called from api_spoolss_rffpcnex
2644 ********************************************************************/
2646 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2648 POLICY_HND *handle = &q_u->handle;
2649 uint32 flags = q_u->flags;
2650 uint32 options = q_u->options;
2651 UNISTR2 *localmachine = &q_u->localmachine;
2652 uint32 printerlocal = q_u->printerlocal;
2654 SPOOL_NOTIFY_OPTION *option = q_u->option;
2655 struct in_addr client_ip;
2657 /* store the notify value in the printer struct */
2659 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2662 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2666 Printer->notify.flags=flags;
2667 Printer->notify.options=options;
2668 Printer->notify.printerlocal=printerlocal;
2670 if (Printer->notify.option)
2671 free_spool_notify_option(&Printer->notify.option);
2673 Printer->notify.option=dup_spool_notify_option(option);
2675 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2676 sizeof(Printer->notify.localmachine)-1);
2678 /* Connect to the client machine and send a ReplyOpenPrinter */
2680 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2682 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2683 !get_printer_snum(p, handle, &snum) )
2686 client_ip.s_addr = inet_addr(p->conn->client_address);
2688 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2689 Printer->notify.printerlocal, 1,
2690 &Printer->notify.client_hnd, &client_ip))
2691 return WERR_SERVER_UNAVAILABLE;
2693 Printer->notify.client_connected=True;
2698 /*******************************************************************
2699 * fill a notify_info_data with the servername
2700 ********************************************************************/
2702 void spoolss_notify_server_name(int snum,
2703 SPOOL_NOTIFY_INFO_DATA *data,
2704 print_queue_struct *queue,
2705 NT_PRINTER_INFO_LEVEL *printer,
2706 TALLOC_CTX *mem_ctx)
2711 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2713 data->notify_data.data.length = len;
2714 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2716 if (!data->notify_data.data.string) {
2717 data->notify_data.data.length = 0;
2721 memcpy(data->notify_data.data.string, temp, len);
2724 /*******************************************************************
2725 * fill a notify_info_data with the printername (not including the servername).
2726 ********************************************************************/
2728 void spoolss_notify_printer_name(int snum,
2729 SPOOL_NOTIFY_INFO_DATA *data,
2730 print_queue_struct *queue,
2731 NT_PRINTER_INFO_LEVEL *printer,
2732 TALLOC_CTX *mem_ctx)
2737 /* the notify name should not contain the \\server\ part */
2738 char *p = strrchr(printer->info_2->printername, '\\');
2741 p = printer->info_2->printername;
2746 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2748 data->notify_data.data.length = len;
2749 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2751 if (!data->notify_data.data.string) {
2752 data->notify_data.data.length = 0;
2756 memcpy(data->notify_data.data.string, temp, len);
2759 /*******************************************************************
2760 * fill a notify_info_data with the servicename
2761 ********************************************************************/
2763 void spoolss_notify_share_name(int snum,
2764 SPOOL_NOTIFY_INFO_DATA *data,
2765 print_queue_struct *queue,
2766 NT_PRINTER_INFO_LEVEL *printer,
2767 TALLOC_CTX *mem_ctx)
2772 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2774 data->notify_data.data.length = len;
2775 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2777 if (!data->notify_data.data.string) {
2778 data->notify_data.data.length = 0;
2782 memcpy(data->notify_data.data.string, temp, len);
2785 /*******************************************************************
2786 * fill a notify_info_data with the port name
2787 ********************************************************************/
2789 void spoolss_notify_port_name(int snum,
2790 SPOOL_NOTIFY_INFO_DATA *data,
2791 print_queue_struct *queue,
2792 NT_PRINTER_INFO_LEVEL *printer,
2793 TALLOC_CTX *mem_ctx)
2798 /* even if it's strange, that's consistant in all the code */
2800 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2802 data->notify_data.data.length = len;
2803 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2805 if (!data->notify_data.data.string) {
2806 data->notify_data.data.length = 0;
2810 memcpy(data->notify_data.data.string, temp, len);
2813 /*******************************************************************
2814 * fill a notify_info_data with the printername
2815 * but it doesn't exist, have to see what to do
2816 ********************************************************************/
2818 void spoolss_notify_driver_name(int snum,
2819 SPOOL_NOTIFY_INFO_DATA *data,
2820 print_queue_struct *queue,
2821 NT_PRINTER_INFO_LEVEL *printer,
2822 TALLOC_CTX *mem_ctx)
2827 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2829 data->notify_data.data.length = len;
2830 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2832 if (!data->notify_data.data.string) {
2833 data->notify_data.data.length = 0;
2837 memcpy(data->notify_data.data.string, temp, len);
2840 /*******************************************************************
2841 * fill a notify_info_data with the comment
2842 ********************************************************************/
2844 void spoolss_notify_comment(int snum,
2845 SPOOL_NOTIFY_INFO_DATA *data,
2846 print_queue_struct *queue,
2847 NT_PRINTER_INFO_LEVEL *printer,
2848 TALLOC_CTX *mem_ctx)
2853 if (*printer->info_2->comment == '\0')
2854 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2856 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2858 data->notify_data.data.length = len;
2859 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2861 if (!data->notify_data.data.string) {
2862 data->notify_data.data.length = 0;
2866 memcpy(data->notify_data.data.string, temp, len);
2869 /*******************************************************************
2870 * fill a notify_info_data with the comment
2871 * location = "Room 1, floor 2, building 3"
2872 ********************************************************************/
2874 void spoolss_notify_location(int snum,
2875 SPOOL_NOTIFY_INFO_DATA *data,
2876 print_queue_struct *queue,
2877 NT_PRINTER_INFO_LEVEL *printer,
2878 TALLOC_CTX *mem_ctx)
2883 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2885 data->notify_data.data.length = len;
2886 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2888 if (!data->notify_data.data.string) {
2889 data->notify_data.data.length = 0;
2893 memcpy(data->notify_data.data.string, temp, len);
2896 /*******************************************************************
2897 * fill a notify_info_data with the device mode
2898 * jfm:xxxx don't to it for know but that's a real problem !!!
2899 ********************************************************************/
2901 static void spoolss_notify_devmode(int snum,
2902 SPOOL_NOTIFY_INFO_DATA *data,
2903 print_queue_struct *queue,
2904 NT_PRINTER_INFO_LEVEL *printer,
2905 TALLOC_CTX *mem_ctx)
2909 /*******************************************************************
2910 * fill a notify_info_data with the separator file name
2911 ********************************************************************/
2913 void spoolss_notify_sepfile(int snum,
2914 SPOOL_NOTIFY_INFO_DATA *data,
2915 print_queue_struct *queue,
2916 NT_PRINTER_INFO_LEVEL *printer,
2917 TALLOC_CTX *mem_ctx)
2922 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2924 data->notify_data.data.length = len;
2925 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2927 if (!data->notify_data.data.string) {
2928 data->notify_data.data.length = 0;
2932 memcpy(data->notify_data.data.string, temp, len);
2935 /*******************************************************************
2936 * fill a notify_info_data with the print processor
2937 * jfm:xxxx return always winprint to indicate we don't do anything to it
2938 ********************************************************************/
2940 void spoolss_notify_print_processor(int snum,
2941 SPOOL_NOTIFY_INFO_DATA *data,
2942 print_queue_struct *queue,
2943 NT_PRINTER_INFO_LEVEL *printer,
2944 TALLOC_CTX *mem_ctx)
2949 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2951 data->notify_data.data.length = len;
2952 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2954 if (!data->notify_data.data.string) {
2955 data->notify_data.data.length = 0;
2959 memcpy(data->notify_data.data.string, temp, len);
2962 /*******************************************************************
2963 * fill a notify_info_data with the print processor options
2964 * jfm:xxxx send an empty string
2965 ********************************************************************/
2967 void spoolss_notify_parameters(int snum,
2968 SPOOL_NOTIFY_INFO_DATA *data,
2969 print_queue_struct *queue,
2970 NT_PRINTER_INFO_LEVEL *printer,
2971 TALLOC_CTX *mem_ctx)
2976 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2978 data->notify_data.data.length = len;
2979 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2981 if (!data->notify_data.data.string) {
2982 data->notify_data.data.length = 0;
2986 memcpy(data->notify_data.data.string, temp, len);
2989 /*******************************************************************
2990 * fill a notify_info_data with the data type
2991 * jfm:xxxx always send RAW as data type
2992 ********************************************************************/
2994 void spoolss_notify_datatype(int snum,
2995 SPOOL_NOTIFY_INFO_DATA *data,
2996 print_queue_struct *queue,
2997 NT_PRINTER_INFO_LEVEL *printer,
2998 TALLOC_CTX *mem_ctx)
3003 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3005 data->notify_data.data.length = len;
3006 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3008 if (!data->notify_data.data.string) {
3009 data->notify_data.data.length = 0;
3013 memcpy(data->notify_data.data.string, temp, len);
3016 /*******************************************************************
3017 * fill a notify_info_data with the security descriptor
3018 * jfm:xxxx send an null pointer to say no security desc
3019 * have to implement security before !
3020 ********************************************************************/
3022 static void spoolss_notify_security_desc(int snum,
3023 SPOOL_NOTIFY_INFO_DATA *data,
3024 print_queue_struct *queue,
3025 NT_PRINTER_INFO_LEVEL *printer,
3026 TALLOC_CTX *mem_ctx)
3028 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3029 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3032 /*******************************************************************
3033 * fill a notify_info_data with the attributes
3034 * jfm:xxxx a samba printer is always shared
3035 ********************************************************************/
3037 void spoolss_notify_attributes(int snum,
3038 SPOOL_NOTIFY_INFO_DATA *data,
3039 print_queue_struct *queue,
3040 NT_PRINTER_INFO_LEVEL *printer,
3041 TALLOC_CTX *mem_ctx)
3043 data->notify_data.value[0] = printer->info_2->attributes;
3044 data->notify_data.value[1] = 0;
3047 /*******************************************************************
3048 * fill a notify_info_data with the priority
3049 ********************************************************************/
3051 static void spoolss_notify_priority(int snum,
3052 SPOOL_NOTIFY_INFO_DATA *data,
3053 print_queue_struct *queue,
3054 NT_PRINTER_INFO_LEVEL *printer,
3055 TALLOC_CTX *mem_ctx)
3057 data->notify_data.value[0] = printer->info_2->priority;
3058 data->notify_data.value[1] = 0;
3061 /*******************************************************************
3062 * fill a notify_info_data with the default priority
3063 ********************************************************************/
3065 static void spoolss_notify_default_priority(int snum,
3066 SPOOL_NOTIFY_INFO_DATA *data,
3067 print_queue_struct *queue,
3068 NT_PRINTER_INFO_LEVEL *printer,
3069 TALLOC_CTX *mem_ctx)
3071 data->notify_data.value[0] = printer->info_2->default_priority;
3072 data->notify_data.value[1] = 0;
3075 /*******************************************************************
3076 * fill a notify_info_data with the start time
3077 ********************************************************************/
3079 static void spoolss_notify_start_time(int snum,
3080 SPOOL_NOTIFY_INFO_DATA *data,
3081 print_queue_struct *queue,
3082 NT_PRINTER_INFO_LEVEL *printer,
3083 TALLOC_CTX *mem_ctx)
3085 data->notify_data.value[0] = printer->info_2->starttime;
3086 data->notify_data.value[1] = 0;
3089 /*******************************************************************
3090 * fill a notify_info_data with the until time
3091 ********************************************************************/
3093 static void spoolss_notify_until_time(int snum,
3094 SPOOL_NOTIFY_INFO_DATA *data,
3095 print_queue_struct *queue,
3096 NT_PRINTER_INFO_LEVEL *printer,
3097 TALLOC_CTX *mem_ctx)
3099 data->notify_data.value[0] = printer->info_2->untiltime;
3100 data->notify_data.value[1] = 0;
3103 /*******************************************************************
3104 * fill a notify_info_data with the status
3105 ********************************************************************/
3107 static void spoolss_notify_status(int snum,
3108 SPOOL_NOTIFY_INFO_DATA *data,
3109 print_queue_struct *queue,
3110 NT_PRINTER_INFO_LEVEL *printer,
3111 TALLOC_CTX *mem_ctx)
3113 print_status_struct status;
3115 print_queue_length(snum, &status);
3116 data->notify_data.value[0]=(uint32) status.status;
3117 data->notify_data.value[1] = 0;
3120 /*******************************************************************
3121 * fill a notify_info_data with the number of jobs queued
3122 ********************************************************************/
3124 void spoolss_notify_cjobs(int snum,
3125 SPOOL_NOTIFY_INFO_DATA *data,
3126 print_queue_struct *queue,
3127 NT_PRINTER_INFO_LEVEL *printer,
3128 TALLOC_CTX *mem_ctx)
3130 data->notify_data.value[0] = print_queue_length(snum, NULL);
3131 data->notify_data.value[1] = 0;
3134 /*******************************************************************
3135 * fill a notify_info_data with the average ppm
3136 ********************************************************************/
3138 static void spoolss_notify_average_ppm(int snum,
3139 SPOOL_NOTIFY_INFO_DATA *data,
3140 print_queue_struct *queue,
3141 NT_PRINTER_INFO_LEVEL *printer,
3142 TALLOC_CTX *mem_ctx)
3144 /* always respond 8 pages per minutes */
3145 /* a little hard ! */
3146 data->notify_data.value[0] = printer->info_2->averageppm;
3147 data->notify_data.value[1] = 0;
3150 /*******************************************************************
3151 * fill a notify_info_data with username
3152 ********************************************************************/
3154 static void spoolss_notify_username(int snum,
3155 SPOOL_NOTIFY_INFO_DATA *data,
3156 print_queue_struct *queue,
3157 NT_PRINTER_INFO_LEVEL *printer,
3158 TALLOC_CTX *mem_ctx)
3163 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3165 data->notify_data.data.length = len;
3166 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3168 if (!data->notify_data.data.string) {
3169 data->notify_data.data.length = 0;
3173 memcpy(data->notify_data.data.string, temp, len);
3176 /*******************************************************************
3177 * fill a notify_info_data with job status
3178 ********************************************************************/
3180 static void spoolss_notify_job_status(int snum,
3181 SPOOL_NOTIFY_INFO_DATA *data,
3182 print_queue_struct *queue,
3183 NT_PRINTER_INFO_LEVEL *printer,
3184 TALLOC_CTX *mem_ctx)
3186 data->notify_data.value[0]=nt_printj_status(queue->status);
3187 data->notify_data.value[1] = 0;
3190 /*******************************************************************
3191 * fill a notify_info_data with job name
3192 ********************************************************************/
3194 static void spoolss_notify_job_name(int snum,
3195 SPOOL_NOTIFY_INFO_DATA *data,
3196 print_queue_struct *queue,
3197 NT_PRINTER_INFO_LEVEL *printer,
3198 TALLOC_CTX *mem_ctx)
3203 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3205 data->notify_data.data.length = len;
3206 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3208 if (!data->notify_data.data.string) {
3209 data->notify_data.data.length = 0;
3213 memcpy(data->notify_data.data.string, temp, len);
3216 /*******************************************************************
3217 * fill a notify_info_data with job status
3218 ********************************************************************/
3220 static void spoolss_notify_job_status_string(int snum,
3221 SPOOL_NOTIFY_INFO_DATA *data,
3222 print_queue_struct *queue,
3223 NT_PRINTER_INFO_LEVEL *printer,
3224 TALLOC_CTX *mem_ctx)
3227 * Now we're returning job status codes we just return a "" here. JRA.
3234 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3237 switch (queue->status) {
3242 p = ""; /* NT provides the paused string */
3251 #endif /* NO LONGER NEEDED. */
3253 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3255 data->notify_data.data.length = len;
3256 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3258 if (!data->notify_data.data.string) {
3259 data->notify_data.data.length = 0;
3263 memcpy(data->notify_data.data.string, temp, len);
3266 /*******************************************************************
3267 * fill a notify_info_data with job time
3268 ********************************************************************/
3270 static void spoolss_notify_job_time(int snum,
3271 SPOOL_NOTIFY_INFO_DATA *data,
3272 print_queue_struct *queue,
3273 NT_PRINTER_INFO_LEVEL *printer,
3274 TALLOC_CTX *mem_ctx)
3276 data->notify_data.value[0]=0x0;
3277 data->notify_data.value[1]=0;
3280 /*******************************************************************
3281 * fill a notify_info_data with job size
3282 ********************************************************************/
3284 static void spoolss_notify_job_size(int snum,
3285 SPOOL_NOTIFY_INFO_DATA *data,
3286 print_queue_struct *queue,
3287 NT_PRINTER_INFO_LEVEL *printer,
3288 TALLOC_CTX *mem_ctx)
3290 data->notify_data.value[0]=queue->size;
3291 data->notify_data.value[1]=0;
3294 /*******************************************************************
3295 * fill a notify_info_data with page info
3296 ********************************************************************/
3297 static void spoolss_notify_total_pages(int snum,
3298 SPOOL_NOTIFY_INFO_DATA *data,
3299 print_queue_struct *queue,
3300 NT_PRINTER_INFO_LEVEL *printer,
3301 TALLOC_CTX *mem_ctx)
3303 data->notify_data.value[0]=queue->page_count;
3304 data->notify_data.value[1]=0;
3307 /*******************************************************************
3308 * fill a notify_info_data with pages printed info.
3309 ********************************************************************/
3310 static void spoolss_notify_pages_printed(int snum,
3311 SPOOL_NOTIFY_INFO_DATA *data,
3312 print_queue_struct *queue,
3313 NT_PRINTER_INFO_LEVEL *printer,
3314 TALLOC_CTX *mem_ctx)
3316 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3317 data->notify_data.value[1]=0;
3320 /*******************************************************************
3321 Fill a notify_info_data with job position.
3322 ********************************************************************/
3324 static void spoolss_notify_job_position(int snum,
3325 SPOOL_NOTIFY_INFO_DATA *data,
3326 print_queue_struct *queue,
3327 NT_PRINTER_INFO_LEVEL *printer,
3328 TALLOC_CTX *mem_ctx)
3330 data->notify_data.value[0]=queue->job;
3331 data->notify_data.value[1]=0;
3334 /*******************************************************************
3335 Fill a notify_info_data with submitted time.
3336 ********************************************************************/
3338 static void spoolss_notify_submitted_time(int snum,
3339 SPOOL_NOTIFY_INFO_DATA *data,
3340 print_queue_struct *queue,
3341 NT_PRINTER_INFO_LEVEL *printer,
3342 TALLOC_CTX *mem_ctx)
3349 t=gmtime(&queue->time);
3351 len = sizeof(SYSTEMTIME);
3353 data->notify_data.data.length = len;
3354 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3356 if (!data->notify_data.data.string) {
3357 data->notify_data.data.length = 0;
3361 make_systemtime(&st, t);
3364 * Systemtime must be linearized as a set of UINT16's.
3365 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3368 p = (char *)data->notify_data.data.string;
3369 SSVAL(p, 0, st.year);
3370 SSVAL(p, 2, st.month);
3371 SSVAL(p, 4, st.dayofweek);
3372 SSVAL(p, 6, st.day);
3373 SSVAL(p, 8, st.hour);
3374 SSVAL(p, 10, st.minute);
3375 SSVAL(p, 12, st.second);
3376 SSVAL(p, 14, st.milliseconds);
3379 struct s_notify_info_data_table
3385 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3386 print_queue_struct *queue,
3387 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3390 /* A table describing the various print notification constants and
3391 whether the notification data is a pointer to a variable sized
3392 buffer, a one value uint32 or a two value uint32. */
3394 static const struct s_notify_info_data_table notify_info_data_table[] =
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3445 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3448 /*******************************************************************
3449 Return the size of info_data structure.
3450 ********************************************************************/
3452 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3456 for (i = 0; i < sizeof(notify_info_data_table); i++)
3458 if ( (notify_info_data_table[i].type == type)
3459 && (notify_info_data_table[i].field == field) )
3461 switch(notify_info_data_table[i].size)
3463 case NOTIFY_ONE_VALUE:
3464 case NOTIFY_TWO_VALUE:
3469 /* The only pointer notify data I have seen on
3470 the wire is the submitted time and this has
3471 the notify size set to 4. -tpot */
3473 case NOTIFY_POINTER:
3476 case NOTIFY_SECDESC:
3482 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3487 /*******************************************************************
3488 Return the type of notify_info_data.
3489 ********************************************************************/
3491 static int type_of_notify_info_data(uint16 type, uint16 field)
3495 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3496 if (notify_info_data_table[i].type == type &&
3497 notify_info_data_table[i].field == field)
3498 return notify_info_data_table[i].size;
3504 /****************************************************************************
3505 ****************************************************************************/
3507 static int search_notify(uint16 type, uint16 field, int *value)
3511 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3512 if (notify_info_data_table[i].type == type &&
3513 notify_info_data_table[i].field == field &&
3514 notify_info_data_table[i].fn != NULL) {
3523 /****************************************************************************
3524 ****************************************************************************/
3526 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3528 info_data->type = type;
3529 info_data->field = field;
3530 info_data->reserved = 0;
3532 info_data->size = size_of_notify_info_data(type, field);
3533 info_data->enc_type = type_of_notify_info_data(type, field);
3540 /*******************************************************************
3542 * fill a notify_info struct with info asked
3544 ********************************************************************/
3546 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3547 snum, SPOOL_NOTIFY_OPTION_TYPE
3548 *option_type, uint32 id,
3549 TALLOC_CTX *mem_ctx)
3555 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3556 NT_PRINTER_INFO_LEVEL *printer = NULL;
3557 print_queue_struct *queue=NULL;
3559 type=option_type->type;
3561 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3562 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3563 option_type->count, lp_servicename(snum)));
3565 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3568 for(field_num=0; field_num<option_type->count; field_num++) {
3569 field = option_type->fields[field_num];
3571 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3573 if (!search_notify(type, field, &j) )
3576 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3577 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3582 current_data = &info->data[info->count];
3584 construct_info_data(current_data, type, field, id);
3586 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3587 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3589 notify_info_data_table[j].fn(snum, current_data, queue,
3595 free_a_printer(&printer, 2);
3599 /*******************************************************************
3601 * fill a notify_info struct with info asked
3603 ********************************************************************/
3605 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3606 SPOOL_NOTIFY_INFO *info,
3607 NT_PRINTER_INFO_LEVEL *printer,
3608 int snum, SPOOL_NOTIFY_OPTION_TYPE
3609 *option_type, uint32 id,
3610 TALLOC_CTX *mem_ctx)
3616 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3618 DEBUG(4,("construct_notify_jobs_info\n"));
3620 type = option_type->type;
3622 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3623 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3624 option_type->count));
3626 for(field_num=0; field_num<option_type->count; field_num++) {
3627 field = option_type->fields[field_num];
3629 if (!search_notify(type, field, &j) )
3632 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3633 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3636 else info->data = tid;
3638 current_data=&(info->data[info->count]);
3640 construct_info_data(current_data, type, field, id);
3641 notify_info_data_table[j].fn(snum, current_data, queue,
3650 * JFM: The enumeration is not that simple, it's even non obvious.
3652 * let's take an example: I want to monitor the PRINTER SERVER for
3653 * the printer's name and the number of jobs currently queued.
3654 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3655 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3657 * I have 3 printers on the back of my server.
3659 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3662 * 1 printer 1 name 1
3663 * 2 printer 1 cjob 1
3664 * 3 printer 2 name 2
3665 * 4 printer 2 cjob 2
3666 * 5 printer 3 name 3
3667 * 6 printer 3 name 3
3669 * that's the print server case, the printer case is even worse.
3672 /*******************************************************************
3674 * enumerate all printers on the printserver
3675 * fill a notify_info struct with info asked
3677 ********************************************************************/
3679 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3680 SPOOL_NOTIFY_INFO *info,
3681 TALLOC_CTX *mem_ctx)
3684 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3685 int n_services=lp_numservices();
3687 SPOOL_NOTIFY_OPTION *option;
3688 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3690 DEBUG(4,("printserver_notify_info\n"));
3695 option=Printer->notify.option;
3700 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3701 sending a ffpcn() request first */
3706 for (i=0; i<option->count; i++) {
3707 option_type=&(option->ctr.type[i]);
3709 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3712 for (snum=0; snum<n_services; snum++)
3714 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3715 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3721 * Debugging information, don't delete.
3724 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3725 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3726 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3728 for (i=0; i<info->count; i++) {
3729 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3730 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3731 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3738 /*******************************************************************
3740 * fill a notify_info struct with info asked
3742 ********************************************************************/
3744 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3745 TALLOC_CTX *mem_ctx)
3748 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3751 SPOOL_NOTIFY_OPTION *option;
3752 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3754 print_queue_struct *queue=NULL;
3755 print_status_struct status;
3757 DEBUG(4,("printer_notify_info\n"));
3762 option=Printer->notify.option;
3768 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3769 sending a ffpcn() request first */
3774 get_printer_snum(p, hnd, &snum);
3776 for (i=0; i<option->count; i++) {
3777 option_type=&option->ctr.type[i];
3779 switch ( option_type->type ) {
3780 case PRINTER_NOTIFY_TYPE:
3781 if(construct_notify_printer_info(Printer, info, snum,
3787 case JOB_NOTIFY_TYPE: {
3788 NT_PRINTER_INFO_LEVEL *printer = NULL;
3790 count = print_queue_status(snum, &queue, &status);
3792 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3795 for (j=0; j<count; j++) {
3796 construct_notify_jobs_info(&queue[j], info,
3803 free_a_printer(&printer, 2);
3813 * Debugging information, don't delete.
3816 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3817 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3818 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3820 for (i=0; i<info->count; i++) {
3821 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3822 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3823 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3829 /********************************************************************
3831 ********************************************************************/
3833 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3835 POLICY_HND *handle = &q_u->handle;
3836 SPOOL_NOTIFY_INFO *info = &r_u->info;
3838 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3839 WERROR result = WERR_BADFID;
3841 /* we always have a NOTIFY_INFO struct */
3845 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3846 OUR_HANDLE(handle)));
3850 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3853 * We are now using the change value, and
3854 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3855 * I don't have a global notification system, I'm sending back all the
3856 * informations even when _NOTHING_ has changed.
3859 /* We need to keep track of the change value to send back in
3860 RRPCN replies otherwise our updates are ignored. */
3862 Printer->notify.fnpcn = True;
3864 if (Printer->notify.client_connected) {
3865 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3866 Printer->notify.change = q_u->change;
3869 /* just ignore the SPOOL_NOTIFY_OPTION */
3871 switch (Printer->printer_type) {
3872 case PRINTER_HANDLE_IS_PRINTSERVER:
3873 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3876 case PRINTER_HANDLE_IS_PRINTER:
3877 result = printer_notify_info(p, handle, info, p->mem_ctx);
3881 Printer->notify.fnpcn = False;
3887 /********************************************************************
3888 * construct_printer_info_0
3889 * fill a printer_info_0 struct
3890 ********************************************************************/
3892 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3896 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3897 counter_printer_0 *session_counter;
3898 uint32 global_counter;
3901 print_status_struct status;
3903 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3906 count = print_queue_length(snum, &status);
3908 /* check if we already have a counter for this printer */
3909 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3910 if (session_counter->snum == snum)
3914 /* it's the first time, add it to the list */
3915 if (session_counter==NULL) {
3916 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3917 free_a_printer(&ntprinter, 2);
3920 ZERO_STRUCTP(session_counter);
3921 session_counter->snum=snum;
3922 session_counter->counter=0;
3923 DLIST_ADD(counter_list, session_counter);
3927 session_counter->counter++;
3930 * the global_counter should be stored in a TDB as it's common to all the clients
3931 * and should be zeroed on samba startup
3933 global_counter=session_counter->counter;
3935 pstrcpy(chaine,ntprinter->info_2->printername);
3937 init_unistr(&printer->printername, chaine);
3939 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3940 init_unistr(&printer->servername, chaine);
3942 printer->cjobs = count;
3943 printer->total_jobs = 0;
3944 printer->total_bytes = 0;
3946 setuptime = (time_t)ntprinter->info_2->setuptime;
3947 t=gmtime(&setuptime);
3949 printer->year = t->tm_year+1900;
3950 printer->month = t->tm_mon+1;
3951 printer->dayofweek = t->tm_wday;
3952 printer->day = t->tm_mday;
3953 printer->hour = t->tm_hour;
3954 printer->minute = t->tm_min;
3955 printer->second = t->tm_sec;
3956 printer->milliseconds = 0;
3958 printer->global_counter = global_counter;
3959 printer->total_pages = 0;
3961 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3962 printer->major_version = 0x0005; /* NT 5 */
3963 printer->build_version = 0x0893; /* build 2195 */
3965 printer->unknown7 = 0x1;
3966 printer->unknown8 = 0x0;
3967 printer->unknown9 = 0x0;
3968 printer->session_counter = session_counter->counter;
3969 printer->unknown11 = 0x0;
3970 printer->printer_errors = 0x0; /* number of print failure */
3971 printer->unknown13 = 0x0;
3972 printer->unknown14 = 0x1;
3973 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3974 printer->unknown16 = 0x0;
3975 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3976 printer->unknown18 = 0x0;
3977 printer->status = nt_printq_status(status.status);
3978 printer->unknown20 = 0x0;
3979 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3980 printer->unknown22 = 0x0;
3981 printer->unknown23 = 0x6; /* 6 ???*/
3982 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3983 printer->unknown25 = 0;
3984 printer->unknown26 = 0;
3985 printer->unknown27 = 0;
3986 printer->unknown28 = 0;
3987 printer->unknown29 = 0;
3989 free_a_printer(&ntprinter,2);
3993 /********************************************************************
3994 * construct_printer_info_1
3995 * fill a printer_info_1 struct
3996 ********************************************************************/
3997 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4001 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4003 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4006 printer->flags=flags;
4008 if (*ntprinter->info_2->comment == '\0') {
4009 init_unistr(&printer->comment, lp_comment(snum));
4010 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4011 ntprinter->info_2->drivername, lp_comment(snum));
4014 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4015 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4016 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4019 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4021 init_unistr(&printer->description, chaine);
4022 init_unistr(&printer->name, chaine2);
4024 free_a_printer(&ntprinter,2);
4029 /****************************************************************************
4030 Free a DEVMODE struct.
4031 ****************************************************************************/
4033 static void free_dev_mode(DEVICEMODE *dev)
4038 SAFE_FREE(dev->dev_private);
4043 /****************************************************************************
4044 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4045 should be valid upon entry
4046 ****************************************************************************/
4048 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4050 if ( !devmode || !ntdevmode )
4053 init_unistr(&devmode->devicename, ntdevmode->devicename);
4055 init_unistr(&devmode->formname, ntdevmode->formname);
4057 devmode->specversion = ntdevmode->specversion;
4058 devmode->driverversion = ntdevmode->driverversion;
4059 devmode->size = ntdevmode->size;
4060 devmode->driverextra = ntdevmode->driverextra;
4061 devmode->fields = ntdevmode->fields;
4063 devmode->orientation = ntdevmode->orientation;
4064 devmode->papersize = ntdevmode->papersize;
4065 devmode->paperlength = ntdevmode->paperlength;
4066 devmode->paperwidth = ntdevmode->paperwidth;
4067 devmode->scale = ntdevmode->scale;
4068 devmode->copies = ntdevmode->copies;
4069 devmode->defaultsource = ntdevmode->defaultsource;
4070 devmode->printquality = ntdevmode->printquality;
4071 devmode->color = ntdevmode->color;
4072 devmode->duplex = ntdevmode->duplex;
4073 devmode->yresolution = ntdevmode->yresolution;
4074 devmode->ttoption = ntdevmode->ttoption;
4075 devmode->collate = ntdevmode->collate;
4076 devmode->icmmethod = ntdevmode->icmmethod;
4077 devmode->icmintent = ntdevmode->icmintent;
4078 devmode->mediatype = ntdevmode->mediatype;
4079 devmode->dithertype = ntdevmode->dithertype;
4081 if (ntdevmode->nt_dev_private != NULL) {
4082 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4089 /****************************************************************************
4090 Create a DEVMODE struct. Returns malloced memory.
4091 ****************************************************************************/
4093 DEVICEMODE *construct_dev_mode(int snum)
4095 NT_PRINTER_INFO_LEVEL *printer = NULL;
4096 DEVICEMODE *devmode = NULL;
4098 DEBUG(7,("construct_dev_mode\n"));
4100 DEBUGADD(8,("getting printer characteristics\n"));
4102 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4105 if ( !printer->info_2->devmode ) {
4106 DEBUG(5, ("BONG! There was no device mode!\n"));
4110 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4111 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4115 ZERO_STRUCTP(devmode);
4117 DEBUGADD(8,("loading DEVICEMODE\n"));
4119 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4120 free_dev_mode( devmode );
4125 free_a_printer(&printer,2);
4130 /********************************************************************
4131 * construct_printer_info_2
4132 * fill a printer_info_2 struct
4133 ********************************************************************/
4135 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4138 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4140 print_status_struct status;
4142 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4145 count = print_queue_length(snum, &status);
4147 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4148 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4149 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4150 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4151 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4153 if (*ntprinter->info_2->comment == '\0')
4154 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4156 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4158 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4159 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4160 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4161 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4162 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4164 printer->attributes = ntprinter->info_2->attributes;
4166 printer->priority = ntprinter->info_2->priority; /* priority */
4167 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4168 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4169 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4170 printer->status = nt_printq_status(status.status); /* status */
4171 printer->cjobs = count; /* jobs */
4172 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4174 if ( !(printer->devmode = construct_dev_mode(snum)) )
4175 DEBUG(8, ("Returning NULL Devicemode!\n"));
4177 printer->secdesc = NULL;
4179 if ( ntprinter->info_2->secdesc_buf
4180 && ntprinter->info_2->secdesc_buf->len != 0 )
4182 /* don't use talloc_steal() here unless you do a deep steal of all
4183 the SEC_DESC members */
4185 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4186 ntprinter->info_2->secdesc_buf->sec );
4189 free_a_printer(&ntprinter, 2);
4194 /********************************************************************
4195 * construct_printer_info_3
4196 * fill a printer_info_3 struct
4197 ********************************************************************/
4199 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4201 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4202 PRINTER_INFO_3 *printer = NULL;
4204 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4208 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4209 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4213 ZERO_STRUCTP(printer);
4215 /* These are the components of the SD we are returning. */
4217 printer->flags = 0x4;
4219 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4220 /* don't use talloc_steal() here unless you do a deep steal of all
4221 the SEC_DESC members */
4223 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4224 ntprinter->info_2->secdesc_buf->sec );
4227 free_a_printer(&ntprinter, 2);
4229 *pp_printer = printer;
4233 /********************************************************************
4234 * construct_printer_info_4
4235 * fill a printer_info_4 struct
4236 ********************************************************************/
4238 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4240 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4242 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4245 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4246 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4247 printer->attributes = ntprinter->info_2->attributes;
4249 free_a_printer(&ntprinter, 2);
4253 /********************************************************************
4254 * construct_printer_info_5
4255 * fill a printer_info_5 struct
4256 ********************************************************************/
4258 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4260 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4262 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4265 init_unistr(&printer->printername, ntprinter->info_2->printername);
4266 init_unistr(&printer->portname, ntprinter->info_2->portname);
4267 printer->attributes = ntprinter->info_2->attributes;
4269 /* these two are not used by NT+ according to MSDN */
4271 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4272 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4274 free_a_printer(&ntprinter, 2);
4279 /********************************************************************
4280 * construct_printer_info_7
4281 * fill a printer_info_7 struct
4282 ********************************************************************/
4284 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4286 char *guid_str = NULL;
4289 if (is_printer_published(print_hnd, snum, &guid)) {
4290 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4291 strupper_m(guid_str);
4292 init_unistr(&printer->guid, guid_str);
4293 printer->action = SPOOL_DS_PUBLISH;
4295 init_unistr(&printer->guid, "");
4296 printer->action = SPOOL_DS_UNPUBLISH;
4302 /********************************************************************
4303 Spoolss_enumprinters.
4304 ********************************************************************/
4306 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4310 int n_services=lp_numservices();
4311 PRINTER_INFO_1 *tp, *printers=NULL;
4312 PRINTER_INFO_1 current_prt;
4313 WERROR result = WERR_OK;
4315 DEBUG(4,("enum_all_printers_info_1\n"));
4317 for (snum=0; snum<n_services; snum++) {
4318 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4319 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4321 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4322 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4323 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4324 SAFE_FREE(printers);
4329 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4331 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4337 /* check the required size. */
4338 for (i=0; i<*returned; i++)
4339 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4341 if (*needed > offered) {
4342 result = WERR_INSUFFICIENT_BUFFER;
4346 if (!rpcbuf_alloc_size(buffer, *needed)) {
4347 result = WERR_NOMEM;
4351 /* fill the buffer with the structures */
4352 for (i=0; i<*returned; i++)
4353 smb_io_printer_info_1("", buffer, &printers[i], 0);
4358 SAFE_FREE(printers);
4360 if ( !W_ERROR_IS_OK(result) )
4366 /********************************************************************
4367 enum_all_printers_info_1_local.
4368 *********************************************************************/
4370 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4372 DEBUG(4,("enum_all_printers_info_1_local\n"));
4374 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4377 /********************************************************************
4378 enum_all_printers_info_1_name.
4379 *********************************************************************/
4381 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4385 DEBUG(4,("enum_all_printers_info_1_name\n"));
4387 if ((name[0] == '\\') && (name[1] == '\\'))
4390 if (is_myname_or_ipaddr(s)) {
4391 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4394 return WERR_INVALID_NAME;
4397 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4398 /********************************************************************
4399 enum_all_printers_info_1_remote.
4400 *********************************************************************/
4402 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4404 PRINTER_INFO_1 *printer;
4405 fstring printername;
4408 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4409 WERROR result = WERR_OK;
4411 /* JFM: currently it's more a place holder than anything else.
4412 * In the spooler world there is a notion of server registration.
4413 * the print servers are registered on the PDC (in the same domain)
4415 * We should have a TDB here. The registration is done thru an
4416 * undocumented RPC call.
4419 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4424 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4425 slprintf(desc, sizeof(desc)-1,"%s", name);
4426 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4428 init_unistr(&printer->description, desc);
4429 init_unistr(&printer->name, printername);
4430 init_unistr(&printer->comment, comment);
4431 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4433 /* check the required size. */
4434 *needed += spoolss_size_printer_info_1(printer);
4436 if (*needed > offered) {
4437 result = WERR_INSUFFICIENT_BUFFER;
4441 if (!rpcbuf_alloc_size(buffer, *needed)) {
4442 result = WERR_NOMEM;
4446 /* fill the buffer with the structures */
4447 smb_io_printer_info_1("", buffer, printer, 0);
4453 if ( !W_ERROR_IS_OK(result) )
4461 /********************************************************************
4462 enum_all_printers_info_1_network.
4463 *********************************************************************/
4465 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4469 DEBUG(4,("enum_all_printers_info_1_network\n"));
4471 /* If we respond to a enum_printers level 1 on our name with flags
4472 set to PRINTER_ENUM_REMOTE with a list of printers then these
4473 printers incorrectly appear in the APW browse list.
4474 Specifically the printers for the server appear at the workgroup
4475 level where all the other servers in the domain are
4476 listed. Windows responds to this call with a
4477 WERR_CAN_NOT_COMPLETE so we should do the same. */
4479 if (name[0] == '\\' && name[1] == '\\')
4482 if (is_myname_or_ipaddr(s))
4483 return WERR_CAN_NOT_COMPLETE;
4485 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4488 /********************************************************************
4489 * api_spoolss_enumprinters
4491 * called from api_spoolss_enumprinters (see this to understand)
4492 ********************************************************************/
4494 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4498 int n_services=lp_numservices();
4499 PRINTER_INFO_2 *tp, *printers=NULL;
4500 PRINTER_INFO_2 current_prt;
4501 WERROR result = WERR_OK;
4503 for (snum=0; snum<n_services; snum++) {
4504 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4505 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4507 if (construct_printer_info_2(NULL, ¤t_prt, snum))
4509 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4510 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4511 SAFE_FREE(printers);
4516 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4519 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4526 /* check the required size. */
4527 for (i=0; i<*returned; i++)
4528 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4530 if (*needed > offered) {
4531 result = WERR_INSUFFICIENT_BUFFER;
4535 if (!rpcbuf_alloc_size(buffer, *needed)) {
4536 result = WERR_NOMEM;
4540 /* fill the buffer with the structures */
4541 for (i=0; i<*returned; i++)
4542 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4547 for (i=0; i<*returned; i++)
4548 free_devmode(printers[i].devmode);
4550 SAFE_FREE(printers);
4552 if ( !W_ERROR_IS_OK(result) )
4558 /********************************************************************
4559 * handle enumeration of printers at level 1
4560 ********************************************************************/
4562 static WERROR enumprinters_level1( uint32 flags, fstring name,
4563 RPC_BUFFER *buffer, uint32 offered,
4564 uint32 *needed, uint32 *returned)
4566 /* Not all the flags are equals */
4568 if (flags & PRINTER_ENUM_LOCAL)
4569 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4571 if (flags & PRINTER_ENUM_NAME)
4572 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4574 #if 0 /* JERRY - disabled for now */
4575 if (flags & PRINTER_ENUM_REMOTE)
4576 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4579 if (flags & PRINTER_ENUM_NETWORK)
4580 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4582 return WERR_OK; /* NT4sp5 does that */
4585 /********************************************************************
4586 * handle enumeration of printers at level 2
4587 ********************************************************************/
4589 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4590 RPC_BUFFER *buffer, uint32 offered,
4591 uint32 *needed, uint32 *returned)
4593 char *s = servername;
4595 if (flags & PRINTER_ENUM_LOCAL) {
4596 return enum_all_printers_info_2(buffer, offered, needed, returned);
4599 if (flags & PRINTER_ENUM_NAME) {
4600 if ((servername[0] == '\\') && (servername[1] == '\\'))
4602 if (is_myname_or_ipaddr(s))
4603 return enum_all_printers_info_2(buffer, offered, needed, returned);
4605 return WERR_INVALID_NAME;
4608 if (flags & PRINTER_ENUM_REMOTE)
4609 return WERR_UNKNOWN_LEVEL;
4614 /********************************************************************
4615 * handle enumeration of printers at level 5
4616 ********************************************************************/
4618 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4619 RPC_BUFFER *buffer, uint32 offered,
4620 uint32 *needed, uint32 *returned)
4622 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4626 /********************************************************************
4627 * api_spoolss_enumprinters
4629 * called from api_spoolss_enumprinters (see this to understand)
4630 ********************************************************************/
4632 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4634 uint32 flags = q_u->flags;
4635 UNISTR2 *servername = &q_u->servername;
4636 uint32 level = q_u->level;
4637 RPC_BUFFER *buffer = NULL;
4638 uint32 offered = q_u->offered;
4639 uint32 *needed = &r_u->needed;
4640 uint32 *returned = &r_u->returned;
4644 /* that's an [in out] buffer */
4646 if ( q_u->buffer ) {
4647 rpcbuf_move(q_u->buffer, &r_u->buffer);
4648 buffer = r_u->buffer;
4651 DEBUG(4,("_spoolss_enumprinters\n"));
4658 * flags==PRINTER_ENUM_NAME
4659 * if name=="" then enumerates all printers
4660 * if name!="" then enumerate the printer
4661 * flags==PRINTER_ENUM_REMOTE
4662 * name is NULL, enumerate printers
4663 * Level 2: name!="" enumerates printers, name can't be NULL
4664 * Level 3: doesn't exist
4665 * Level 4: does a local registry lookup
4666 * Level 5: same as Level 2
4669 unistr2_to_ascii(name, servername, sizeof(name)-1);
4674 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4676 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4678 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4683 return WERR_UNKNOWN_LEVEL;
4686 /****************************************************************************
4687 ****************************************************************************/
4689 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4691 PRINTER_INFO_0 *printer=NULL;
4692 WERROR result = WERR_OK;
4694 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4697 construct_printer_info_0(print_hnd, printer, snum);
4699 /* check the required size. */
4700 *needed += spoolss_size_printer_info_0(printer);
4702 if (*needed > offered) {
4703 result = WERR_INSUFFICIENT_BUFFER;
4707 if (!rpcbuf_alloc_size(buffer, *needed)) {
4708 result = WERR_NOMEM;
4712 /* fill the buffer with the structures */
4713 smb_io_printer_info_0("", buffer, printer, 0);
4723 /****************************************************************************
4724 ****************************************************************************/
4726 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4728 PRINTER_INFO_1 *printer=NULL;
4729 WERROR result = WERR_OK;
4731 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4734 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4736 /* check the required size. */
4737 *needed += spoolss_size_printer_info_1(printer);
4739 if (*needed > offered) {
4740 result = WERR_INSUFFICIENT_BUFFER;
4744 if (!rpcbuf_alloc_size(buffer, *needed)) {
4745 result = WERR_NOMEM;
4749 /* fill the buffer with the structures */
4750 smb_io_printer_info_1("", buffer, printer, 0);
4759 /****************************************************************************
4760 ****************************************************************************/
4762 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4764 PRINTER_INFO_2 *printer=NULL;
4765 WERROR result = WERR_OK;
4767 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4770 construct_printer_info_2(print_hnd, printer, snum);
4772 /* check the required size. */
4773 *needed += spoolss_size_printer_info_2(printer);
4775 if (*needed > offered) {
4776 result = WERR_INSUFFICIENT_BUFFER;
4780 if (!rpcbuf_alloc_size(buffer, *needed)) {
4781 result = WERR_NOMEM;
4785 /* fill the buffer with the structures */
4786 if (!smb_io_printer_info_2("", buffer, printer, 0))
4787 result = WERR_NOMEM;
4791 free_printer_info_2(printer);
4796 /****************************************************************************
4797 ****************************************************************************/
4799 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4801 PRINTER_INFO_3 *printer=NULL;
4802 WERROR result = WERR_OK;
4804 if (!construct_printer_info_3(print_hnd, &printer, snum))
4807 /* check the required size. */
4808 *needed += spoolss_size_printer_info_3(printer);
4810 if (*needed > offered) {
4811 result = WERR_INSUFFICIENT_BUFFER;
4815 if (!rpcbuf_alloc_size(buffer, *needed)) {
4816 result = WERR_NOMEM;
4820 /* fill the buffer with the structures */
4821 smb_io_printer_info_3("", buffer, printer, 0);
4825 free_printer_info_3(printer);
4830 /****************************************************************************
4831 ****************************************************************************/
4833 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4835 PRINTER_INFO_4 *printer=NULL;
4836 WERROR result = WERR_OK;
4838 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4841 if (!construct_printer_info_4(print_hnd, printer, snum))
4844 /* check the required size. */
4845 *needed += spoolss_size_printer_info_4(printer);
4847 if (*needed > offered) {
4848 result = WERR_INSUFFICIENT_BUFFER;
4852 if (!rpcbuf_alloc_size(buffer, *needed)) {
4853 result = WERR_NOMEM;
4857 /* fill the buffer with the structures */
4858 smb_io_printer_info_4("", buffer, printer, 0);
4862 free_printer_info_4(printer);
4867 /****************************************************************************
4868 ****************************************************************************/
4870 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4872 PRINTER_INFO_5 *printer=NULL;
4873 WERROR result = WERR_OK;
4875 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4878 if (!construct_printer_info_5(print_hnd, printer, snum))
4881 /* check the required size. */
4882 *needed += spoolss_size_printer_info_5(printer);
4884 if (*needed > offered) {
4885 result = WERR_INSUFFICIENT_BUFFER;
4889 if (!rpcbuf_alloc_size(buffer, *needed)) {
4890 result = WERR_NOMEM;
4894 /* fill the buffer with the structures */
4895 smb_io_printer_info_5("", buffer, printer, 0);
4899 free_printer_info_5(printer);
4904 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4906 PRINTER_INFO_7 *printer=NULL;
4907 WERROR result = WERR_OK;
4909 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4912 if (!construct_printer_info_7(print_hnd, printer, snum))
4915 /* check the required size. */
4916 *needed += spoolss_size_printer_info_7(printer);
4918 if (*needed > offered) {
4919 result = WERR_INSUFFICIENT_BUFFER;
4923 if (!rpcbuf_alloc_size(buffer, *needed)) {
4924 result = WERR_NOMEM;
4929 /* fill the buffer with the structures */
4930 smb_io_printer_info_7("", buffer, printer, 0);
4934 free_printer_info_7(printer);
4939 /****************************************************************************
4940 ****************************************************************************/
4942 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4944 POLICY_HND *handle = &q_u->handle;
4945 uint32 level = q_u->level;
4946 RPC_BUFFER *buffer = NULL;
4947 uint32 offered = q_u->offered;
4948 uint32 *needed = &r_u->needed;
4949 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4953 /* that's an [in out] buffer */
4955 if ( q_u->buffer ) {
4956 rpcbuf_move(q_u->buffer, &r_u->buffer);
4957 buffer = r_u->buffer;
4962 if (!get_printer_snum(p, handle, &snum))
4967 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4969 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4971 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4973 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4975 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4977 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4979 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4981 return WERR_UNKNOWN_LEVEL;
4984 /********************************************************************
4985 * fill a DRIVER_INFO_1 struct
4986 ********************************************************************/
4988 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4990 init_unistr( &info->name, driver.info_3->name);
4993 /********************************************************************
4994 * construct_printer_driver_info_1
4995 ********************************************************************/
4997 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4999 NT_PRINTER_INFO_LEVEL *printer = NULL;
5000 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5002 ZERO_STRUCT(driver);
5004 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5005 return WERR_INVALID_PRINTER_NAME;
5007 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5008 return WERR_UNKNOWN_PRINTER_DRIVER;
5010 fill_printer_driver_info_1(info, driver, servername, architecture);
5012 free_a_printer(&printer,2);
5017 /********************************************************************
5018 * construct_printer_driver_info_2
5019 * fill a printer_info_2 struct
5020 ********************************************************************/
5022 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5026 info->version=driver.info_3->cversion;
5028 init_unistr( &info->name, driver.info_3->name );
5029 init_unistr( &info->architecture, driver.info_3->environment );
5032 if (strlen(driver.info_3->driverpath)) {
5033 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5034 init_unistr( &info->driverpath, temp );
5036 init_unistr( &info->driverpath, "" );
5038 if (strlen(driver.info_3->datafile)) {
5039 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5040 init_unistr( &info->datafile, temp );
5042 init_unistr( &info->datafile, "" );
5044 if (strlen(driver.info_3->configfile)) {
5045 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5046 init_unistr( &info->configfile, temp );
5048 init_unistr( &info->configfile, "" );
5051 /********************************************************************
5052 * construct_printer_driver_info_2
5053 * fill a printer_info_2 struct
5054 ********************************************************************/
5056 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5058 NT_PRINTER_INFO_LEVEL *printer = NULL;
5059 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5061 ZERO_STRUCT(printer);
5062 ZERO_STRUCT(driver);
5064 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5065 return WERR_INVALID_PRINTER_NAME;
5067 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5068 return WERR_UNKNOWN_PRINTER_DRIVER;
5070 fill_printer_driver_info_2(info, driver, servername);
5072 free_a_printer(&printer,2);
5077 /********************************************************************
5078 * copy a strings array and convert to UNICODE
5080 * convert an array of ascii string to a UNICODE string
5081 ********************************************************************/
5083 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5091 DEBUG(6,("init_unistr_array\n"));
5102 v = ""; /* hack to handle null lists */
5105 /* hack to allow this to be used in places other than when generating
5106 the list of dependent files */
5109 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5113 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5115 /* add one extra unit16 for the second terminating NULL */
5117 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5118 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5126 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5131 /* special case for ""; we need to add both NULL's here */
5133 (*uni_array)[j++]=0x0000;
5134 (*uni_array)[j]=0x0000;
5137 DEBUGADD(6,("last one:done\n"));
5139 /* return size of array in uint16's */
5144 /********************************************************************
5145 * construct_printer_info_3
5146 * fill a printer_info_3 struct
5147 ********************************************************************/
5149 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5155 info->version=driver.info_3->cversion;
5157 init_unistr( &info->name, driver.info_3->name );
5158 init_unistr( &info->architecture, driver.info_3->environment );
5160 if (strlen(driver.info_3->driverpath)) {
5161 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5162 init_unistr( &info->driverpath, temp );
5164 init_unistr( &info->driverpath, "" );
5166 if (strlen(driver.info_3->datafile)) {
5167 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5168 init_unistr( &info->datafile, temp );
5170 init_unistr( &info->datafile, "" );
5172 if (strlen(driver.info_3->configfile)) {
5173 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5174 init_unistr( &info->configfile, temp );
5176 init_unistr( &info->configfile, "" );
5178 if (strlen(driver.info_3->helpfile)) {
5179 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5180 init_unistr( &info->helpfile, temp );
5182 init_unistr( &info->helpfile, "" );
5184 init_unistr( &info->monitorname, driver.info_3->monitorname );
5185 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5187 info->dependentfiles=NULL;
5188 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5191 /********************************************************************
5192 * construct_printer_info_3
5193 * fill a printer_info_3 struct
5194 ********************************************************************/
5196 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5198 NT_PRINTER_INFO_LEVEL *printer = NULL;
5199 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5201 ZERO_STRUCT(driver);
5203 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5204 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5205 if (!W_ERROR_IS_OK(status))
5206 return WERR_INVALID_PRINTER_NAME;
5208 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5209 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5214 * I put this code in during testing. Helpful when commenting out the
5215 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5216 * as win2k always queries the driver using an infor level of 6.
5217 * I've left it in (but ifdef'd out) because I'll probably
5218 * use it in experimentation again in the future. --jerry 22/01/2002
5221 if (!W_ERROR_IS_OK(status)) {
5223 * Is this a W2k client ?
5226 /* Yes - try again with a WinNT driver. */
5228 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5229 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5233 if (!W_ERROR_IS_OK(status)) {
5234 free_a_printer(&printer,2);
5235 return WERR_UNKNOWN_PRINTER_DRIVER;
5243 fill_printer_driver_info_3(info, driver, servername);
5245 free_a_printer(&printer,2);
5250 /********************************************************************
5251 * construct_printer_info_6
5252 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5253 ********************************************************************/
5255 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5261 memset(&nullstr, '\0', sizeof(fstring));
5263 info->version=driver.info_3->cversion;
5265 init_unistr( &info->name, driver.info_3->name );
5266 init_unistr( &info->architecture, driver.info_3->environment );
5268 if (strlen(driver.info_3->driverpath)) {
5269 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5270 init_unistr( &info->driverpath, temp );
5272 init_unistr( &info->driverpath, "" );
5274 if (strlen(driver.info_3->datafile)) {
5275 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5276 init_unistr( &info->datafile, temp );
5278 init_unistr( &info->datafile, "" );
5280 if (strlen(driver.info_3->configfile)) {
5281 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5282 init_unistr( &info->configfile, temp );
5284 init_unistr( &info->configfile, "" );
5286 if (strlen(driver.info_3->helpfile)) {
5287 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5288 init_unistr( &info->helpfile, temp );
5290 init_unistr( &info->helpfile, "" );
5292 init_unistr( &info->monitorname, driver.info_3->monitorname );
5293 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5295 info->dependentfiles = NULL;
5296 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5298 info->previousdrivernames=NULL;
5299 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5301 info->driver_date.low=0;
5302 info->driver_date.high=0;
5305 info->driver_version_low=0;
5306 info->driver_version_high=0;
5308 init_unistr( &info->mfgname, "");
5309 init_unistr( &info->oem_url, "");
5310 init_unistr( &info->hardware_id, "");
5311 init_unistr( &info->provider, "");
5314 /********************************************************************
5315 * construct_printer_info_6
5316 * fill a printer_info_6 struct
5317 ********************************************************************/
5319 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5320 fstring servername, fstring architecture, uint32 version)
5322 NT_PRINTER_INFO_LEVEL *printer = NULL;
5323 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5326 ZERO_STRUCT(driver);
5328 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5330 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5332 if (!W_ERROR_IS_OK(status))
5333 return WERR_INVALID_PRINTER_NAME;
5335 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5337 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5339 if (!W_ERROR_IS_OK(status))
5342 * Is this a W2k client ?
5346 free_a_printer(&printer,2);
5347 return WERR_UNKNOWN_PRINTER_DRIVER;
5350 /* Yes - try again with a WinNT driver. */
5352 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5353 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5354 if (!W_ERROR_IS_OK(status)) {
5355 free_a_printer(&printer,2);
5356 return WERR_UNKNOWN_PRINTER_DRIVER;
5360 fill_printer_driver_info_6(info, driver, servername);
5362 free_a_printer(&printer,2);
5363 free_a_printer_driver(driver, 3);
5368 /****************************************************************************
5369 ****************************************************************************/
5371 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5373 SAFE_FREE(info->dependentfiles);
5376 /****************************************************************************
5377 ****************************************************************************/
5379 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5381 SAFE_FREE(info->dependentfiles);
5384 /****************************************************************************
5385 ****************************************************************************/
5387 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5389 DRIVER_INFO_1 *info=NULL;
5392 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5395 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5396 if (!W_ERROR_IS_OK(result))
5399 /* check the required size. */
5400 *needed += spoolss_size_printer_driver_info_1(info);
5402 if (*needed > offered) {
5403 result = WERR_INSUFFICIENT_BUFFER;
5407 if (!rpcbuf_alloc_size(buffer, *needed)) {
5408 result = WERR_NOMEM;
5412 /* fill the buffer with the structures */
5413 smb_io_printer_driver_info_1("", buffer, info, 0);
5422 /****************************************************************************
5423 ****************************************************************************/
5425 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5427 DRIVER_INFO_2 *info=NULL;
5430 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5433 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5434 if (!W_ERROR_IS_OK(result))
5437 /* check the required size. */
5438 *needed += spoolss_size_printer_driver_info_2(info);
5440 if (*needed > offered) {
5441 result = WERR_INSUFFICIENT_BUFFER;
5445 if (!rpcbuf_alloc_size(buffer, *needed)) {
5446 result = WERR_NOMEM;
5450 /* fill the buffer with the structures */
5451 smb_io_printer_driver_info_2("", buffer, info, 0);
5460 /****************************************************************************
5461 ****************************************************************************/
5463 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5470 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5471 if (!W_ERROR_IS_OK(result))
5474 /* check the required size. */
5475 *needed += spoolss_size_printer_driver_info_3(&info);
5477 if (*needed > offered) {
5478 result = WERR_INSUFFICIENT_BUFFER;
5482 if (!rpcbuf_alloc_size(buffer, *needed)) {
5483 result = WERR_NOMEM;
5487 /* fill the buffer with the structures */
5488 smb_io_printer_driver_info_3("", buffer, &info, 0);
5491 free_printer_driver_info_3(&info);
5496 /****************************************************************************
5497 ****************************************************************************/
5499 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5506 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5507 if (!W_ERROR_IS_OK(result))
5510 /* check the required size. */
5511 *needed += spoolss_size_printer_driver_info_6(&info);
5513 if (*needed > offered) {
5514 result = WERR_INSUFFICIENT_BUFFER;
5518 if (!rpcbuf_alloc_size(buffer, *needed)) {
5519 result = WERR_NOMEM;
5523 /* fill the buffer with the structures */
5524 smb_io_printer_driver_info_6("", buffer, &info, 0);
5527 free_printer_driver_info_6(&info);
5532 /****************************************************************************
5533 ****************************************************************************/
5535 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5537 POLICY_HND *handle = &q_u->handle;
5538 UNISTR2 *uni_arch = &q_u->architecture;
5539 uint32 level = q_u->level;
5540 uint32 clientmajorversion = q_u->clientmajorversion;
5541 RPC_BUFFER *buffer = NULL;
5542 uint32 offered = q_u->offered;
5543 uint32 *needed = &r_u->needed;
5544 uint32 *servermajorversion = &r_u->servermajorversion;
5545 uint32 *serverminorversion = &r_u->serverminorversion;
5546 Printer_entry *printer;
5549 fstring architecture;
5552 /* that's an [in out] buffer */
5554 if ( q_u->buffer ) {
5555 rpcbuf_move(q_u->buffer, &r_u->buffer);
5556 buffer = r_u->buffer;
5559 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5561 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5562 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5563 return WERR_INVALID_PRINTER_NAME;
5567 *servermajorversion = 0;
5568 *serverminorversion = 0;
5570 fstrcpy(servername, get_server_name( printer ));
5571 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5573 if (!get_printer_snum(p, handle, &snum))
5578 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5580 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5582 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5584 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5587 /* apparently this call is the equivalent of
5588 EnumPrinterDataEx() for the DsDriver key */
5593 return WERR_UNKNOWN_LEVEL;
5596 /****************************************************************************
5597 ****************************************************************************/
5599 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5601 POLICY_HND *handle = &q_u->handle;
5603 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5606 DEBUG(3,("Error in startpageprinter printer handle\n"));
5610 Printer->page_started=True;
5614 /****************************************************************************
5615 ****************************************************************************/
5617 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5619 POLICY_HND *handle = &q_u->handle;
5622 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5625 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5629 if (!get_printer_snum(p, handle, &snum))
5632 Printer->page_started=False;
5633 print_job_endpage(snum, Printer->jobid);
5638 /********************************************************************
5639 * api_spoolss_getprinter
5640 * called from the spoolss dispatcher
5642 ********************************************************************/
5644 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5646 POLICY_HND *handle = &q_u->handle;
5647 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5648 uint32 *jobid = &r_u->jobid;
5650 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5654 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5655 struct current_user user;
5658 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5662 get_current_user(&user, p);
5665 * a nice thing with NT is it doesn't listen to what you tell it.
5666 * when asked to send _only_ RAW datas, it tries to send datas
5669 * So I add checks like in NT Server ...
5672 if (info_1->p_datatype != 0) {
5673 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5674 if (strcmp(datatype, "RAW") != 0) {
5676 return WERR_INVALID_DATATYPE;
5680 /* get the share number of the printer */
5681 if (!get_printer_snum(p, handle, &snum)) {
5685 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5687 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5689 /* An error occured in print_job_start() so return an appropriate
5692 if (Printer->jobid == -1) {
5693 return map_werror_from_unix(errno);
5696 Printer->document_started=True;
5697 (*jobid) = Printer->jobid;
5702 /********************************************************************
5703 * api_spoolss_getprinter
5704 * called from the spoolss dispatcher
5706 ********************************************************************/
5708 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5710 POLICY_HND *handle = &q_u->handle;
5712 return _spoolss_enddocprinter_internal(p, handle);
5715 /****************************************************************************
5716 ****************************************************************************/
5718 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5720 POLICY_HND *handle = &q_u->handle;
5721 uint32 buffer_size = q_u->buffer_size;
5722 uint8 *buffer = q_u->buffer;
5723 uint32 *buffer_written = &q_u->buffer_size2;
5725 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5728 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5729 r_u->buffer_written = q_u->buffer_size2;
5733 if (!get_printer_snum(p, handle, &snum))
5736 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5737 (SMB_OFF_T)-1, (size_t)buffer_size);
5738 if (*buffer_written == (uint32)-1) {
5739 r_u->buffer_written = 0;
5740 if (errno == ENOSPC)
5741 return WERR_NO_SPOOL_SPACE;
5743 return WERR_ACCESS_DENIED;
5746 r_u->buffer_written = q_u->buffer_size2;
5751 /********************************************************************
5752 * api_spoolss_getprinter
5753 * called from the spoolss dispatcher
5755 ********************************************************************/
5757 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5760 struct current_user user;
5762 WERROR errcode = WERR_BADFUNC;
5763 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5765 get_current_user(&user, p);
5768 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5772 if (!get_printer_snum(p, handle, &snum))
5776 case PRINTER_CONTROL_PAUSE:
5777 if (print_queue_pause(&user, snum, &errcode)) {
5781 case PRINTER_CONTROL_RESUME:
5782 case PRINTER_CONTROL_UNPAUSE:
5783 if (print_queue_resume(&user, snum, &errcode)) {
5787 case PRINTER_CONTROL_PURGE:
5788 if (print_queue_purge(&user, snum, &errcode)) {
5793 return WERR_UNKNOWN_LEVEL;
5799 /********************************************************************
5800 * api_spoolss_abortprinter
5801 * From MSDN: "Deletes printer's spool file if printer is configured
5803 ********************************************************************/
5805 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5807 POLICY_HND *handle = &q_u->handle;
5808 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5810 struct current_user user;
5811 WERROR errcode = WERR_OK;
5814 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5818 if (!get_printer_snum(p, handle, &snum))
5821 get_current_user( &user, p );
5823 print_job_delete( &user, snum, Printer->jobid, &errcode );
5828 /********************************************************************
5829 * called by spoolss_api_setprinter
5830 * when updating a printer description
5831 ********************************************************************/
5833 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5834 const SPOOL_PRINTER_INFO_LEVEL *info,
5835 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5837 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5841 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5843 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5844 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5845 OUR_HANDLE(handle)));
5847 result = WERR_BADFID;
5851 /* Check the user has permissions to change the security
5852 descriptor. By experimentation with two NT machines, the user
5853 requires Full Access to the printer to change security
5856 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5857 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5858 result = WERR_ACCESS_DENIED;
5862 /* NT seems to like setting the security descriptor even though
5863 nothing may have actually changed. */
5865 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5867 if (DEBUGLEVEL >= 10) {
5871 the_acl = old_secdesc_ctr->sec->dacl;
5872 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5873 PRINTERNAME(snum), the_acl->num_aces));
5875 for (i = 0; i < the_acl->num_aces; i++) {
5878 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5880 DEBUG(10, ("%s 0x%08x\n", sid_str,
5881 the_acl->ace[i].info.mask));
5884 the_acl = secdesc_ctr->sec->dacl;
5887 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5888 PRINTERNAME(snum), the_acl->num_aces));
5890 for (i = 0; i < the_acl->num_aces; i++) {
5893 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5895 DEBUG(10, ("%s 0x%08x\n", sid_str,
5896 the_acl->ace[i].info.mask));
5899 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5903 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5905 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5910 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5917 /********************************************************************
5918 Canonicalize printer info from a client
5920 ATTN: It does not matter what we set the servername to hear
5921 since we do the necessary work in get_a_printer() to set it to
5922 the correct value based on what the client sent in the
5923 _spoolss_open_printer_ex().
5924 ********************************************************************/
5926 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5928 fstring printername;
5931 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5932 "portname=%s drivername=%s comment=%s location=%s\n",
5933 info->servername, info->printername, info->sharename,
5934 info->portname, info->drivername, info->comment, info->location));
5936 /* we force some elements to "correct" values */
5937 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5938 fstrcpy(info->sharename, lp_servicename(snum));
5940 /* check to see if we allow printername != sharename */
5942 if ( lp_force_printername(snum) ) {
5943 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5944 global_myname(), info->sharename );
5947 /* make sure printername is in \\server\printername format */
5949 fstrcpy( printername, info->printername );
5951 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5952 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5956 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5957 global_myname(), p );
5960 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5961 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5968 /****************************************************************************
5969 ****************************************************************************/
5971 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5973 char *cmd = lp_addprinter_cmd();
5979 fstring remote_machine = "%m";
5980 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5981 BOOL is_print_op = False;
5983 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5985 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5986 cmd, printer->info_2->printername, printer->info_2->sharename,
5987 printer->info_2->portname, printer->info_2->drivername,
5988 printer->info_2->location, printer->info_2->comment, remote_machine);
5991 is_print_op = user_has_privileges( token, &se_printop );
5993 DEBUG(10,("Running [%s]\n", command));
5995 /********* BEGIN SePrintOperatorPrivilege **********/
6000 if ( (ret = smbrun(command, &fd)) == 0 ) {
6001 /* Tell everyone we updated smb.conf. */
6002 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6008 /********* END SePrintOperatorPrivilege **********/
6010 DEBUGADD(10,("returned [%d]\n", ret));
6018 /* reload our services immediately */
6019 reload_services( False );
6022 /* Get lines and convert them back to dos-codepage */
6023 qlines = fd_lines_load(fd, &numlines);
6024 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6027 /* Set the portname to what the script says the portname should be. */
6028 /* but don't require anything to be return from the script exit a good error code */
6031 /* Set the portname to what the script says the portname should be. */
6032 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6033 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6036 file_lines_free(qlines);
6040 /********************************************************************
6041 * Called by spoolss_api_setprinter
6042 * when updating a printer description.
6043 ********************************************************************/
6045 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6046 const SPOOL_PRINTER_INFO_LEVEL *info,
6047 DEVICEMODE *devmode)
6050 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6051 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6056 DEBUG(8,("update_printer\n"));
6061 result = WERR_BADFID;
6065 if (!get_printer_snum(p, handle, &snum)) {
6066 result = WERR_BADFID;
6070 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6071 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6072 result = WERR_BADFID;
6076 DEBUGADD(8,("Converting info_2 struct\n"));
6079 * convert_printer_info converts the incoming
6080 * info from the client and overwrites the info
6081 * just read from the tdb in the pointer 'printer'.
6084 if (!convert_printer_info(info, printer, level)) {
6085 result = WERR_NOMEM;
6090 /* we have a valid devmode
6091 convert it and link it*/
6093 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6094 if (!convert_devicemode(printer->info_2->printername, devmode,
6095 &printer->info_2->devmode)) {
6096 result = WERR_NOMEM;
6101 /* Do sanity check on the requested changes for Samba */
6103 if (!check_printer_ok(printer->info_2, snum)) {
6104 result = WERR_INVALID_PARAM;
6108 /* FIXME!!! If the driver has changed we really should verify that
6109 it is installed before doing much else --jerry */
6111 /* Check calling user has permission to update printer description */
6113 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6114 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6115 result = WERR_ACCESS_DENIED;
6119 /* Call addprinter hook */
6120 /* Check changes to see if this is really needed */
6122 if ( *lp_addprinter_cmd()
6123 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6124 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6125 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6126 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6128 /* add_printer_hook() will call reload_services() */
6130 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6131 result = WERR_ACCESS_DENIED;
6137 * When a *new* driver is bound to a printer, the drivername is used to
6138 * lookup previously saved driver initialization info, which is then
6139 * bound to the printer, simulating what happens in the Windows arch.
6141 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6143 if (!set_driver_init(printer, 2))
6145 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6146 printer->info_2->drivername));
6149 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6150 printer->info_2->drivername));
6152 notify_printer_driver(snum, printer->info_2->drivername);
6156 * flag which changes actually occured. This is a small subset of
6157 * all the possible changes. We also have to update things in the
6161 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6162 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6163 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6164 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6166 notify_printer_comment(snum, printer->info_2->comment);
6169 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6170 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6171 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6172 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6174 notify_printer_sharename(snum, printer->info_2->sharename);
6177 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6180 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6183 pname = printer->info_2->printername;
6186 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6187 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6188 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6190 notify_printer_printername( snum, pname );
6193 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6194 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6195 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6196 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6198 notify_printer_port(snum, printer->info_2->portname);
6201 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6202 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6203 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6204 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6206 notify_printer_location(snum, printer->info_2->location);
6209 /* here we need to update some more DsSpooler keys */
6210 /* uNCName, serverName, shortServerName */
6212 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6213 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6214 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6215 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6216 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6218 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6219 global_myname(), printer->info_2->sharename );
6220 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6221 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6222 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6224 /* Update printer info */
6225 result = mod_a_printer(printer, 2);
6228 free_a_printer(&printer, 2);
6229 free_a_printer(&old_printer, 2);
6235 /****************************************************************************
6236 ****************************************************************************/
6237 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6238 const SPOOL_PRINTER_INFO_LEVEL *info)
6241 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6243 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6245 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6250 if (!get_printer_snum(p, handle, &snum))
6253 nt_printer_publish(Printer, snum, info7->action);
6257 return WERR_UNKNOWN_LEVEL;
6260 /****************************************************************************
6261 ****************************************************************************/
6263 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6265 POLICY_HND *handle = &q_u->handle;
6266 uint32 level = q_u->level;
6267 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6268 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6269 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6270 uint32 command = q_u->command;
6273 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6276 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6280 /* check the level */
6283 return control_printer(handle, command, p);
6285 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6286 if (!W_ERROR_IS_OK(result))
6289 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6292 return update_printer_sec(handle, level, info, p,
6295 return publish_or_unpublish_printer(p, handle, info);
6297 return WERR_UNKNOWN_LEVEL;
6301 /****************************************************************************
6302 ****************************************************************************/
6304 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6306 POLICY_HND *handle = &q_u->handle;
6307 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6310 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6314 if (Printer->notify.client_connected==True) {
6317 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6319 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6320 !get_printer_snum(p, handle, &snum) )
6323 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6326 Printer->notify.flags=0;
6327 Printer->notify.options=0;
6328 Printer->notify.localmachine[0]='\0';
6329 Printer->notify.printerlocal=0;
6330 if (Printer->notify.option)
6331 free_spool_notify_option(&Printer->notify.option);
6332 Printer->notify.client_connected=False;
6337 /****************************************************************************
6338 ****************************************************************************/
6340 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6342 /* that's an [in out] buffer */
6345 rpcbuf_move(q_u->buffer, &r_u->buffer);
6348 return WERR_INVALID_PARAM; /* this is what a NT server
6349 returns for AddJob. AddJob
6350 must fail on non-local
6354 /****************************************************************************
6355 ****************************************************************************/
6357 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6358 int position, int snum,
6359 NT_PRINTER_INFO_LEVEL *ntprinter)
6363 t=gmtime(&queue->time);
6365 job_info->jobid=queue->job;
6366 init_unistr(&job_info->printername, lp_servicename(snum));
6367 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6368 init_unistr(&job_info->username, queue->fs_user);
6369 init_unistr(&job_info->document, queue->fs_file);
6370 init_unistr(&job_info->datatype, "RAW");
6371 init_unistr(&job_info->text_status, "");
6372 job_info->status=nt_printj_status(queue->status);
6373 job_info->priority=queue->priority;
6374 job_info->position=position;
6375 job_info->totalpages=queue->page_count;
6376 job_info->pagesprinted=0;
6378 make_systemtime(&job_info->submitted, t);
6381 /****************************************************************************
6382 ****************************************************************************/
6384 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6385 int position, int snum,
6386 NT_PRINTER_INFO_LEVEL *ntprinter,
6387 DEVICEMODE *devmode)
6391 t=gmtime(&queue->time);
6393 job_info->jobid=queue->job;
6395 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6397 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6398 init_unistr(&job_info->username, queue->fs_user);
6399 init_unistr(&job_info->document, queue->fs_file);
6400 init_unistr(&job_info->notifyname, queue->fs_user);
6401 init_unistr(&job_info->datatype, "RAW");
6402 init_unistr(&job_info->printprocessor, "winprint");
6403 init_unistr(&job_info->parameters, "");
6404 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6405 init_unistr(&job_info->text_status, "");
6407 /* and here the security descriptor */
6409 job_info->status=nt_printj_status(queue->status);
6410 job_info->priority=queue->priority;
6411 job_info->position=position;
6412 job_info->starttime=0;
6413 job_info->untiltime=0;
6414 job_info->totalpages=queue->page_count;
6415 job_info->size=queue->size;
6416 make_systemtime(&(job_info->submitted), t);
6417 job_info->timeelapsed=0;
6418 job_info->pagesprinted=0;
6420 job_info->devmode = devmode;
6425 /****************************************************************************
6426 Enumjobs at level 1.
6427 ****************************************************************************/
6429 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6430 NT_PRINTER_INFO_LEVEL *ntprinter,
6431 RPC_BUFFER *buffer, uint32 offered,
6432 uint32 *needed, uint32 *returned)
6436 WERROR result = WERR_OK;
6438 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6445 for (i=0; i<*returned; i++)
6446 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6450 /* check the required size. */
6451 for (i=0; i<*returned; i++)
6452 (*needed) += spoolss_size_job_info_1(&info[i]);
6454 if (*needed > offered) {
6455 result = WERR_INSUFFICIENT_BUFFER;
6459 if (!rpcbuf_alloc_size(buffer, *needed)) {
6460 result = WERR_NOMEM;
6464 /* fill the buffer with the structures */
6465 for (i=0; i<*returned; i++)
6466 smb_io_job_info_1("", buffer, &info[i], 0);
6472 if ( !W_ERROR_IS_OK(result) )
6478 /****************************************************************************
6479 Enumjobs at level 2.
6480 ****************************************************************************/
6482 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6483 NT_PRINTER_INFO_LEVEL *ntprinter,
6484 RPC_BUFFER *buffer, uint32 offered,
6485 uint32 *needed, uint32 *returned)
6487 JOB_INFO_2 *info = NULL;
6489 WERROR result = WERR_OK;
6490 DEVICEMODE *devmode = NULL;
6492 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6497 /* this should not be a failure condition if the devmode is NULL */
6499 devmode = construct_dev_mode(snum);
6501 for (i=0; i<*returned; i++)
6502 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6504 free_a_printer(&ntprinter, 2);
6507 /* check the required size. */
6508 for (i=0; i<*returned; i++)
6509 (*needed) += spoolss_size_job_info_2(&info[i]);
6511 if (*needed > offered) {
6512 result = WERR_INSUFFICIENT_BUFFER;
6516 if (!rpcbuf_alloc_size(buffer, *needed)) {
6517 result = WERR_NOMEM;
6521 /* fill the buffer with the structures */
6522 for (i=0; i<*returned; i++)
6523 smb_io_job_info_2("", buffer, &info[i], 0);
6526 free_devmode(devmode);
6529 if ( !W_ERROR_IS_OK(result) )
6536 /****************************************************************************
6538 ****************************************************************************/
6540 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6542 POLICY_HND *handle = &q_u->handle;
6543 uint32 level = q_u->level;
6544 RPC_BUFFER *buffer = NULL;
6545 uint32 offered = q_u->offered;
6546 uint32 *needed = &r_u->needed;
6547 uint32 *returned = &r_u->returned;
6549 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6551 print_status_struct prt_status;
6552 print_queue_struct *queue=NULL;
6554 /* that's an [in out] buffer */
6556 if ( q_u->buffer ) {
6557 rpcbuf_move(q_u->buffer, &r_u->buffer);
6558 buffer = r_u->buffer;
6561 DEBUG(4,("_spoolss_enumjobs\n"));
6566 /* lookup the printer snum and tdb entry */
6568 if (!get_printer_snum(p, handle, &snum))
6571 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6572 if ( !W_ERROR_IS_OK(wret) )
6575 *returned = print_queue_status(snum, &queue, &prt_status);
6576 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6578 if (*returned == 0) {
6585 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6588 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6593 wret = WERR_UNKNOWN_LEVEL;
6596 free_a_printer( &ntprinter, 2 );
6600 /****************************************************************************
6601 ****************************************************************************/
6603 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6608 /****************************************************************************
6609 ****************************************************************************/
6611 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6613 POLICY_HND *handle = &q_u->handle;
6614 uint32 jobid = q_u->jobid;
6615 uint32 command = q_u->command;
6617 struct current_user user;
6619 WERROR errcode = WERR_BADFUNC;
6621 if (!get_printer_snum(p, handle, &snum)) {
6625 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6626 return WERR_INVALID_PRINTER_NAME;
6629 get_current_user(&user, p);
6632 case JOB_CONTROL_CANCEL:
6633 case JOB_CONTROL_DELETE:
6634 if (print_job_delete(&user, snum, jobid, &errcode)) {
6638 case JOB_CONTROL_PAUSE:
6639 if (print_job_pause(&user, snum, jobid, &errcode)) {
6643 case JOB_CONTROL_RESTART:
6644 case JOB_CONTROL_RESUME:
6645 if (print_job_resume(&user, snum, jobid, &errcode)) {
6650 return WERR_UNKNOWN_LEVEL;
6656 /****************************************************************************
6657 Enumerates all printer drivers at level 1.
6658 ****************************************************************************/
6660 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6665 fstring *list = NULL;
6666 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6667 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6668 WERROR result = WERR_OK;
6672 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6674 ndrivers=get_ntdrivers(&list, architecture, version);
6675 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6681 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6682 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6683 SAFE_FREE(driver_info_1);
6687 else driver_info_1 = tdi1;
6690 for (i=0; i<ndrivers; i++) {
6692 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6693 ZERO_STRUCT(driver);
6694 status = get_a_printer_driver(&driver, 3, list[i],
6695 architecture, version);
6696 if (!W_ERROR_IS_OK(status)) {
6700 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6701 free_a_printer_driver(driver, 3);
6704 *returned+=ndrivers;
6708 /* check the required size. */
6709 for (i=0; i<*returned; i++) {
6710 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6711 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6714 if (*needed > offered) {
6715 result = WERR_INSUFFICIENT_BUFFER;
6719 if (!rpcbuf_alloc_size(buffer, *needed)) {
6720 result = WERR_NOMEM;
6724 /* fill the buffer with the driver structures */
6725 for (i=0; i<*returned; i++) {
6726 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6727 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6731 SAFE_FREE(driver_info_1);
6733 if ( !W_ERROR_IS_OK(result) )
6739 /****************************************************************************
6740 Enumerates all printer drivers at level 2.
6741 ****************************************************************************/
6743 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6748 fstring *list = NULL;
6749 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6750 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6751 WERROR result = WERR_OK;
6755 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6757 ndrivers=get_ntdrivers(&list, architecture, version);
6758 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6764 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6765 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6766 SAFE_FREE(driver_info_2);
6770 else driver_info_2 = tdi2;
6773 for (i=0; i<ndrivers; i++) {
6776 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6777 ZERO_STRUCT(driver);
6778 status = get_a_printer_driver(&driver, 3, list[i],
6779 architecture, version);
6780 if (!W_ERROR_IS_OK(status)) {
6784 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6785 free_a_printer_driver(driver, 3);
6788 *returned+=ndrivers;
6792 /* check the required size. */
6793 for (i=0; i<*returned; i++) {
6794 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6795 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6798 if (*needed > offered) {
6799 result = WERR_INSUFFICIENT_BUFFER;
6803 if (!rpcbuf_alloc_size(buffer, *needed)) {
6804 result = WERR_NOMEM;
6808 /* fill the buffer with the form structures */
6809 for (i=0; i<*returned; i++) {
6810 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6811 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6815 SAFE_FREE(driver_info_2);
6817 if ( !W_ERROR_IS_OK(result) )
6823 /****************************************************************************
6824 Enumerates all printer drivers at level 3.
6825 ****************************************************************************/
6827 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6832 fstring *list = NULL;
6833 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6834 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6835 WERROR result = WERR_OK;
6839 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6841 ndrivers=get_ntdrivers(&list, architecture, version);
6842 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6848 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6849 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6850 SAFE_FREE(driver_info_3);
6854 else driver_info_3 = tdi3;
6857 for (i=0; i<ndrivers; i++) {
6860 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6861 ZERO_STRUCT(driver);
6862 status = get_a_printer_driver(&driver, 3, list[i],
6863 architecture, version);
6864 if (!W_ERROR_IS_OK(status)) {
6868 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6869 free_a_printer_driver(driver, 3);
6872 *returned+=ndrivers;
6876 /* check the required size. */
6877 for (i=0; i<*returned; i++) {
6878 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6879 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6882 if (*needed > offered) {
6883 result = WERR_INSUFFICIENT_BUFFER;
6887 if (!rpcbuf_alloc_size(buffer, *needed)) {
6888 result = WERR_NOMEM;
6892 /* fill the buffer with the driver structures */
6893 for (i=0; i<*returned; i++) {
6894 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6895 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6899 for (i=0; i<*returned; i++)
6900 SAFE_FREE(driver_info_3[i].dependentfiles);
6902 SAFE_FREE(driver_info_3);
6904 if ( !W_ERROR_IS_OK(result) )
6910 /****************************************************************************
6911 Enumerates all printer drivers.
6912 ****************************************************************************/
6914 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6916 uint32 level = q_u->level;
6917 RPC_BUFFER *buffer = NULL;
6918 uint32 offered = q_u->offered;
6919 uint32 *needed = &r_u->needed;
6920 uint32 *returned = &r_u->returned;
6923 fstring architecture;
6925 /* that's an [in out] buffer */
6927 if ( q_u->buffer ) {
6928 rpcbuf_move(q_u->buffer, &r_u->buffer);
6929 buffer = r_u->buffer;
6932 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6937 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6938 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6940 if ( !is_myname_or_ipaddr( servername ) )
6941 return WERR_UNKNOWN_PRINTER_DRIVER;
6945 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6947 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6949 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6951 return WERR_UNKNOWN_LEVEL;
6955 /****************************************************************************
6956 ****************************************************************************/
6958 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6960 form->flag=list->flag;
6961 init_unistr(&form->name, list->name);
6962 form->width=list->width;
6963 form->length=list->length;
6964 form->left=list->left;
6965 form->top=list->top;
6966 form->right=list->right;
6967 form->bottom=list->bottom;
6970 /****************************************************************************
6971 ****************************************************************************/
6973 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6975 uint32 level = q_u->level;
6976 RPC_BUFFER *buffer = NULL;
6977 uint32 offered = q_u->offered;
6978 uint32 *needed = &r_u->needed;
6979 uint32 *numofforms = &r_u->numofforms;
6980 uint32 numbuiltinforms;
6982 nt_forms_struct *list=NULL;
6983 nt_forms_struct *builtinlist=NULL;
6988 /* that's an [in out] buffer */
6990 if ( q_u->buffer ) {
6991 rpcbuf_move(q_u->buffer, &r_u->buffer);
6992 buffer = r_u->buffer;
6995 DEBUG(4,("_spoolss_enumforms\n"));
6996 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6997 DEBUGADD(5,("Info level [%d]\n", level));
6999 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7000 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7001 *numofforms = get_ntforms(&list);
7002 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7003 *numofforms += numbuiltinforms;
7005 if (*numofforms == 0)
7006 return WERR_NO_MORE_ITEMS;
7010 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7015 /* construct the list of form structures */
7016 for (i=0; i<numbuiltinforms; i++) {
7017 DEBUGADD(6,("Filling form number [%d]\n",i));
7018 fill_form_1(&forms_1[i], &builtinlist[i]);
7021 SAFE_FREE(builtinlist);
7023 for (; i<*numofforms; i++) {
7024 DEBUGADD(6,("Filling form number [%d]\n",i));
7025 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7030 /* check the required size. */
7031 for (i=0; i<numbuiltinforms; i++) {
7032 DEBUGADD(6,("adding form [%d]'s size\n",i));
7033 buffer_size += spoolss_size_form_1(&forms_1[i]);
7035 for (; i<*numofforms; i++) {
7036 DEBUGADD(6,("adding form [%d]'s size\n",i));
7037 buffer_size += spoolss_size_form_1(&forms_1[i]);
7040 *needed=buffer_size;
7042 if (*needed > offered) {
7045 return WERR_INSUFFICIENT_BUFFER;
7048 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7054 /* fill the buffer with the form structures */
7055 for (i=0; i<numbuiltinforms; i++) {
7056 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7057 smb_io_form_1("", buffer, &forms_1[i], 0);
7059 for (; i<*numofforms; i++) {
7060 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7061 smb_io_form_1("", buffer, &forms_1[i], 0);
7070 SAFE_FREE(builtinlist);
7071 return WERR_UNKNOWN_LEVEL;
7076 /****************************************************************************
7077 ****************************************************************************/
7079 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7081 uint32 level = q_u->level;
7082 UNISTR2 *uni_formname = &q_u->formname;
7083 RPC_BUFFER *buffer = NULL;
7084 uint32 offered = q_u->offered;
7085 uint32 *needed = &r_u->needed;
7087 nt_forms_struct *list=NULL;
7088 nt_forms_struct builtin_form;
7093 int numofforms=0, i=0;
7095 /* that's an [in out] buffer */
7097 if ( q_u->buffer ) {
7098 rpcbuf_move(q_u->buffer, &r_u->buffer);
7099 buffer = r_u->buffer;
7102 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7104 DEBUG(4,("_spoolss_getform\n"));
7105 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7106 DEBUGADD(5,("Info level [%d]\n", level));
7108 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7109 if (!foundBuiltin) {
7110 numofforms = get_ntforms(&list);
7111 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7113 if (numofforms == 0)
7120 fill_form_1(&form_1, &builtin_form);
7123 /* Check if the requested name is in the list of form structures */
7124 for (i=0; i<numofforms; i++) {
7126 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7128 if (strequal(form_name, list[i].name)) {
7129 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7130 fill_form_1(&form_1, &list[i]);
7136 if (i == numofforms) {
7140 /* check the required size. */
7142 *needed=spoolss_size_form_1(&form_1);
7144 if (*needed > offered)
7145 return WERR_INSUFFICIENT_BUFFER;
7147 if (!rpcbuf_alloc_size(buffer, buffer_size))
7150 /* fill the buffer with the form structures */
7151 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7152 smb_io_form_1("", buffer, &form_1, 0);
7158 return WERR_UNKNOWN_LEVEL;
7162 /****************************************************************************
7163 ****************************************************************************/
7165 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7167 init_unistr(&port->port_name, name);
7170 /****************************************************************************
7171 ****************************************************************************/
7173 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7175 init_unistr(&port->port_name, name);
7176 init_unistr(&port->monitor_name, "Local Monitor");
7177 init_unistr(&port->description, "Local Port");
7178 port->port_type=PORT_TYPE_WRITE;
7183 /****************************************************************************
7184 wrapper around the enumer ports command
7185 ****************************************************************************/
7187 WERROR enumports_hook( int *count, char ***lines )
7189 char *cmd = lp_enumports_cmd();
7197 /* if no hook then just fill in the default port */
7200 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7201 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7206 /* we have a valid enumport command */
7208 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7210 DEBUG(10,("Running [%s]\n", command));
7211 ret = smbrun(command, &fd);
7212 DEBUG(10,("Returned [%d]\n", ret));
7217 return WERR_ACCESS_DENIED;
7221 qlines = fd_lines_load(fd, &numlines);
7222 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7232 /****************************************************************************
7234 ****************************************************************************/
7236 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7238 PORT_INFO_1 *ports=NULL;
7240 WERROR result = WERR_OK;
7244 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7248 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7249 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7250 dos_errstr(WERR_NOMEM)));
7251 file_lines_free(qlines);
7255 for (i=0; i<numlines; i++) {
7256 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7257 fill_port_1(&ports[i], qlines[i]);
7260 file_lines_free(qlines);
7263 *returned = numlines;
7265 /* check the required size. */
7266 for (i=0; i<*returned; i++) {
7267 DEBUGADD(6,("adding port [%d]'s size\n", i));
7268 *needed += spoolss_size_port_info_1(&ports[i]);
7271 if (*needed > offered) {
7272 result = WERR_INSUFFICIENT_BUFFER;
7276 if (!rpcbuf_alloc_size(buffer, *needed)) {
7277 result = WERR_NOMEM;
7281 /* fill the buffer with the ports structures */
7282 for (i=0; i<*returned; i++) {
7283 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7284 smb_io_port_1("", buffer, &ports[i], 0);
7290 if ( !W_ERROR_IS_OK(result) )
7296 /****************************************************************************
7298 ****************************************************************************/
7300 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7302 PORT_INFO_2 *ports=NULL;
7304 WERROR result = WERR_OK;
7308 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7313 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7314 file_lines_free(qlines);
7318 for (i=0; i<numlines; i++) {
7319 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7320 fill_port_2(&(ports[i]), qlines[i]);
7323 file_lines_free(qlines);
7326 *returned = numlines;
7328 /* check the required size. */
7329 for (i=0; i<*returned; i++) {
7330 DEBUGADD(6,("adding port [%d]'s size\n", i));
7331 *needed += spoolss_size_port_info_2(&ports[i]);
7334 if (*needed > offered) {
7335 result = WERR_INSUFFICIENT_BUFFER;
7339 if (!rpcbuf_alloc_size(buffer, *needed)) {
7340 result = WERR_NOMEM;
7344 /* fill the buffer with the ports structures */
7345 for (i=0; i<*returned; i++) {
7346 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7347 smb_io_port_2("", buffer, &ports[i], 0);
7353 if ( !W_ERROR_IS_OK(result) )
7359 /****************************************************************************
7361 ****************************************************************************/
7363 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7365 uint32 level = q_u->level;
7366 RPC_BUFFER *buffer = NULL;
7367 uint32 offered = q_u->offered;
7368 uint32 *needed = &r_u->needed;
7369 uint32 *returned = &r_u->returned;
7371 /* that's an [in out] buffer */
7373 if ( q_u->buffer ) {
7374 rpcbuf_move(q_u->buffer, &r_u->buffer);
7375 buffer = r_u->buffer;
7378 DEBUG(4,("_spoolss_enumports\n"));
7385 return enumports_level_1(buffer, offered, needed, returned);
7387 return enumports_level_2(buffer, offered, needed, returned);
7389 return WERR_UNKNOWN_LEVEL;
7393 /****************************************************************************
7394 ****************************************************************************/
7396 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7397 const SPOOL_PRINTER_INFO_LEVEL *info,
7398 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7399 uint32 user_switch, const SPOOL_USER_CTR *user,
7402 NT_PRINTER_INFO_LEVEL *printer = NULL;
7405 WERROR err = WERR_OK;
7407 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7408 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7412 ZERO_STRUCTP(printer);
7414 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7415 if (!convert_printer_info(info, printer, 2)) {
7416 free_a_printer(&printer, 2);
7420 /* check to see if the printer already exists */
7422 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7423 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7424 printer->info_2->sharename));
7425 free_a_printer(&printer, 2);
7426 return WERR_PRINTER_ALREADY_EXISTS;
7429 /* FIXME!!! smbd should check to see if the driver is installed before
7430 trying to add a printer like this --jerry */
7432 if (*lp_addprinter_cmd() ) {
7433 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7434 free_a_printer(&printer,2);
7435 return WERR_ACCESS_DENIED;
7438 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7439 "smb.conf parameter \"addprinter command\" is defined. This"
7440 "parameter must exist for this call to succeed\n",
7441 printer->info_2->sharename ));
7444 /* use our primary netbios name since get_a_printer() will convert
7445 it to what the client expects on a case by case basis */
7447 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7448 printer->info_2->sharename);
7451 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7452 free_a_printer(&printer,2);
7453 return WERR_ACCESS_DENIED;
7456 /* you must be a printer admin to add a new printer */
7457 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7458 free_a_printer(&printer,2);
7459 return WERR_ACCESS_DENIED;
7463 * Do sanity check on the requested changes for Samba.
7466 if (!check_printer_ok(printer->info_2, snum)) {
7467 free_a_printer(&printer,2);
7468 return WERR_INVALID_PARAM;
7472 * When a printer is created, the drivername bound to the printer is used
7473 * to lookup previously saved driver initialization info, which is then
7474 * bound to the new printer, simulating what happens in the Windows arch.
7479 set_driver_init(printer, 2);
7483 /* A valid devmode was included, convert and link it
7485 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7487 if (!convert_devicemode(printer->info_2->printername, devmode,
7488 &printer->info_2->devmode))
7492 /* write the ASCII on disk */
7493 err = mod_a_printer(printer, 2);
7494 if (!W_ERROR_IS_OK(err)) {
7495 free_a_printer(&printer,2);
7499 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7500 /* Handle open failed - remove addition. */
7501 del_a_printer(printer->info_2->sharename);
7502 free_a_printer(&printer,2);
7503 return WERR_ACCESS_DENIED;
7506 update_c_setprinter(False);
7507 free_a_printer(&printer,2);
7512 /****************************************************************************
7513 ****************************************************************************/
7515 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7517 UNISTR2 *uni_srv_name = q_u->server_name;
7518 uint32 level = q_u->level;
7519 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7520 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7521 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7522 uint32 user_switch = q_u->user_switch;
7523 SPOOL_USER_CTR *user = &q_u->user_ctr;
7524 POLICY_HND *handle = &r_u->handle;
7528 /* we don't handle yet */
7529 /* but I know what to do ... */
7530 return WERR_UNKNOWN_LEVEL;
7532 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7534 user_switch, user, handle);
7536 return WERR_UNKNOWN_LEVEL;
7540 /****************************************************************************
7541 ****************************************************************************/
7543 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7545 uint32 level = q_u->level;
7546 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7547 WERROR err = WERR_OK;
7548 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7549 struct current_user user;
7550 fstring driver_name;
7553 ZERO_STRUCT(driver);
7555 get_current_user(&user, p);
7557 if (!convert_printer_driver_info(info, &driver, level)) {
7562 DEBUG(5,("Cleaning driver's information\n"));
7563 err = clean_up_driver_struct(driver, level, &user);
7564 if (!W_ERROR_IS_OK(err))
7567 DEBUG(5,("Moving driver to final destination\n"));
7568 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7572 if (add_a_printer_driver(driver, level)!=0) {
7573 err = WERR_ACCESS_DENIED;
7577 /* BEGIN_ADMIN_LOG */
7580 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7581 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7582 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7585 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7586 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7587 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7593 * I think this is where he DrvUpgradePrinter() hook would be
7594 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7595 * server. Right now, we just need to send ourselves a message
7596 * to update each printer bound to this driver. --jerry
7599 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7600 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7605 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7606 * decide if the driver init data should be deleted. The rules are:
7607 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7608 * 2) delete init data only if there is no 2k/Xp driver
7609 * 3) always delete init data
7610 * The generalized rule is always use init data from the highest order driver.
7611 * It is necessary to follow the driver install by an initialization step to
7612 * finish off this process.
7615 version = driver.info_3->cversion;
7616 else if (level == 6)
7617 version = driver.info_6->version;
7622 * 9x printer driver - never delete init data
7625 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7630 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7631 * there is no 2k/Xp driver init data for this driver name.
7635 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7637 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7639 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7641 if (!del_driver_init(driver_name))
7642 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7645 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7647 free_a_printer_driver(driver1,3);
7648 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7655 * 2k or Xp printer driver - always delete init data
7658 if (!del_driver_init(driver_name))
7659 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7663 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7669 free_a_printer_driver(driver, level);
7673 /********************************************************************
7674 * spoolss_addprinterdriverex
7675 ********************************************************************/
7677 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7679 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7680 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7683 * we only support the semantics of AddPrinterDriver()
7684 * i.e. only copy files that are newer than existing ones
7687 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7688 return WERR_ACCESS_DENIED;
7690 ZERO_STRUCT(q_u_local);
7691 ZERO_STRUCT(r_u_local);
7693 /* just pass the information off to _spoolss_addprinterdriver() */
7694 q_u_local.server_name_ptr = q_u->server_name_ptr;
7695 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7696 q_u_local.level = q_u->level;
7697 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7699 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7702 /****************************************************************************
7703 ****************************************************************************/
7705 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7707 init_unistr(&info->name, name);
7710 /****************************************************************************
7711 ****************************************************************************/
7713 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7719 const char *short_archi;
7720 DRIVER_DIRECTORY_1 *info=NULL;
7721 WERROR result = WERR_OK;
7723 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7724 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7726 /* check for beginning double '\'s and that the server
7729 pservername = servername;
7730 if ( *pservername == '\\' && strlen(servername)>2 ) {
7734 if ( !is_myname_or_ipaddr( pservername ) )
7735 return WERR_INVALID_PARAM;
7737 if (!(short_archi = get_short_archi(long_archi)))
7738 return WERR_INVALID_ENVIRONMENT;
7740 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7743 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7745 DEBUG(4,("printer driver directory: [%s]\n", path));
7747 fill_driverdir_1(info, path);
7749 *needed += spoolss_size_driverdir_info_1(info);
7751 if (*needed > offered) {
7752 result = WERR_INSUFFICIENT_BUFFER;
7756 if (!rpcbuf_alloc_size(buffer, *needed)) {
7757 result = WERR_NOMEM;
7761 smb_io_driverdir_1("", buffer, info, 0);
7769 /****************************************************************************
7770 ****************************************************************************/
7772 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7774 UNISTR2 *name = &q_u->name;
7775 UNISTR2 *uni_environment = &q_u->environment;
7776 uint32 level = q_u->level;
7777 RPC_BUFFER *buffer = NULL;
7778 uint32 offered = q_u->offered;
7779 uint32 *needed = &r_u->needed;
7781 /* that's an [in out] buffer */
7783 if ( q_u->buffer ) {
7784 rpcbuf_move(q_u->buffer, &r_u->buffer);
7785 buffer = r_u->buffer;
7788 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7794 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7796 return WERR_UNKNOWN_LEVEL;
7800 /****************************************************************************
7801 ****************************************************************************/
7803 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7805 POLICY_HND *handle = &q_u->handle;
7806 uint32 idx = q_u->index;
7807 uint32 in_value_len = q_u->valuesize;
7808 uint32 in_data_len = q_u->datasize;
7809 uint32 *out_max_value_len = &r_u->valuesize;
7810 uint16 **out_value = &r_u->value;
7811 uint32 *out_value_len = &r_u->realvaluesize;
7812 uint32 *out_type = &r_u->type;
7813 uint32 *out_max_data_len = &r_u->datasize;
7814 uint8 **data_out = &r_u->data;
7815 uint32 *out_data_len = &r_u->realdatasize;
7817 NT_PRINTER_INFO_LEVEL *printer = NULL;
7819 uint32 biggest_valuesize;
7820 uint32 biggest_datasize;
7822 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7825 REGISTRY_VALUE *val = NULL;
7826 NT_PRINTER_DATA *p_data;
7827 int i, key_index, num_values;
7832 *out_max_data_len = 0;
7836 DEBUG(5,("spoolss_enumprinterdata\n"));
7839 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7843 if (!get_printer_snum(p,handle, &snum))
7846 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7847 if (!W_ERROR_IS_OK(result))
7850 p_data = printer->info_2->data;
7851 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7856 * The NT machine wants to know the biggest size of value and data
7858 * cf: MSDN EnumPrinterData remark section
7861 if ( !in_value_len && !in_data_len && (key_index != -1) )
7863 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7865 biggest_valuesize = 0;
7866 biggest_datasize = 0;
7868 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7870 for ( i=0; i<num_values; i++ )
7872 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7874 name_length = strlen(val->valuename);
7875 if ( strlen(val->valuename) > biggest_valuesize )
7876 biggest_valuesize = name_length;
7878 if ( val->size > biggest_datasize )
7879 biggest_datasize = val->size;
7881 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7885 /* the value is an UNICODE string but real_value_size is the length
7886 in bytes including the trailing 0 */
7888 *out_value_len = 2 * (1+biggest_valuesize);
7889 *out_data_len = biggest_datasize;
7891 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7897 * the value len is wrong in NT sp3
7898 * that's the number of bytes not the number of unicode chars
7901 if ( key_index != -1 )
7902 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7907 /* out_value should default to "" or else NT4 has
7908 problems unmarshalling the response */
7910 *out_max_value_len=(in_value_len/sizeof(uint16));
7912 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7914 result = WERR_NOMEM;
7918 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7920 /* the data is counted in bytes */
7922 *out_max_data_len = in_data_len;
7923 *out_data_len = in_data_len;
7925 /* only allocate when given a non-zero data_len */
7927 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7929 result = WERR_NOMEM;
7933 result = WERR_NO_MORE_ITEMS;
7939 * - counted in bytes in the request
7940 * - counted in UNICODE chars in the max reply
7941 * - counted in bytes in the real size
7943 * take a pause *before* coding not *during* coding
7947 *out_max_value_len=(in_value_len/sizeof(uint16));
7948 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7950 result = WERR_NOMEM;
7954 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7958 *out_type = regval_type( val );
7960 /* data - counted in bytes */
7962 *out_max_data_len = in_data_len;
7963 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7965 result = WERR_NOMEM;
7968 data_len = regval_size(val);
7970 memcpy( *data_out, regval_data_p(val), data_len );
7971 *out_data_len = data_len;
7975 free_a_printer(&printer, 2);
7979 /****************************************************************************
7980 ****************************************************************************/
7982 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7984 POLICY_HND *handle = &q_u->handle;
7985 UNISTR2 *value = &q_u->value;
7986 uint32 type = q_u->type;
7987 uint8 *data = q_u->data;
7988 uint32 real_len = q_u->real_len;
7990 NT_PRINTER_INFO_LEVEL *printer = NULL;
7992 WERROR status = WERR_OK;
7993 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7996 DEBUG(5,("spoolss_setprinterdata\n"));
7999 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8003 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8004 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8005 return WERR_INVALID_PARAM;
8008 if (!get_printer_snum(p,handle, &snum))
8012 * Access check : NT returns "access denied" if you make a
8013 * SetPrinterData call without the necessary privildge.
8014 * we were originally returning OK if nothing changed
8015 * which made Win2k issue **a lot** of SetPrinterData
8016 * when connecting to a printer --jerry
8019 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8021 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8022 status = WERR_ACCESS_DENIED;
8026 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8027 if (!W_ERROR_IS_OK(status))
8030 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8033 * When client side code sets a magic printer data key, detect it and save
8034 * the current printer data and the magic key's data (its the DEVMODE) for
8035 * future printer/driver initializations.
8037 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8039 /* Set devmode and printer initialization info */
8040 status = save_driver_init( printer, 2, data, real_len );
8042 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8046 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8047 type, data, real_len );
8048 if ( W_ERROR_IS_OK(status) )
8049 status = mod_a_printer(printer, 2);
8053 free_a_printer(&printer, 2);
8058 /****************************************************************************
8059 ****************************************************************************/
8061 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8063 POLICY_HND *handle = &q_u->handle;
8064 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8067 DEBUG(5,("_spoolss_resetprinter\n"));
8070 * All we do is to check to see if the handle and queue is valid.
8071 * This call really doesn't mean anything to us because we only
8072 * support RAW printing. --jerry
8076 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8080 if (!get_printer_snum(p,handle, &snum))
8084 /* blindly return success */
8089 /****************************************************************************
8090 ****************************************************************************/
8092 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8094 POLICY_HND *handle = &q_u->handle;
8095 UNISTR2 *value = &q_u->valuename;
8097 NT_PRINTER_INFO_LEVEL *printer = NULL;
8099 WERROR status = WERR_OK;
8100 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8103 DEBUG(5,("spoolss_deleteprinterdata\n"));
8106 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8110 if (!get_printer_snum(p, handle, &snum))
8113 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8114 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8115 return WERR_ACCESS_DENIED;
8118 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8119 if (!W_ERROR_IS_OK(status))
8122 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8124 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8126 if ( W_ERROR_IS_OK(status) )
8127 mod_a_printer( printer, 2 );
8129 free_a_printer(&printer, 2);
8134 /****************************************************************************
8135 ****************************************************************************/
8137 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8139 POLICY_HND *handle = &q_u->handle;
8140 FORM *form = &q_u->form;
8141 nt_forms_struct tmpForm;
8143 WERROR status = WERR_OK;
8144 NT_PRINTER_INFO_LEVEL *printer = NULL;
8147 nt_forms_struct *list=NULL;
8148 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8150 DEBUG(5,("spoolss_addform\n"));
8153 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8158 /* forms can be added on printer of on the print server handle */
8160 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8162 if (!get_printer_snum(p,handle, &snum))
8165 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8166 if (!W_ERROR_IS_OK(status))
8170 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8171 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8172 status = WERR_ACCESS_DENIED;
8176 /* can't add if builtin */
8178 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8179 status = WERR_ALREADY_EXISTS;
8183 count = get_ntforms(&list);
8185 if(!add_a_form(&list, form, &count)) {
8186 status = WERR_NOMEM;
8190 write_ntforms(&list, count);
8193 * ChangeID must always be set if this is a printer
8196 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8197 status = mod_a_printer(printer, 2);
8201 free_a_printer(&printer, 2);
8207 /****************************************************************************
8208 ****************************************************************************/
8210 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8212 POLICY_HND *handle = &q_u->handle;
8213 UNISTR2 *form_name = &q_u->name;
8214 nt_forms_struct tmpForm;
8216 nt_forms_struct *list=NULL;
8217 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8219 WERROR status = WERR_OK;
8220 NT_PRINTER_INFO_LEVEL *printer = NULL;
8222 DEBUG(5,("spoolss_deleteform\n"));
8225 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8229 /* forms can be deleted on printer of on the print server handle */
8231 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8233 if (!get_printer_snum(p,handle, &snum))
8236 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8237 if (!W_ERROR_IS_OK(status))
8241 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8242 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8243 status = WERR_ACCESS_DENIED;
8247 /* can't delete if builtin */
8249 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8250 status = WERR_INVALID_PARAM;
8254 count = get_ntforms(&list);
8256 if ( !delete_a_form(&list, form_name, &count, &status ))
8260 * ChangeID must always be set if this is a printer
8263 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8264 status = mod_a_printer(printer, 2);
8268 free_a_printer(&printer, 2);
8274 /****************************************************************************
8275 ****************************************************************************/
8277 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8279 POLICY_HND *handle = &q_u->handle;
8280 FORM *form = &q_u->form;
8281 nt_forms_struct tmpForm;
8283 WERROR status = WERR_OK;
8284 NT_PRINTER_INFO_LEVEL *printer = NULL;
8287 nt_forms_struct *list=NULL;
8288 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8290 DEBUG(5,("spoolss_setform\n"));
8293 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8297 /* forms can be modified on printer of on the print server handle */
8299 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8301 if (!get_printer_snum(p,handle, &snum))
8304 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8305 if (!W_ERROR_IS_OK(status))
8309 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8310 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8311 status = WERR_ACCESS_DENIED;
8315 /* can't set if builtin */
8316 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8317 status = WERR_INVALID_PARAM;
8321 count = get_ntforms(&list);
8322 update_a_form(&list, form, count);
8323 write_ntforms(&list, count);
8326 * ChangeID must always be set if this is a printer
8329 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8330 status = mod_a_printer(printer, 2);
8335 free_a_printer(&printer, 2);
8341 /****************************************************************************
8342 enumprintprocessors level 1.
8343 ****************************************************************************/
8345 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8347 PRINTPROCESSOR_1 *info_1=NULL;
8348 WERROR result = WERR_OK;
8350 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8355 init_unistr(&info_1->name, "winprint");
8357 *needed += spoolss_size_printprocessor_info_1(info_1);
8359 if (*needed > offered) {
8360 result = WERR_INSUFFICIENT_BUFFER;
8364 if (!rpcbuf_alloc_size(buffer, *needed)) {
8365 result = WERR_NOMEM;
8369 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8374 if ( !W_ERROR_IS_OK(result) )
8380 /****************************************************************************
8381 ****************************************************************************/
8383 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8385 uint32 level = q_u->level;
8386 RPC_BUFFER *buffer = NULL;
8387 uint32 offered = q_u->offered;
8388 uint32 *needed = &r_u->needed;
8389 uint32 *returned = &r_u->returned;
8391 /* that's an [in out] buffer */
8393 if ( q_u->buffer ) {
8394 rpcbuf_move(q_u->buffer, &r_u->buffer);
8395 buffer = r_u->buffer;
8398 DEBUG(5,("spoolss_enumprintprocessors\n"));
8401 * Enumerate the print processors ...
8403 * Just reply with "winprint", to keep NT happy
8404 * and I can use my nice printer checker.
8412 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8414 return WERR_UNKNOWN_LEVEL;
8418 /****************************************************************************
8419 enumprintprocdatatypes level 1.
8420 ****************************************************************************/
8422 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8424 PRINTPROCDATATYPE_1 *info_1=NULL;
8425 WERROR result = WERR_NOMEM;
8427 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8432 init_unistr(&info_1->name, "RAW");
8434 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8436 if (*needed > offered) {
8437 result = WERR_INSUFFICIENT_BUFFER;
8441 if (!rpcbuf_alloc_size(buffer, *needed)) {
8442 result = WERR_NOMEM;
8446 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8451 if ( !W_ERROR_IS_OK(result) )
8457 /****************************************************************************
8458 ****************************************************************************/
8460 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8462 uint32 level = q_u->level;
8463 RPC_BUFFER *buffer = NULL;
8464 uint32 offered = q_u->offered;
8465 uint32 *needed = &r_u->needed;
8466 uint32 *returned = &r_u->returned;
8468 /* that's an [in out] buffer */
8470 if ( q_u->buffer ) {
8471 rpcbuf_move(q_u->buffer, &r_u->buffer);
8472 buffer = r_u->buffer;
8475 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8482 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8484 return WERR_UNKNOWN_LEVEL;
8488 /****************************************************************************
8489 enumprintmonitors level 1.
8490 ****************************************************************************/
8492 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8494 PRINTMONITOR_1 *info_1=NULL;
8495 WERROR result = WERR_OK;
8497 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8502 init_unistr(&info_1->name, "Local Port");
8504 *needed += spoolss_size_printmonitor_info_1(info_1);
8506 if (*needed > offered) {
8507 result = WERR_INSUFFICIENT_BUFFER;
8511 if (!rpcbuf_alloc_size(buffer, *needed)) {
8512 result = WERR_NOMEM;
8516 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8521 if ( !W_ERROR_IS_OK(result) )
8527 /****************************************************************************
8528 enumprintmonitors level 2.
8529 ****************************************************************************/
8531 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8533 PRINTMONITOR_2 *info_2=NULL;
8534 WERROR result = WERR_OK;
8536 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8541 init_unistr(&info_2->name, "Local Port");
8542 init_unistr(&info_2->environment, "Windows NT X86");
8543 init_unistr(&info_2->dll_name, "localmon.dll");
8545 *needed += spoolss_size_printmonitor_info_2(info_2);
8547 if (*needed > offered) {
8548 result = WERR_INSUFFICIENT_BUFFER;
8552 if (!rpcbuf_alloc_size(buffer, *needed)) {
8553 result = WERR_NOMEM;
8557 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8562 if ( !W_ERROR_IS_OK(result) )
8568 /****************************************************************************
8569 ****************************************************************************/
8571 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8573 uint32 level = q_u->level;
8574 RPC_BUFFER *buffer = NULL;
8575 uint32 offered = q_u->offered;
8576 uint32 *needed = &r_u->needed;
8577 uint32 *returned = &r_u->returned;
8579 /* that's an [in out] buffer */
8581 if ( q_u->buffer ) {
8582 rpcbuf_move(q_u->buffer, &r_u->buffer);
8583 buffer = r_u->buffer;
8586 DEBUG(5,("spoolss_enumprintmonitors\n"));
8589 * Enumerate the print monitors ...
8591 * Just reply with "Local Port", to keep NT happy
8592 * and I can use my nice printer checker.
8600 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8602 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8604 return WERR_UNKNOWN_LEVEL;
8608 /****************************************************************************
8609 ****************************************************************************/
8611 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8612 NT_PRINTER_INFO_LEVEL *ntprinter,
8613 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8618 JOB_INFO_1 *info_1=NULL;
8619 WERROR result = WERR_OK;
8621 info_1=SMB_MALLOC_P(JOB_INFO_1);
8623 if (info_1 == NULL) {
8627 for (i=0; i<count && found==False; i++) {
8628 if ((*queue)[i].job==(int)jobid)
8634 /* NT treats not found as bad param... yet another bad choice */
8635 return WERR_INVALID_PARAM;
8638 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8640 *needed += spoolss_size_job_info_1(info_1);
8642 if (*needed > offered) {
8643 result = WERR_INSUFFICIENT_BUFFER;
8647 if (!rpcbuf_alloc_size(buffer, *needed)) {
8648 result = WERR_NOMEM;
8652 smb_io_job_info_1("", buffer, info_1, 0);
8660 /****************************************************************************
8661 ****************************************************************************/
8663 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8664 NT_PRINTER_INFO_LEVEL *ntprinter,
8665 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8672 DEVICEMODE *devmode = NULL;
8673 NT_DEVICEMODE *nt_devmode = NULL;
8675 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8678 ZERO_STRUCTP(info_2);
8680 for ( i=0; i<count && found==False; i++ )
8682 if ((*queue)[i].job == (int)jobid)
8687 /* NT treats not found as bad param... yet another bad
8689 result = WERR_INVALID_PARAM;
8694 * if the print job does not have a DEVMODE associated with it,
8695 * just use the one for the printer. A NULL devicemode is not
8696 * a failure condition
8699 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8700 devmode = construct_dev_mode(snum);
8702 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8703 ZERO_STRUCTP( devmode );
8704 convert_nt_devicemode( devmode, nt_devmode );
8708 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8710 *needed += spoolss_size_job_info_2(info_2);
8712 if (*needed > offered) {
8713 result = WERR_INSUFFICIENT_BUFFER;
8717 if (!rpcbuf_alloc_size(buffer, *needed)) {
8718 result = WERR_NOMEM;
8722 smb_io_job_info_2("", buffer, info_2, 0);
8727 /* Cleanup allocated memory */
8729 free_job_info_2(info_2); /* Also frees devmode */
8735 /****************************************************************************
8736 ****************************************************************************/
8738 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8740 POLICY_HND *handle = &q_u->handle;
8741 uint32 jobid = q_u->jobid;
8742 uint32 level = q_u->level;
8743 RPC_BUFFER *buffer = NULL;
8744 uint32 offered = q_u->offered;
8745 uint32 *needed = &r_u->needed;
8746 WERROR wstatus = WERR_OK;
8747 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8750 print_queue_struct *queue = NULL;
8751 print_status_struct prt_status;
8753 /* that's an [in out] buffer */
8755 if ( q_u->buffer ) {
8756 rpcbuf_move(q_u->buffer, &r_u->buffer);
8757 buffer = r_u->buffer;
8760 DEBUG(5,("spoolss_getjob\n"));
8764 if (!get_printer_snum(p, handle, &snum))
8767 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8768 if ( !W_ERROR_IS_OK(wstatus) )
8771 count = print_queue_status(snum, &queue, &prt_status);
8773 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8774 count, prt_status.status, prt_status.message));
8778 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8779 buffer, offered, needed);
8782 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8783 buffer, offered, needed);
8786 wstatus = WERR_UNKNOWN_LEVEL;
8791 free_a_printer( &ntprinter, 2 );
8796 /********************************************************************
8797 spoolss_getprinterdataex
8799 From MSDN documentation of GetPrinterDataEx: pass request
8800 to GetPrinterData if key is "PrinterDriverData".
8801 ********************************************************************/
8803 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8805 POLICY_HND *handle = &q_u->handle;
8806 uint32 in_size = q_u->size;
8807 uint32 *type = &r_u->type;
8808 uint32 *out_size = &r_u->size;
8809 uint8 **data = &r_u->data;
8810 uint32 *needed = &r_u->needed;
8811 fstring keyname, valuename;
8813 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8815 NT_PRINTER_INFO_LEVEL *printer = NULL;
8817 WERROR status = WERR_OK;
8819 DEBUG(4,("_spoolss_getprinterdataex\n"));
8821 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8822 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8824 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8825 keyname, valuename));
8827 /* in case of problem, return some default values */
8831 *out_size = in_size;
8834 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8835 status = WERR_BADFID;
8839 /* Is the handle to a printer or to the server? */
8841 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8842 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8843 status = WERR_INVALID_PARAM;
8847 if ( !get_printer_snum(p,handle, &snum) )
8850 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8851 if ( !W_ERROR_IS_OK(status) )
8854 /* check to see if the keyname is valid */
8855 if ( !strlen(keyname) ) {
8856 status = WERR_INVALID_PARAM;
8860 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8861 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8862 free_a_printer( &printer, 2 );
8863 status = WERR_BADFILE;
8867 /* When given a new keyname, we should just create it */
8869 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8871 if (*needed > *out_size)
8872 status = WERR_MORE_DATA;
8875 if ( !W_ERROR_IS_OK(status) )
8877 DEBUG(5, ("error: allocating %d\n", *out_size));
8879 /* reply this param doesn't exist */
8883 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8884 status = WERR_NOMEM;
8894 free_a_printer( &printer, 2 );
8899 /********************************************************************
8900 * spoolss_setprinterdataex
8901 ********************************************************************/
8903 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8905 POLICY_HND *handle = &q_u->handle;
8906 uint32 type = q_u->type;
8907 uint8 *data = q_u->data;
8908 uint32 real_len = q_u->real_len;
8910 NT_PRINTER_INFO_LEVEL *printer = NULL;
8912 WERROR status = WERR_OK;
8913 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8918 DEBUG(4,("_spoolss_setprinterdataex\n"));
8920 /* From MSDN documentation of SetPrinterDataEx: pass request to
8921 SetPrinterData if key is "PrinterDriverData" */
8924 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8928 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8929 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8930 return WERR_INVALID_PARAM;
8933 if ( !get_printer_snum(p,handle, &snum) )
8937 * Access check : NT returns "access denied" if you make a
8938 * SetPrinterData call without the necessary privildge.
8939 * we were originally returning OK if nothing changed
8940 * which made Win2k issue **a lot** of SetPrinterData
8941 * when connecting to a printer --jerry
8944 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8946 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8947 return WERR_ACCESS_DENIED;
8950 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8951 if (!W_ERROR_IS_OK(status))
8954 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8955 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8957 /* check for OID in valuename */
8959 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8965 /* save the registry data */
8967 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8969 if ( W_ERROR_IS_OK(status) )
8971 /* save the OID if one was specified */
8973 fstrcat( keyname, "\\" );
8974 fstrcat( keyname, SPOOL_OID_KEY );
8977 * I'm not checking the status here on purpose. Don't know
8978 * if this is right, but I'm returning the status from the
8979 * previous set_printer_dataex() call. I have no idea if
8980 * this is right. --jerry
8983 set_printer_dataex( printer, keyname, valuename,
8984 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8987 status = mod_a_printer(printer, 2);
8990 free_a_printer(&printer, 2);
8996 /********************************************************************
8997 * spoolss_deleteprinterdataex
8998 ********************************************************************/
9000 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9002 POLICY_HND *handle = &q_u->handle;
9003 UNISTR2 *value = &q_u->valuename;
9004 UNISTR2 *key = &q_u->keyname;
9006 NT_PRINTER_INFO_LEVEL *printer = NULL;
9008 WERROR status = WERR_OK;
9009 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9010 pstring valuename, keyname;
9012 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9015 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9019 if (!get_printer_snum(p, handle, &snum))
9022 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9023 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9024 return WERR_ACCESS_DENIED;
9027 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9028 if (!W_ERROR_IS_OK(status))
9031 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9032 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9034 status = delete_printer_dataex( printer, keyname, valuename );
9036 if ( W_ERROR_IS_OK(status) )
9037 mod_a_printer( printer, 2 );
9039 free_a_printer(&printer, 2);
9044 /********************************************************************
9045 * spoolss_enumprinterkey
9046 ********************************************************************/
9049 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9052 fstring *keynames = NULL;
9053 uint16 *enumkeys = NULL;
9056 POLICY_HND *handle = &q_u->handle;
9057 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9058 NT_PRINTER_DATA *data;
9059 NT_PRINTER_INFO_LEVEL *printer = NULL;
9061 WERROR status = WERR_BADFILE;
9064 DEBUG(4,("_spoolss_enumprinterkey\n"));
9067 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9071 if ( !get_printer_snum(p,handle, &snum) )
9074 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9075 if (!W_ERROR_IS_OK(status))
9078 /* get the list of subkey names */
9080 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9081 data = printer->info_2->data;
9083 num_keys = get_printer_subkeys( data, key, &keynames );
9085 if ( num_keys == -1 ) {
9086 status = WERR_BADFILE;
9090 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9092 r_u->needed = printerkey_len*2;
9094 if ( q_u->size < r_u->needed ) {
9095 status = WERR_MORE_DATA;
9099 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9100 status = WERR_NOMEM;
9106 if ( q_u->size < r_u->needed )
9107 status = WERR_MORE_DATA;
9110 free_a_printer( &printer, 2 );
9111 SAFE_FREE( keynames );
9116 /********************************************************************
9117 * spoolss_deleteprinterkey
9118 ********************************************************************/
9120 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9122 POLICY_HND *handle = &q_u->handle;
9123 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9125 NT_PRINTER_INFO_LEVEL *printer = NULL;
9129 DEBUG(5,("spoolss_deleteprinterkey\n"));
9132 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9136 /* if keyname == NULL, return error */
9138 if ( !q_u->keyname.buffer )
9139 return WERR_INVALID_PARAM;
9141 if (!get_printer_snum(p, handle, &snum))
9144 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9145 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9146 return WERR_ACCESS_DENIED;
9149 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9150 if (!W_ERROR_IS_OK(status))
9153 /* delete the key and all subneys */
9155 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9157 status = delete_all_printer_data( printer->info_2, key );
9159 if ( W_ERROR_IS_OK(status) )
9160 status = mod_a_printer(printer, 2);
9162 free_a_printer( &printer, 2 );
9168 /********************************************************************
9169 * spoolss_enumprinterdataex
9170 ********************************************************************/
9172 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9174 POLICY_HND *handle = &q_u->handle;
9175 uint32 in_size = q_u->size;
9178 NT_PRINTER_INFO_LEVEL *printer = NULL;
9179 PRINTER_ENUM_VALUES *enum_values = NULL;
9180 NT_PRINTER_DATA *p_data;
9182 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9187 REGISTRY_VALUE *val;
9192 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9195 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9200 * first check for a keyname of NULL or "". Win2k seems to send
9201 * this a lot and we should send back WERR_INVALID_PARAM
9202 * no need to spend time looking up the printer in this case.
9206 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9207 if ( !strlen(key) ) {
9208 result = WERR_INVALID_PARAM;
9212 /* get the printer off of disk */
9214 if (!get_printer_snum(p,handle, &snum))
9217 ZERO_STRUCT(printer);
9218 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9219 if (!W_ERROR_IS_OK(result))
9222 /* now look for a match on the key name */
9224 p_data = printer->info_2->data;
9226 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9227 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9229 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9230 result = WERR_INVALID_PARAM;
9237 /* allocate the memory for the array of pointers -- if necessary */
9239 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9242 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9244 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9245 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9246 result = WERR_NOMEM;
9250 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9254 * loop through all params and build the array to pass
9255 * back to the client
9258 for ( i=0; i<num_entries; i++ )
9260 /* lookup the registry value */
9262 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9263 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9267 value_name = regval_name( val );
9268 init_unistr( &enum_values[i].valuename, value_name );
9269 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9270 enum_values[i].type = regval_type( val );
9272 data_len = regval_size( val );
9274 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9276 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9278 result = WERR_NOMEM;
9282 enum_values[i].data_len = data_len;
9284 /* keep track of the size of the array in bytes */
9286 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9289 /* housekeeping information in the reply */
9291 r_u->needed = needed;
9292 r_u->returned = num_entries;
9294 if (needed > in_size) {
9295 result = WERR_MORE_DATA;
9299 /* copy data into the reply */
9301 r_u->ctr.size = r_u->needed;
9302 r_u->ctr.size_of_array = r_u->returned;
9303 r_u->ctr.values = enum_values;
9309 free_a_printer(&printer, 2);
9314 /****************************************************************************
9315 ****************************************************************************/
9317 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9319 init_unistr(&info->name, name);
9322 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9323 UNISTR2 *environment,
9330 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9331 WERROR result = WERR_OK;
9333 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9335 if (!get_short_archi(long_archi))
9336 return WERR_INVALID_ENVIRONMENT;
9338 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9341 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9343 fill_printprocessordirectory_1(info, path);
9345 *needed += spoolss_size_printprocessordirectory_info_1(info);
9347 if (*needed > offered) {
9348 result = WERR_INSUFFICIENT_BUFFER;
9352 if (!rpcbuf_alloc_size(buffer, *needed)) {
9353 result = WERR_INSUFFICIENT_BUFFER;
9357 smb_io_printprocessordirectory_1("", buffer, info, 0);
9365 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9367 uint32 level = q_u->level;
9368 RPC_BUFFER *buffer = NULL;
9369 uint32 offered = q_u->offered;
9370 uint32 *needed = &r_u->needed;
9373 /* that's an [in out] buffer */
9375 if ( q_u->buffer ) {
9376 rpcbuf_move(q_u->buffer, &r_u->buffer);
9377 buffer = r_u->buffer;
9380 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9386 result = getprintprocessordirectory_level_1
9387 (&q_u->name, &q_u->environment, buffer, offered, needed);
9390 result = WERR_UNKNOWN_LEVEL;
9398 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9399 SPOOL_R_REPLYOPENPRINTER *r_u)
9401 DEBUG(5,("_spoolss_replyopenprinter\n"));
9403 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9408 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9409 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9411 DEBUG(5,("_spoolss_replycloseprinter\n"));