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 cli_state notify_cli; /* print notify back-channel */
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 = cli_spoolss_reply_close_printer(¬ify_cli, notify_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_nt_session_close(¬ify_cli);
178 cli_ulogoff(¬ify_cli);
179 cli_shutdown(¬ify_cli);
180 message_deregister(MSG_PRINTER_NOTIFY2);
182 /* Tell the connections db we're no longer interested in
183 * printer notify messages. */
185 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
191 /****************************************************************************
192 Functions to free a printer entry datastruct.
193 ****************************************************************************/
195 static void free_printer_entry(void *ptr)
197 Printer_entry *Printer = (Printer_entry *)ptr;
199 if (Printer->notify.client_connected==True) {
202 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
204 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
205 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
206 snum = print_queue_snum(Printer->sharename);
208 srv_spoolss_replycloseprinter(snum,
209 &Printer->notify.client_hnd);
213 Printer->notify.flags=0;
214 Printer->notify.options=0;
215 Printer->notify.localmachine[0]='\0';
216 Printer->notify.printerlocal=0;
217 free_spool_notify_option(&Printer->notify.option);
218 Printer->notify.option=NULL;
219 Printer->notify.client_connected=False;
221 free_nt_devicemode( &Printer->nt_devmode );
222 free_a_printer( &Printer->printer_info, 2 );
224 talloc_destroy( Printer->ctx );
226 /* Remove from the internal list. */
227 DLIST_REMOVE(printers_list, Printer);
232 /****************************************************************************
233 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
234 ****************************************************************************/
236 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
238 SPOOL_NOTIFY_OPTION *new_sp = NULL;
243 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
250 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
252 if (!new_sp->ctr.type) {
261 /****************************************************************************
262 find printer index by handle
263 ****************************************************************************/
265 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
267 Printer_entry *find_printer = NULL;
269 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
270 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
277 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
278 /****************************************************************************
279 look for a printer object cached on an open printer handle
280 ****************************************************************************/
282 WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2,
283 const char *servername, const char *printername )
287 DEBUG(10,("find_printer_in_print_hnd_cache: printer [\\\\%s\\%s]\n",
288 servername, printername));
290 for ( p=printers_list; p; p=p->next )
292 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
294 && strequal( p->sharename, printername )
295 && strequal( p->servername, servername ) )
297 DEBUG(10,("Found printer\n"));
298 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
304 return WERR_INVALID_PRINTER_NAME;
307 /****************************************************************************
308 destroy any cached printer_info_2 structures on open handles
309 ****************************************************************************/
311 void invalidate_printer_hnd_cache( char *printername )
315 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
317 for ( p=printers_list; p; p=p->next )
319 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
321 && StrCaseCmp(p->sharename, printername)==0)
323 DEBUG(10,("invalidating printer_info cache for handl:\n"));
324 free_a_printer( &p->printer_info, 2 );
325 p->printer_info = NULL;
333 /****************************************************************************
334 Close printer index by handle.
335 ****************************************************************************/
337 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
339 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
342 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
346 close_policy_hnd(p, hnd);
351 /****************************************************************************
352 Delete a printer given a handle.
353 ****************************************************************************/
354 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
356 char *cmd = lp_deleteprinter_cmd();
359 SE_PRIV se_printop = SE_PRINT_OPERATOR;
360 BOOL is_print_op = False;
362 /* can't fail if we don't try */
367 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
370 is_print_op = user_has_privileges( token, &se_printop );
372 DEBUG(10,("Running [%s]\n", command));
374 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
379 if ( (ret = smbrun(command, NULL)) == 0 ) {
380 /* Tell everyone we updated smb.conf. */
381 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
387 /********** END SePrintOperatorPrivlege BLOCK **********/
389 DEBUGADD(10,("returned [%d]\n", ret));
392 return WERR_BADFID; /* What to return here? */
394 /* go ahead and re-read the services immediately */
395 reload_services( False );
397 if ( lp_servicenumber( sharename ) < 0 )
398 return WERR_ACCESS_DENIED;
403 /****************************************************************************
404 Delete a printer given a handle.
405 ****************************************************************************/
407 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
409 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
412 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
417 * It turns out that Windows allows delete printer on a handle
418 * opened by an admin user, then used on a pipe handle created
419 * by an anonymous user..... but they're working on security.... riiight !
423 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
424 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
425 return WERR_ACCESS_DENIED;
428 /* this does not need a become root since the access check has been
429 done on the handle already */
431 if (del_a_printer( Printer->sharename ) != 0) {
432 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
436 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
439 /****************************************************************************
440 Return the snum of a printer corresponding to an handle.
441 ****************************************************************************/
443 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
445 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
448 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
452 switch (Printer->printer_type) {
453 case PRINTER_HANDLE_IS_PRINTER:
454 DEBUG(4,("short name:%s\n", Printer->sharename));
455 *number = print_queue_snum(Printer->sharename);
456 return (*number != -1);
457 case PRINTER_HANDLE_IS_PRINTSERVER:
464 /****************************************************************************
465 Set printer handle type.
466 Check if it's \\server or \\server\printer
467 ****************************************************************************/
469 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
471 DEBUG(3,("Setting printer type=%s\n", handlename));
473 if ( strlen(handlename) < 3 ) {
474 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
478 /* it's a print server */
479 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
480 DEBUGADD(4,("Printer is a print server\n"));
481 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
485 DEBUGADD(4,("Printer is a printer\n"));
486 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
492 /****************************************************************************
493 Set printer handle name.
494 ****************************************************************************/
496 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
499 int n_services=lp_numservices();
500 char *aprinter, *printername;
501 const char *servername;
504 NT_PRINTER_INFO_LEVEL *printer;
507 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
509 aprinter = handlename;
510 if ( *handlename == '\\' ) {
511 servername = handlename + 2;
512 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
521 /* save the servername to fill in replies on this handle */
523 if ( !is_myname_or_ipaddr( servername ) )
526 fstrcpy( Printer->servername, servername );
528 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
531 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
534 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
536 /* Search all sharenames first as this is easier than pulling
537 the printer_info_2 off of disk */
539 snum = find_service(aprinter);
541 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
543 fstrcpy( sname, aprinter );
546 /* do another loop to look for printernames */
548 for (snum=0; !found && snum<n_services; snum++) {
550 /* no point in checking if this is not a printer or
551 we aren't allowing printername != sharename */
553 if ( !(lp_snum_ok(snum)
555 && !lp_force_printername(snum)) )
560 fstrcpy(sname, lp_servicename(snum));
563 result = get_a_printer( NULL, &printer, 2, sname );
564 if ( !W_ERROR_IS_OK(result) ) {
565 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
566 sname, dos_errstr(result)));
570 /* printername is always returned as \\server\printername */
571 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
572 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
573 printer->info_2->printername));
574 free_a_printer( &printer, 2);
580 if ( strequal(printername, aprinter) ) {
584 DEBUGADD(10, ("printername: %s\n", printername));
586 free_a_printer( &printer, 2);
590 DEBUGADD(4,("Printer not found\n"));
594 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
596 fstrcpy(Printer->sharename, sname);
601 /****************************************************************************
602 Find first available printer slot. creates a printer handle for you.
603 ****************************************************************************/
605 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
607 Printer_entry *new_printer;
609 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
611 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
614 ZERO_STRUCTP(new_printer);
616 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
617 SAFE_FREE(new_printer);
621 /* Add to the internal list. */
622 DLIST_ADD(printers_list, new_printer);
624 new_printer->notify.option=NULL;
626 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
627 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
628 close_printer_handle(p, hnd);
632 if (!set_printer_hnd_printertype(new_printer, name)) {
633 close_printer_handle(p, hnd);
637 if (!set_printer_hnd_name(new_printer, name)) {
638 close_printer_handle(p, hnd);
642 new_printer->access_granted = access_granted;
644 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
649 /***************************************************************************
650 check to see if the client motify handle is monitoring the notification
651 given by (notify_type, notify_field).
652 **************************************************************************/
654 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
660 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
663 SPOOL_NOTIFY_OPTION *option = p->notify.option;
667 * Flags should always be zero when the change notify
668 * is registered by the client's spooler. A user Win32 app
669 * might use the flags though instead of the NOTIFY_OPTION_INFO
678 return is_monitoring_event_flags(
679 p->notify.flags, notify_type, notify_field);
681 for (i = 0; i < option->count; i++) {
683 /* Check match for notify_type */
685 if (option->ctr.type[i].type != notify_type)
688 /* Check match for field */
690 for (j = 0; j < option->ctr.type[i].count; j++) {
691 if (option->ctr.type[i].fields[j] == notify_field) {
697 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
698 p->servername, p->sharename, notify_type, notify_field));
703 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
705 static void notify_one_value(struct spoolss_notify_msg *msg,
706 SPOOL_NOTIFY_INFO_DATA *data,
709 data->notify_data.value[0] = msg->notify.value[0];
710 data->notify_data.value[1] = 0;
713 static void notify_string(struct spoolss_notify_msg *msg,
714 SPOOL_NOTIFY_INFO_DATA *data,
719 /* The length of the message includes the trailing \0 */
721 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
723 data->notify_data.data.length = msg->len * 2;
724 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
726 if (!data->notify_data.data.string) {
727 data->notify_data.data.length = 0;
731 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
734 static void notify_system_time(struct spoolss_notify_msg *msg,
735 SPOOL_NOTIFY_INFO_DATA *data,
741 if (msg->len != sizeof(time_t)) {
742 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
747 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
748 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
752 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
753 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
757 if (!spoolss_io_system_time("", &ps, 0, &systime))
760 data->notify_data.data.length = prs_offset(&ps);
761 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
763 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
768 struct notify2_message_table {
770 void (*fn)(struct spoolss_notify_msg *msg,
771 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
774 static struct notify2_message_table printer_notify_table[] = {
775 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
776 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
777 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
778 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
779 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
780 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
781 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
782 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
783 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
784 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
785 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
786 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
787 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
788 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
789 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
790 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
791 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
792 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
793 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
796 static struct notify2_message_table job_notify_table[] = {
797 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
798 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
799 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
800 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
801 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
802 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
803 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
804 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
805 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
806 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
807 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
808 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
809 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
810 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
811 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
812 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
813 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
814 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
815 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
816 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
817 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
818 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
819 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
820 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
824 /***********************************************************************
825 Allocate talloc context for container object
826 **********************************************************************/
828 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
833 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
838 /***********************************************************************
839 release all allocated memory and zero out structure
840 **********************************************************************/
842 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
848 talloc_destroy(ctr->ctx);
855 /***********************************************************************
856 **********************************************************************/
858 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
866 /***********************************************************************
867 **********************************************************************/
869 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
871 if ( !ctr || !ctr->msg_groups )
874 if ( idx >= ctr->num_groups )
877 return &ctr->msg_groups[idx];
881 /***********************************************************************
882 How many groups of change messages do we have ?
883 **********************************************************************/
885 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
890 return ctr->num_groups;
893 /***********************************************************************
894 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
895 **********************************************************************/
897 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
899 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
900 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
901 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
907 /* loop over all groups looking for a matching printer name */
909 for ( i=0; i<ctr->num_groups; i++ ) {
910 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
914 /* add a new group? */
916 if ( i == ctr->num_groups ) {
919 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
920 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
923 ctr->msg_groups = groups;
925 /* clear the new entry and set the printer name */
927 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
928 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
931 /* add the change messages; 'i' is the correct index now regardless */
933 msg_grp = &ctr->msg_groups[i];
937 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
938 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
941 msg_grp->msgs = msg_list;
943 new_slot = msg_grp->num_msgs-1;
944 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
946 /* need to allocate own copy of data */
949 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
951 return ctr->num_groups;
954 /***********************************************************************
955 Send a change notication message on all handles which have a call
957 **********************************************************************/
959 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
962 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
963 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
964 SPOOLSS_NOTIFY_MSG *messages;
965 int sending_msg_count;
968 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
972 messages = msg_group->msgs;
975 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
979 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
981 /* loop over all printers */
983 for (p = printers_list; p; p = p->next) {
984 SPOOL_NOTIFY_INFO_DATA *data;
989 /* Is there notification on this handle? */
991 if ( !p->notify.client_connected )
994 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
996 /* For this printer? Print servers always receive
999 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1000 ( !strequal(msg_group->printername, p->sharename) ) )
1003 DEBUG(10,("Our printer\n"));
1005 /* allocate the max entries possible */
1007 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
1010 /* build the array of change notifications */
1012 sending_msg_count = 0;
1014 for ( i=0; i<msg_group->num_msgs; i++ ) {
1015 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1017 /* Are we monitoring this event? */
1019 if (!is_monitoring_event(p, msg->type, msg->field))
1022 sending_msg_count++;
1025 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1026 msg->type, msg->field, p->sharename));
1029 * if the is a printer notification handle and not a job notification
1030 * type, then set the id to 0. Other wise just use what was specified
1033 * When registering change notification on a print server handle
1034 * we always need to send back the id (snum) matching the printer
1035 * for which the change took place. For change notify registered
1036 * on a printer handle, this does not matter and the id should be 0.
1041 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1047 /* Convert unix jobid to smb jobid */
1049 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1050 id = sysjob_to_jobid(msg->id);
1053 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1058 construct_info_data( &data[data_len], msg->type, msg->field, id );
1061 case PRINTER_NOTIFY_TYPE:
1062 if ( printer_notify_table[msg->field].fn )
1063 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1066 case JOB_NOTIFY_TYPE:
1067 if ( job_notify_table[msg->field].fn )
1068 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1072 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1079 if ( sending_msg_count ) {
1080 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1081 data_len, data, p->notify.change, 0 );
1086 DEBUG(8,("send_notify2_changes: Exit...\n"));
1090 /***********************************************************************
1091 **********************************************************************/
1093 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1096 uint32 tv_sec, tv_usec;
1099 /* Unpack message */
1101 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1104 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1106 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1109 tdb_unpack((char *)buf + offset, len - offset, "dd",
1110 &msg->notify.value[0], &msg->notify.value[1]);
1112 tdb_unpack((char *)buf + offset, len - offset, "B",
1113 &msg->len, &msg->notify.data);
1115 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1116 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1118 tv->tv_sec = tv_sec;
1119 tv->tv_usec = tv_usec;
1122 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1123 msg->notify.value[1]));
1125 dump_data(3, msg->notify.data, msg->len);
1130 /********************************************************************
1131 Receive a notify2 message list
1132 ********************************************************************/
1134 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1136 size_t msg_count, i;
1137 char *buf = (char *)msg;
1140 SPOOLSS_NOTIFY_MSG notify;
1141 SPOOLSS_NOTIFY_MSG_CTR messages;
1145 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1149 msg_count = IVAL(buf, 0);
1152 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1154 if (msg_count == 0) {
1155 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1159 /* initialize the container */
1161 ZERO_STRUCT( messages );
1162 notify_msg_ctr_init( &messages );
1165 * build message groups for each printer identified
1166 * in a change_notify msg. Remember that a PCN message
1167 * includes the handle returned for the srv_spoolss_replyopenprinter()
1168 * call. Therefore messages are grouped according to printer handle.
1171 for ( i=0; i<msg_count; i++ ) {
1172 struct timeval msg_tv;
1174 if (msg_ptr + 4 - buf > len) {
1175 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1179 msg_len = IVAL(msg_ptr,0);
1182 if (msg_ptr + msg_len - buf > len) {
1183 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1187 /* unpack messages */
1189 ZERO_STRUCT( notify );
1190 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1193 /* add to correct list in container */
1195 notify_msg_ctr_addmsg( &messages, ¬ify );
1197 /* free memory that might have been allocated by notify2_unpack_msg() */
1199 if ( notify.len != 0 )
1200 SAFE_FREE( notify.notify.data );
1203 /* process each group of messages */
1205 num_groups = notify_msg_ctr_numgroups( &messages );
1206 for ( i=0; i<num_groups; i++ )
1207 send_notify2_changes( &messages, i );
1212 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1214 notify_msg_ctr_destroy( &messages );
1219 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
1220 /********************************************************************
1221 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1222 one smbd, all of processes must clear their printer cache immediately.
1223 ********************************************************************/
1225 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1227 fstring printername;
1229 fstrcpy( printername, buf );
1231 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1233 invalidate_printer_hnd_cache( printername );
1237 /********************************************************************
1238 Send a message to ourself about new driver being installed
1239 so we can upgrade the information for each printer bound to this
1241 ********************************************************************/
1243 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1245 int len = strlen(drivername);
1250 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1253 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1258 /**********************************************************************
1259 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1260 over all printers, upgrading ones as necessary
1261 **********************************************************************/
1263 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1267 int n_services = lp_numservices();
1269 len = MIN(len,sizeof(drivername)-1);
1270 strncpy(drivername, buf, len);
1272 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1274 /* Iterate the printer list */
1276 for (snum=0; snum<n_services; snum++)
1278 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1281 NT_PRINTER_INFO_LEVEL *printer = NULL;
1283 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1284 if (!W_ERROR_IS_OK(result))
1287 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1289 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1291 /* all we care about currently is the change_id */
1293 result = mod_a_printer(printer, 2);
1294 if (!W_ERROR_IS_OK(result)) {
1295 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1296 dos_errstr(result)));
1300 free_a_printer(&printer, 2);
1307 /********************************************************************
1308 Update the cache for all printq's with a registered client
1310 ********************************************************************/
1312 void update_monitored_printq_cache( void )
1314 Printer_entry *printer = printers_list;
1317 /* loop through all printers and update the cache where
1318 client_connected == True */
1321 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1322 && printer->notify.client_connected )
1324 snum = print_queue_snum(printer->sharename);
1325 print_queue_status( snum, NULL, NULL );
1328 printer = printer->next;
1333 /********************************************************************
1334 Send a message to ourself about new driver being installed
1335 so we can upgrade the information for each printer bound to this
1337 ********************************************************************/
1339 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1341 int len = strlen(drivername);
1346 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1349 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1354 /**********************************************************************
1355 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1356 over all printers, resetting printer data as neessary
1357 **********************************************************************/
1359 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1363 int n_services = lp_numservices();
1365 len = MIN( len, sizeof(drivername)-1 );
1366 strncpy( drivername, buf, len );
1368 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1370 /* Iterate the printer list */
1372 for ( snum=0; snum<n_services; snum++ )
1374 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1377 NT_PRINTER_INFO_LEVEL *printer = NULL;
1379 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1380 if ( !W_ERROR_IS_OK(result) )
1384 * if the printer is bound to the driver,
1385 * then reset to the new driver initdata
1388 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1390 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1392 if ( !set_driver_init(printer, 2) ) {
1393 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1394 printer->info_2->printername, printer->info_2->drivername));
1397 result = mod_a_printer( printer, 2 );
1398 if ( !W_ERROR_IS_OK(result) ) {
1399 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1400 get_dos_error_msg(result)));
1404 free_a_printer( &printer, 2 );
1413 /********************************************************************
1414 Copy routines used by convert_to_openprinterex()
1415 *******************************************************************/
1417 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1425 DEBUG (8,("dup_devmode\n"));
1427 /* bulk copy first */
1429 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1433 /* dup the pointer members separately */
1435 len = unistrlen(devmode->devicename.buffer);
1437 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1438 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1443 len = unistrlen(devmode->formname.buffer);
1445 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1446 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1450 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1455 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1457 if (!new_ctr || !ctr)
1460 DEBUG(8,("copy_devmode_ctr\n"));
1462 new_ctr->size = ctr->size;
1463 new_ctr->devmode_ptr = ctr->devmode_ptr;
1465 if(ctr->devmode_ptr)
1466 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1469 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1471 if (!new_def || !def)
1474 DEBUG(8,("copy_printer_defaults\n"));
1476 new_def->datatype_ptr = def->datatype_ptr;
1478 if (def->datatype_ptr)
1479 copy_unistr2(&new_def->datatype, &def->datatype);
1481 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1483 new_def->access_required = def->access_required;
1486 /********************************************************************
1487 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1488 * SPOOL_Q_OPEN_PRINTER_EX structure
1489 ********************************************************************/
1491 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1493 if (!q_u_ex || !q_u)
1496 DEBUG(8,("convert_to_openprinterex\n"));
1498 if ( q_u->printername ) {
1499 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1500 if (q_u_ex->printername == NULL)
1502 copy_unistr2(q_u_ex->printername, q_u->printername);
1505 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1510 /********************************************************************
1511 * spoolss_open_printer
1513 * called from the spoolss dispatcher
1514 ********************************************************************/
1516 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1518 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1519 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1524 ZERO_STRUCT(q_u_ex);
1525 ZERO_STRUCT(r_u_ex);
1527 /* convert the OpenPrinter() call to OpenPrinterEx() */
1529 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1530 if (!W_ERROR_IS_OK(r_u_ex.status))
1531 return r_u_ex.status;
1533 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1535 /* convert back to OpenPrinter() */
1537 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1542 /********************************************************************
1543 * spoolss_open_printer
1545 * If the openprinterex rpc call contains a devmode,
1546 * it's a per-user one. This per-user devmode is derivated
1547 * from the global devmode. Openprinterex() contains a per-user
1548 * devmode for when you do EMF printing and spooling.
1549 * In the EMF case, the NT workstation is only doing half the job
1550 * of rendering the page. The other half is done by running the printer
1551 * driver on the server.
1552 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1553 * The EMF file only contains what is to be printed on the page.
1554 * So in order for the server to know how to print, the NT client sends
1555 * a devicemode attached to the openprinterex call.
1556 * But this devicemode is short lived, it's only valid for the current print job.
1558 * If Samba would have supported EMF spooling, this devicemode would
1559 * have been attached to the handle, to sent it to the driver to correctly
1560 * rasterize the EMF file.
1562 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1563 * we just act as a pass-thru between windows and the printer.
1565 * In order to know that Samba supports only RAW spooling, NT has to call
1566 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1567 * and until NT sends a RAW job, we refuse it.
1569 * But to call getprinter() or startdoc(), you first need a valid handle,
1570 * and to get an handle you have to call openprintex(). Hence why you have
1571 * a devicemode in the openprinterex() call.
1574 * Differences between NT4 and NT 2000.
1577 * On NT4, you only have a global devicemode. This global devicemode can be changed
1578 * by the administrator (or by a user with enough privs). Everytime a user
1579 * wants to print, the devicemode is resetted to the default. In Word, everytime
1580 * you print, the printer's characteristics are always reset to the global devicemode.
1584 * In W2K, there is the notion of per-user devicemode. The first time you use
1585 * a printer, a per-user devicemode is build from the global devicemode.
1586 * If you change your per-user devicemode, it is saved in the registry, under the
1587 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1588 * printer preferences available.
1590 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1591 * on the General Tab of the printer properties windows.
1593 * To change the global devicemode: it's the "Printing Defaults..." button
1594 * on the Advanced Tab of the printer properties window.
1597 ********************************************************************/
1599 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1601 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1602 POLICY_HND *handle = &r_u->handle;
1606 struct current_user user;
1607 Printer_entry *Printer=NULL;
1609 if ( !q_u->printername )
1610 return WERR_INVALID_PRINTER_NAME;
1612 /* some sanity check because you can open a printer or a print server */
1613 /* aka: \\server\printer or \\server */
1615 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1617 DEBUGADD(3,("checking name: %s\n",name));
1619 if (!open_printer_hnd(p, handle, name, 0))
1620 return WERR_INVALID_PRINTER_NAME;
1622 Printer=find_printer_index_by_hnd(p, handle);
1624 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1625 "handle we created for printer %s\n", name ));
1626 close_printer_handle(p,handle);
1627 return WERR_INVALID_PRINTER_NAME;
1630 get_current_user(&user, p);
1633 * First case: the user is opening the print server:
1635 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1636 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1638 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1639 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1640 * or if the user is listed in the smb.conf printer admin parameter.
1642 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1643 * client view printer folder, but does not show the MSAPW.
1645 * Note: this test needs code to check access rights here too. Jeremy
1646 * could you look at this?
1648 * Second case: the user is opening a printer:
1649 * NT doesn't let us connect to a printer if the connecting user
1650 * doesn't have print permission.
1653 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1655 /* Printserver handles use global struct... */
1659 /* Map standard access rights to object specific access rights */
1661 se_map_standard(&printer_default->access_required,
1662 &printserver_std_mapping);
1664 /* Deny any object specific bits that don't apply to print
1665 servers (i.e printer and job specific bits) */
1667 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1669 if (printer_default->access_required &
1670 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1671 DEBUG(3, ("access DENIED for non-printserver bits"));
1672 close_printer_handle(p, handle);
1673 return WERR_ACCESS_DENIED;
1676 /* Allow admin access */
1678 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1680 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1682 if (!lp_ms_add_printer_wizard()) {
1683 close_printer_handle(p, handle);
1684 return WERR_ACCESS_DENIED;
1687 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1688 and not a printer admin, then fail */
1691 && !user_has_privileges( user.nt_user_token, &se_printop )
1692 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1694 close_printer_handle(p, handle);
1695 return WERR_ACCESS_DENIED;
1698 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1702 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1705 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1706 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1708 /* We fall through to return WERR_OK */
1713 /* NT doesn't let us connect to a printer if the connecting user
1714 doesn't have print permission. */
1716 if (!get_printer_snum(p, handle, &snum)) {
1717 close_printer_handle(p, handle);
1721 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1723 /* map an empty access mask to the minimum access mask */
1724 if (printer_default->access_required == 0x0)
1725 printer_default->access_required = PRINTER_ACCESS_USE;
1728 * If we are not serving the printer driver for this printer,
1729 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1730 * will keep NT clients happy --jerry
1733 if (lp_use_client_driver(snum)
1734 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1736 printer_default->access_required = PRINTER_ACCESS_USE;
1739 /* check smb.conf parameters and the the sec_desc */
1741 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1742 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1743 return WERR_ACCESS_DENIED;
1746 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1747 DEBUG(3, ("access DENIED for printer open\n"));
1748 close_printer_handle(p, handle);
1749 return WERR_ACCESS_DENIED;
1752 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1753 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1754 close_printer_handle(p, handle);
1755 return WERR_ACCESS_DENIED;
1758 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1759 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1761 printer_default->access_required = PRINTER_ACCESS_USE;
1763 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1764 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1768 Printer->access_granted = printer_default->access_required;
1771 * If the client sent a devmode in the OpenPrinter() call, then
1772 * save it here in case we get a job submission on this handle
1775 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1776 && q_u->printer_default.devmode_cont.devmode_ptr )
1778 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1779 &Printer->nt_devmode );
1782 #if 0 /* JERRY -- I'm doubtful this is really effective */
1783 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1784 optimization in Windows 2000 clients --jerry */
1786 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1787 && (RA_WIN2K == get_remote_arch()) )
1789 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1790 sys_usleep( 500000 );
1797 /****************************************************************************
1798 ****************************************************************************/
1800 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1801 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1807 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1816 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1817 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1823 printer->info_3=NULL;
1824 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1828 printer->info_6=NULL;
1829 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1839 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1840 NT_DEVICEMODE **pp_nt_devmode)
1842 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1845 * Ensure nt_devmode is a valid pointer
1846 * as we will be overwriting it.
1849 if (nt_devmode == NULL) {
1850 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1851 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1855 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1856 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1858 nt_devmode->specversion=devmode->specversion;
1859 nt_devmode->driverversion=devmode->driverversion;
1860 nt_devmode->size=devmode->size;
1861 nt_devmode->fields=devmode->fields;
1862 nt_devmode->orientation=devmode->orientation;
1863 nt_devmode->papersize=devmode->papersize;
1864 nt_devmode->paperlength=devmode->paperlength;
1865 nt_devmode->paperwidth=devmode->paperwidth;
1866 nt_devmode->scale=devmode->scale;
1867 nt_devmode->copies=devmode->copies;
1868 nt_devmode->defaultsource=devmode->defaultsource;
1869 nt_devmode->printquality=devmode->printquality;
1870 nt_devmode->color=devmode->color;
1871 nt_devmode->duplex=devmode->duplex;
1872 nt_devmode->yresolution=devmode->yresolution;
1873 nt_devmode->ttoption=devmode->ttoption;
1874 nt_devmode->collate=devmode->collate;
1876 nt_devmode->logpixels=devmode->logpixels;
1877 nt_devmode->bitsperpel=devmode->bitsperpel;
1878 nt_devmode->pelswidth=devmode->pelswidth;
1879 nt_devmode->pelsheight=devmode->pelsheight;
1880 nt_devmode->displayflags=devmode->displayflags;
1881 nt_devmode->displayfrequency=devmode->displayfrequency;
1882 nt_devmode->icmmethod=devmode->icmmethod;
1883 nt_devmode->icmintent=devmode->icmintent;
1884 nt_devmode->mediatype=devmode->mediatype;
1885 nt_devmode->dithertype=devmode->dithertype;
1886 nt_devmode->reserved1=devmode->reserved1;
1887 nt_devmode->reserved2=devmode->reserved2;
1888 nt_devmode->panningwidth=devmode->panningwidth;
1889 nt_devmode->panningheight=devmode->panningheight;
1892 * Only change private and driverextra if the incoming devmode
1893 * has a new one. JRA.
1896 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1897 SAFE_FREE(nt_devmode->nt_dev_private);
1898 nt_devmode->driverextra=devmode->driverextra;
1899 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1901 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1904 *pp_nt_devmode = nt_devmode;
1909 /********************************************************************
1910 * _spoolss_enddocprinter_internal.
1911 ********************************************************************/
1913 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1915 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1919 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1923 if (!get_printer_snum(p, handle, &snum))
1926 Printer->document_started=False;
1927 print_job_end(snum, Printer->jobid,True);
1928 /* error codes unhandled so far ... */
1933 /********************************************************************
1934 * api_spoolss_closeprinter
1935 ********************************************************************/
1937 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1939 POLICY_HND *handle = &q_u->handle;
1941 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1943 if (Printer && Printer->document_started)
1944 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1946 if (!close_printer_handle(p, handle))
1949 /* clear the returned printer handle. Observed behavior
1950 from Win2k server. Don't think this really matters.
1951 Previous code just copied the value of the closed
1954 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1959 /********************************************************************
1960 * api_spoolss_deleteprinter
1962 ********************************************************************/
1964 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1966 POLICY_HND *handle = &q_u->handle;
1967 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1970 if (Printer && Printer->document_started)
1971 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1973 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1975 result = delete_printer_handle(p, handle);
1977 update_c_setprinter(False);
1982 /*******************************************************************
1983 * static function to lookup the version id corresponding to an
1984 * long architecture string
1985 ******************************************************************/
1987 static int get_version_id (char * arch)
1990 struct table_node archi_table[]= {
1992 {"Windows 4.0", "WIN40", 0 },
1993 {"Windows NT x86", "W32X86", 2 },
1994 {"Windows NT R4000", "W32MIPS", 2 },
1995 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1996 {"Windows NT PowerPC", "W32PPC", 2 },
1997 {"Windows IA64", "IA64", 3 },
1998 {"Windows x64", "x64", 3 },
2002 for (i=0; archi_table[i].long_archi != NULL; i++)
2004 if (strcmp(arch, archi_table[i].long_archi) == 0)
2005 return (archi_table[i].version);
2011 /********************************************************************
2012 * _spoolss_deleteprinterdriver
2013 ********************************************************************/
2015 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2019 NT_PRINTER_DRIVER_INFO_LEVEL info;
2020 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2022 struct current_user user;
2024 WERROR status_win2k = WERR_ACCESS_DENIED;
2026 get_current_user(&user, p);
2028 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2029 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2031 /* check that we have a valid driver name first */
2033 if ((version=get_version_id(arch)) == -1)
2034 return WERR_INVALID_ENVIRONMENT;
2037 ZERO_STRUCT(info_win2k);
2039 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2041 /* try for Win2k driver if "Windows NT x86" */
2043 if ( version == 2 ) {
2045 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2046 status = WERR_UNKNOWN_PRINTER_DRIVER;
2050 /* otherwise it was a failure */
2052 status = WERR_UNKNOWN_PRINTER_DRIVER;
2058 if (printer_driver_in_use(info.info_3)) {
2059 status = WERR_PRINTER_DRIVER_IN_USE;
2065 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2067 /* if we get to here, we now have 2 driver info structures to remove */
2068 /* remove the Win2k driver first*/
2070 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2071 free_a_printer_driver( info_win2k, 3 );
2073 /* this should not have failed---if it did, report to client */
2074 if ( !W_ERROR_IS_OK(status_win2k) )
2079 status = delete_printer_driver(info.info_3, &user, version, False);
2081 /* if at least one of the deletes succeeded return OK */
2083 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2087 free_a_printer_driver( info, 3 );
2092 /********************************************************************
2093 * spoolss_deleteprinterdriverex
2094 ********************************************************************/
2096 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2100 NT_PRINTER_DRIVER_INFO_LEVEL info;
2101 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2103 uint32 flags = q_u->delete_flags;
2105 struct current_user user;
2107 WERROR status_win2k = WERR_ACCESS_DENIED;
2109 get_current_user(&user, p);
2111 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2112 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2114 /* check that we have a valid driver name first */
2115 if ((version=get_version_id(arch)) == -1) {
2116 /* this is what NT returns */
2117 return WERR_INVALID_ENVIRONMENT;
2120 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2121 version = q_u->version;
2124 ZERO_STRUCT(info_win2k);
2126 status = get_a_printer_driver(&info, 3, driver, arch, version);
2128 if ( !W_ERROR_IS_OK(status) )
2131 * if the client asked for a specific version,
2132 * or this is something other than Windows NT x86,
2136 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2139 /* try for Win2k driver if "Windows NT x86" */
2142 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2143 status = WERR_UNKNOWN_PRINTER_DRIVER;
2148 if ( printer_driver_in_use(info.info_3) ) {
2149 status = WERR_PRINTER_DRIVER_IN_USE;
2154 * we have a couple of cases to consider.
2155 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2156 * then the delete should fail if **any** files overlap with
2158 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2159 * non-overlapping files
2160 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2161 * is set, the do not delete any files
2162 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2165 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2167 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2169 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2170 /* no idea of the correct error here */
2171 status = WERR_ACCESS_DENIED;
2176 /* also check for W32X86/3 if necessary; maybe we already have? */
2178 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2179 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2182 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2183 /* no idea of the correct error here */
2184 free_a_printer_driver( info_win2k, 3 );
2185 status = WERR_ACCESS_DENIED;
2189 /* if we get to here, we now have 2 driver info structures to remove */
2190 /* remove the Win2k driver first*/
2192 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2193 free_a_printer_driver( info_win2k, 3 );
2195 /* this should not have failed---if it did, report to client */
2197 if ( !W_ERROR_IS_OK(status_win2k) )
2202 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2204 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2207 free_a_printer_driver( info, 3 );
2213 /****************************************************************************
2214 Internal routine for retreiving printerdata
2215 ***************************************************************************/
2217 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2218 const char *key, const char *value, uint32 *type, uint8 **data,
2219 uint32 *needed, uint32 in_size )
2221 REGISTRY_VALUE *val;
2225 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2226 return WERR_BADFILE;
2228 *type = regval_type( val );
2230 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2232 size = regval_size( val );
2234 /* copy the min(in_size, len) */
2237 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2239 /* special case for 0 length values */
2241 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2245 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2254 DEBUG(5,("get_printer_dataex: copy done\n"));
2259 /****************************************************************************
2260 Internal routine for removing printerdata
2261 ***************************************************************************/
2263 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2265 return delete_printer_data( printer->info_2, key, value );
2268 /****************************************************************************
2269 Internal routine for storing printerdata
2270 ***************************************************************************/
2272 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2273 uint32 type, uint8 *data, int real_len )
2275 delete_printer_data( printer->info_2, key, value );
2277 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2280 /********************************************************************
2281 GetPrinterData on a printer server Handle.
2282 ********************************************************************/
2284 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2288 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2290 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2292 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2298 if (!StrCaseCmp(value, "BeepEnabled")) {
2300 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2302 SIVAL(*data, 0, 0x00);
2307 if (!StrCaseCmp(value, "EventLog")) {
2309 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2311 /* formally was 0x1b */
2312 SIVAL(*data, 0, 0x0);
2317 if (!StrCaseCmp(value, "NetPopup")) {
2319 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2321 SIVAL(*data, 0, 0x00);
2326 if (!StrCaseCmp(value, "MajorVersion")) {
2328 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2331 /* Windows NT 4.0 seems to not allow uploading of drivers
2332 to a server that reports 0x3 as the MajorVersion.
2333 need to investigate more how Win2k gets around this .
2336 if ( RA_WINNT == get_remote_arch() )
2345 if (!StrCaseCmp(value, "MinorVersion")) {
2347 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2355 * uint32 size = 0x114
2357 * uint32 minor = [0|1]
2358 * uint32 build = [2195|2600]
2359 * extra unicode string = e.g. "Service Pack 3"
2361 if (!StrCaseCmp(value, "OSVersion")) {
2365 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2368 SIVAL(*data, 0, *needed); /* size */
2369 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2371 SIVAL(*data, 12, 2195); /* build */
2373 /* leave extra string empty */
2379 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2380 const char *string="C:\\PRINTERS";
2382 *needed = 2*(strlen(string)+1);
2383 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2385 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2387 /* it's done by hand ready to go on the wire */
2388 for (i=0; i<strlen(string); i++) {
2389 (*data)[2*i]=string[i];
2390 (*data)[2*i+1]='\0';
2395 if (!StrCaseCmp(value, "Architecture")) {
2396 const char *string="Windows NT x86";
2398 *needed = 2*(strlen(string)+1);
2399 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2401 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2402 for (i=0; i<strlen(string); i++) {
2403 (*data)[2*i]=string[i];
2404 (*data)[2*i+1]='\0';
2409 if (!StrCaseCmp(value, "DsPresent")) {
2411 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2414 /* only show the publish check box if we are a
2415 memeber of a AD domain */
2417 if ( lp_security() == SEC_ADS )
2418 SIVAL(*data, 0, 0x01);
2420 SIVAL(*data, 0, 0x00);
2426 if (!StrCaseCmp(value, "DNSMachineName")) {
2429 if (!get_mydnsfullname(hostname))
2430 return WERR_BADFILE;
2432 *needed = 2*(strlen(hostname)+1);
2433 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2435 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2436 for (i=0; i<strlen(hostname); i++) {
2437 (*data)[2*i]=hostname[i];
2438 (*data)[2*i+1]='\0';
2444 return WERR_BADFILE;
2447 /********************************************************************
2448 * spoolss_getprinterdata
2449 ********************************************************************/
2451 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2453 POLICY_HND *handle = &q_u->handle;
2454 UNISTR2 *valuename = &q_u->valuename;
2455 uint32 in_size = q_u->size;
2456 uint32 *type = &r_u->type;
2457 uint32 *out_size = &r_u->size;
2458 uint8 **data = &r_u->data;
2459 uint32 *needed = &r_u->needed;
2462 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2463 NT_PRINTER_INFO_LEVEL *printer = NULL;
2467 * Reminder: when it's a string, the length is in BYTES
2468 * even if UNICODE is negociated.
2473 *out_size = in_size;
2475 /* in case of problem, return some default values */
2480 DEBUG(4,("_spoolss_getprinterdata\n"));
2483 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2484 status = WERR_BADFID;
2488 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2490 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2491 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2494 if ( !get_printer_snum(p,handle, &snum) ) {
2495 status = WERR_BADFID;
2499 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2500 if ( !W_ERROR_IS_OK(status) )
2503 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2505 if ( strequal(value, "ChangeId") ) {
2507 *needed = sizeof(uint32);
2508 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2509 status = WERR_NOMEM;
2512 SIVAL( *data, 0, printer->info_2->changeid );
2516 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2519 if (*needed > *out_size)
2520 status = WERR_MORE_DATA;
2523 if ( !W_ERROR_IS_OK(status) )
2525 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2527 /* reply this param doesn't exist */
2530 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2532 free_a_printer( &printer, 2 );
2541 /* cleanup & exit */
2544 free_a_printer( &printer, 2 );
2549 /*********************************************************
2550 Connect to the client machine.
2551 **********************************************************/
2553 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2554 struct in_addr *client_ip, const char *remote_machine)
2556 ZERO_STRUCTP(the_cli);
2558 if(cli_initialise(the_cli) == NULL) {
2559 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2563 if ( is_zero_ip(*client_ip) ) {
2564 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2565 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2566 cli_shutdown(the_cli);
2570 if (ismyip(the_cli->dest_ip)) {
2571 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2572 cli_shutdown(the_cli);
2577 the_cli->dest_ip.s_addr = client_ip->s_addr;
2578 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2579 inet_ntoa(*client_ip) ));
2582 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2583 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) ));
2584 cli_shutdown(the_cli);
2588 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2589 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2591 cli_shutdown(the_cli);
2595 the_cli->protocol = PROTOCOL_NT1;
2596 cli_setup_signing_state(the_cli, lp_client_signing());
2598 if (!cli_negprot(the_cli)) {
2599 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2600 cli_shutdown(the_cli);
2604 if (the_cli->protocol != PROTOCOL_NT1) {
2605 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2606 cli_shutdown(the_cli);
2611 * Do an anonymous session setup.
2614 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2615 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2616 cli_shutdown(the_cli);
2620 if (!(the_cli->sec_mode & 1)) {
2621 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2622 cli_shutdown(the_cli);
2626 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2627 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) ));
2628 cli_shutdown(the_cli);
2633 * Ok - we have an anonymous connection to the IPC$ share.
2634 * Now start the NT Domain stuff :-).
2637 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2638 DEBUG(0,("spoolss_connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2639 cli_nt_session_close(the_cli);
2640 cli_ulogoff(the_cli);
2641 cli_shutdown(the_cli);
2648 /***************************************************************************
2649 Connect to the client.
2650 ****************************************************************************/
2652 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2653 uint32 localprinter, uint32 type,
2654 POLICY_HND *handle, struct in_addr *client_ip)
2659 * If it's the first connection, contact the client
2660 * and connect to the IPC$ share anonymously
2662 if (smb_connections==0) {
2663 fstring unix_printer;
2665 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2667 ZERO_STRUCT(notify_cli);
2669 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2672 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2673 /* Tell the connections db we're now interested in printer
2674 * notify messages. */
2675 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2679 * Tell the specific printing tdb we want messages for this printer
2680 * by registering our PID.
2683 if (!print_notify_register_pid(snum))
2684 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2688 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2691 if (!W_ERROR_IS_OK(result))
2692 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2693 dos_errstr(result)));
2695 return (W_ERROR_IS_OK(result));
2698 /********************************************************************
2700 * ReplyFindFirstPrinterChangeNotifyEx
2702 * before replying OK: status=0 a rpc call is made to the workstation
2703 * asking ReplyOpenPrinter
2705 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2706 * called from api_spoolss_rffpcnex
2707 ********************************************************************/
2709 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2711 POLICY_HND *handle = &q_u->handle;
2712 uint32 flags = q_u->flags;
2713 uint32 options = q_u->options;
2714 UNISTR2 *localmachine = &q_u->localmachine;
2715 uint32 printerlocal = q_u->printerlocal;
2717 SPOOL_NOTIFY_OPTION *option = q_u->option;
2718 struct in_addr client_ip;
2720 /* store the notify value in the printer struct */
2722 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2725 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2729 Printer->notify.flags=flags;
2730 Printer->notify.options=options;
2731 Printer->notify.printerlocal=printerlocal;
2733 if (Printer->notify.option)
2734 free_spool_notify_option(&Printer->notify.option);
2736 Printer->notify.option=dup_spool_notify_option(option);
2738 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2739 sizeof(Printer->notify.localmachine)-1);
2741 /* Connect to the client machine and send a ReplyOpenPrinter */
2743 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2745 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2746 !get_printer_snum(p, handle, &snum) )
2749 client_ip.s_addr = inet_addr(p->conn->client_address);
2751 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2752 Printer->notify.printerlocal, 1,
2753 &Printer->notify.client_hnd, &client_ip))
2754 return WERR_SERVER_UNAVAILABLE;
2756 Printer->notify.client_connected=True;
2761 /*******************************************************************
2762 * fill a notify_info_data with the servername
2763 ********************************************************************/
2765 void spoolss_notify_server_name(int snum,
2766 SPOOL_NOTIFY_INFO_DATA *data,
2767 print_queue_struct *queue,
2768 NT_PRINTER_INFO_LEVEL *printer,
2769 TALLOC_CTX *mem_ctx)
2774 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2776 data->notify_data.data.length = len;
2777 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2779 if (!data->notify_data.data.string) {
2780 data->notify_data.data.length = 0;
2784 memcpy(data->notify_data.data.string, temp, len);
2787 /*******************************************************************
2788 * fill a notify_info_data with the printername (not including the servername).
2789 ********************************************************************/
2791 void spoolss_notify_printer_name(int snum,
2792 SPOOL_NOTIFY_INFO_DATA *data,
2793 print_queue_struct *queue,
2794 NT_PRINTER_INFO_LEVEL *printer,
2795 TALLOC_CTX *mem_ctx)
2800 /* the notify name should not contain the \\server\ part */
2801 char *p = strrchr(printer->info_2->printername, '\\');
2804 p = printer->info_2->printername;
2809 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2811 data->notify_data.data.length = len;
2812 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2814 if (!data->notify_data.data.string) {
2815 data->notify_data.data.length = 0;
2819 memcpy(data->notify_data.data.string, temp, len);
2822 /*******************************************************************
2823 * fill a notify_info_data with the servicename
2824 ********************************************************************/
2826 void spoolss_notify_share_name(int snum,
2827 SPOOL_NOTIFY_INFO_DATA *data,
2828 print_queue_struct *queue,
2829 NT_PRINTER_INFO_LEVEL *printer,
2830 TALLOC_CTX *mem_ctx)
2835 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2837 data->notify_data.data.length = len;
2838 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2840 if (!data->notify_data.data.string) {
2841 data->notify_data.data.length = 0;
2845 memcpy(data->notify_data.data.string, temp, len);
2848 /*******************************************************************
2849 * fill a notify_info_data with the port name
2850 ********************************************************************/
2852 void spoolss_notify_port_name(int snum,
2853 SPOOL_NOTIFY_INFO_DATA *data,
2854 print_queue_struct *queue,
2855 NT_PRINTER_INFO_LEVEL *printer,
2856 TALLOC_CTX *mem_ctx)
2861 /* even if it's strange, that's consistant in all the code */
2863 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2865 data->notify_data.data.length = len;
2866 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2868 if (!data->notify_data.data.string) {
2869 data->notify_data.data.length = 0;
2873 memcpy(data->notify_data.data.string, temp, len);
2876 /*******************************************************************
2877 * fill a notify_info_data with the printername
2878 * but it doesn't exist, have to see what to do
2879 ********************************************************************/
2881 void spoolss_notify_driver_name(int snum,
2882 SPOOL_NOTIFY_INFO_DATA *data,
2883 print_queue_struct *queue,
2884 NT_PRINTER_INFO_LEVEL *printer,
2885 TALLOC_CTX *mem_ctx)
2890 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2892 data->notify_data.data.length = len;
2893 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2895 if (!data->notify_data.data.string) {
2896 data->notify_data.data.length = 0;
2900 memcpy(data->notify_data.data.string, temp, len);
2903 /*******************************************************************
2904 * fill a notify_info_data with the comment
2905 ********************************************************************/
2907 void spoolss_notify_comment(int snum,
2908 SPOOL_NOTIFY_INFO_DATA *data,
2909 print_queue_struct *queue,
2910 NT_PRINTER_INFO_LEVEL *printer,
2911 TALLOC_CTX *mem_ctx)
2916 if (*printer->info_2->comment == '\0')
2917 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2919 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2921 data->notify_data.data.length = len;
2922 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2924 if (!data->notify_data.data.string) {
2925 data->notify_data.data.length = 0;
2929 memcpy(data->notify_data.data.string, temp, len);
2932 /*******************************************************************
2933 * fill a notify_info_data with the comment
2934 * location = "Room 1, floor 2, building 3"
2935 ********************************************************************/
2937 void spoolss_notify_location(int snum,
2938 SPOOL_NOTIFY_INFO_DATA *data,
2939 print_queue_struct *queue,
2940 NT_PRINTER_INFO_LEVEL *printer,
2941 TALLOC_CTX *mem_ctx)
2946 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2948 data->notify_data.data.length = len;
2949 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2951 if (!data->notify_data.data.string) {
2952 data->notify_data.data.length = 0;
2956 memcpy(data->notify_data.data.string, temp, len);
2959 /*******************************************************************
2960 * fill a notify_info_data with the device mode
2961 * jfm:xxxx don't to it for know but that's a real problem !!!
2962 ********************************************************************/
2964 static void spoolss_notify_devmode(int snum,
2965 SPOOL_NOTIFY_INFO_DATA *data,
2966 print_queue_struct *queue,
2967 NT_PRINTER_INFO_LEVEL *printer,
2968 TALLOC_CTX *mem_ctx)
2972 /*******************************************************************
2973 * fill a notify_info_data with the separator file name
2974 ********************************************************************/
2976 void spoolss_notify_sepfile(int snum,
2977 SPOOL_NOTIFY_INFO_DATA *data,
2978 print_queue_struct *queue,
2979 NT_PRINTER_INFO_LEVEL *printer,
2980 TALLOC_CTX *mem_ctx)
2985 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2987 data->notify_data.data.length = len;
2988 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2990 if (!data->notify_data.data.string) {
2991 data->notify_data.data.length = 0;
2995 memcpy(data->notify_data.data.string, temp, len);
2998 /*******************************************************************
2999 * fill a notify_info_data with the print processor
3000 * jfm:xxxx return always winprint to indicate we don't do anything to it
3001 ********************************************************************/
3003 void spoolss_notify_print_processor(int snum,
3004 SPOOL_NOTIFY_INFO_DATA *data,
3005 print_queue_struct *queue,
3006 NT_PRINTER_INFO_LEVEL *printer,
3007 TALLOC_CTX *mem_ctx)
3012 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3014 data->notify_data.data.length = len;
3015 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3017 if (!data->notify_data.data.string) {
3018 data->notify_data.data.length = 0;
3022 memcpy(data->notify_data.data.string, temp, len);
3025 /*******************************************************************
3026 * fill a notify_info_data with the print processor options
3027 * jfm:xxxx send an empty string
3028 ********************************************************************/
3030 void spoolss_notify_parameters(int snum,
3031 SPOOL_NOTIFY_INFO_DATA *data,
3032 print_queue_struct *queue,
3033 NT_PRINTER_INFO_LEVEL *printer,
3034 TALLOC_CTX *mem_ctx)
3039 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3041 data->notify_data.data.length = len;
3042 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3044 if (!data->notify_data.data.string) {
3045 data->notify_data.data.length = 0;
3049 memcpy(data->notify_data.data.string, temp, len);
3052 /*******************************************************************
3053 * fill a notify_info_data with the data type
3054 * jfm:xxxx always send RAW as data type
3055 ********************************************************************/
3057 void spoolss_notify_datatype(int snum,
3058 SPOOL_NOTIFY_INFO_DATA *data,
3059 print_queue_struct *queue,
3060 NT_PRINTER_INFO_LEVEL *printer,
3061 TALLOC_CTX *mem_ctx)
3066 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3068 data->notify_data.data.length = len;
3069 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3071 if (!data->notify_data.data.string) {
3072 data->notify_data.data.length = 0;
3076 memcpy(data->notify_data.data.string, temp, len);
3079 /*******************************************************************
3080 * fill a notify_info_data with the security descriptor
3081 * jfm:xxxx send an null pointer to say no security desc
3082 * have to implement security before !
3083 ********************************************************************/
3085 static void spoolss_notify_security_desc(int snum,
3086 SPOOL_NOTIFY_INFO_DATA *data,
3087 print_queue_struct *queue,
3088 NT_PRINTER_INFO_LEVEL *printer,
3089 TALLOC_CTX *mem_ctx)
3091 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3092 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3095 /*******************************************************************
3096 * fill a notify_info_data with the attributes
3097 * jfm:xxxx a samba printer is always shared
3098 ********************************************************************/
3100 void spoolss_notify_attributes(int snum,
3101 SPOOL_NOTIFY_INFO_DATA *data,
3102 print_queue_struct *queue,
3103 NT_PRINTER_INFO_LEVEL *printer,
3104 TALLOC_CTX *mem_ctx)
3106 data->notify_data.value[0] = printer->info_2->attributes;
3107 data->notify_data.value[1] = 0;
3110 /*******************************************************************
3111 * fill a notify_info_data with the priority
3112 ********************************************************************/
3114 static void spoolss_notify_priority(int snum,
3115 SPOOL_NOTIFY_INFO_DATA *data,
3116 print_queue_struct *queue,
3117 NT_PRINTER_INFO_LEVEL *printer,
3118 TALLOC_CTX *mem_ctx)
3120 data->notify_data.value[0] = printer->info_2->priority;
3121 data->notify_data.value[1] = 0;
3124 /*******************************************************************
3125 * fill a notify_info_data with the default priority
3126 ********************************************************************/
3128 static void spoolss_notify_default_priority(int snum,
3129 SPOOL_NOTIFY_INFO_DATA *data,
3130 print_queue_struct *queue,
3131 NT_PRINTER_INFO_LEVEL *printer,
3132 TALLOC_CTX *mem_ctx)
3134 data->notify_data.value[0] = printer->info_2->default_priority;
3135 data->notify_data.value[1] = 0;
3138 /*******************************************************************
3139 * fill a notify_info_data with the start time
3140 ********************************************************************/
3142 static void spoolss_notify_start_time(int snum,
3143 SPOOL_NOTIFY_INFO_DATA *data,
3144 print_queue_struct *queue,
3145 NT_PRINTER_INFO_LEVEL *printer,
3146 TALLOC_CTX *mem_ctx)
3148 data->notify_data.value[0] = printer->info_2->starttime;
3149 data->notify_data.value[1] = 0;
3152 /*******************************************************************
3153 * fill a notify_info_data with the until time
3154 ********************************************************************/
3156 static void spoolss_notify_until_time(int snum,
3157 SPOOL_NOTIFY_INFO_DATA *data,
3158 print_queue_struct *queue,
3159 NT_PRINTER_INFO_LEVEL *printer,
3160 TALLOC_CTX *mem_ctx)
3162 data->notify_data.value[0] = printer->info_2->untiltime;
3163 data->notify_data.value[1] = 0;
3166 /*******************************************************************
3167 * fill a notify_info_data with the status
3168 ********************************************************************/
3170 static void spoolss_notify_status(int snum,
3171 SPOOL_NOTIFY_INFO_DATA *data,
3172 print_queue_struct *queue,
3173 NT_PRINTER_INFO_LEVEL *printer,
3174 TALLOC_CTX *mem_ctx)
3176 print_status_struct status;
3178 print_queue_length(snum, &status);
3179 data->notify_data.value[0]=(uint32) status.status;
3180 data->notify_data.value[1] = 0;
3183 /*******************************************************************
3184 * fill a notify_info_data with the number of jobs queued
3185 ********************************************************************/
3187 void spoolss_notify_cjobs(int snum,
3188 SPOOL_NOTIFY_INFO_DATA *data,
3189 print_queue_struct *queue,
3190 NT_PRINTER_INFO_LEVEL *printer,
3191 TALLOC_CTX *mem_ctx)
3193 data->notify_data.value[0] = print_queue_length(snum, NULL);
3194 data->notify_data.value[1] = 0;
3197 /*******************************************************************
3198 * fill a notify_info_data with the average ppm
3199 ********************************************************************/
3201 static void spoolss_notify_average_ppm(int snum,
3202 SPOOL_NOTIFY_INFO_DATA *data,
3203 print_queue_struct *queue,
3204 NT_PRINTER_INFO_LEVEL *printer,
3205 TALLOC_CTX *mem_ctx)
3207 /* always respond 8 pages per minutes */
3208 /* a little hard ! */
3209 data->notify_data.value[0] = printer->info_2->averageppm;
3210 data->notify_data.value[1] = 0;
3213 /*******************************************************************
3214 * fill a notify_info_data with username
3215 ********************************************************************/
3217 static void spoolss_notify_username(int snum,
3218 SPOOL_NOTIFY_INFO_DATA *data,
3219 print_queue_struct *queue,
3220 NT_PRINTER_INFO_LEVEL *printer,
3221 TALLOC_CTX *mem_ctx)
3226 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3228 data->notify_data.data.length = len;
3229 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3231 if (!data->notify_data.data.string) {
3232 data->notify_data.data.length = 0;
3236 memcpy(data->notify_data.data.string, temp, len);
3239 /*******************************************************************
3240 * fill a notify_info_data with job status
3241 ********************************************************************/
3243 static void spoolss_notify_job_status(int snum,
3244 SPOOL_NOTIFY_INFO_DATA *data,
3245 print_queue_struct *queue,
3246 NT_PRINTER_INFO_LEVEL *printer,
3247 TALLOC_CTX *mem_ctx)
3249 data->notify_data.value[0]=nt_printj_status(queue->status);
3250 data->notify_data.value[1] = 0;
3253 /*******************************************************************
3254 * fill a notify_info_data with job name
3255 ********************************************************************/
3257 static void spoolss_notify_job_name(int snum,
3258 SPOOL_NOTIFY_INFO_DATA *data,
3259 print_queue_struct *queue,
3260 NT_PRINTER_INFO_LEVEL *printer,
3261 TALLOC_CTX *mem_ctx)
3266 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3268 data->notify_data.data.length = len;
3269 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3271 if (!data->notify_data.data.string) {
3272 data->notify_data.data.length = 0;
3276 memcpy(data->notify_data.data.string, temp, len);
3279 /*******************************************************************
3280 * fill a notify_info_data with job status
3281 ********************************************************************/
3283 static void spoolss_notify_job_status_string(int snum,
3284 SPOOL_NOTIFY_INFO_DATA *data,
3285 print_queue_struct *queue,
3286 NT_PRINTER_INFO_LEVEL *printer,
3287 TALLOC_CTX *mem_ctx)
3290 * Now we're returning job status codes we just return a "" here. JRA.
3297 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3300 switch (queue->status) {
3305 p = ""; /* NT provides the paused string */
3314 #endif /* NO LONGER NEEDED. */
3316 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3318 data->notify_data.data.length = len;
3319 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3321 if (!data->notify_data.data.string) {
3322 data->notify_data.data.length = 0;
3326 memcpy(data->notify_data.data.string, temp, len);
3329 /*******************************************************************
3330 * fill a notify_info_data with job time
3331 ********************************************************************/
3333 static void spoolss_notify_job_time(int snum,
3334 SPOOL_NOTIFY_INFO_DATA *data,
3335 print_queue_struct *queue,
3336 NT_PRINTER_INFO_LEVEL *printer,
3337 TALLOC_CTX *mem_ctx)
3339 data->notify_data.value[0]=0x0;
3340 data->notify_data.value[1]=0;
3343 /*******************************************************************
3344 * fill a notify_info_data with job size
3345 ********************************************************************/
3347 static void spoolss_notify_job_size(int snum,
3348 SPOOL_NOTIFY_INFO_DATA *data,
3349 print_queue_struct *queue,
3350 NT_PRINTER_INFO_LEVEL *printer,
3351 TALLOC_CTX *mem_ctx)
3353 data->notify_data.value[0]=queue->size;
3354 data->notify_data.value[1]=0;
3357 /*******************************************************************
3358 * fill a notify_info_data with page info
3359 ********************************************************************/
3360 static void spoolss_notify_total_pages(int snum,
3361 SPOOL_NOTIFY_INFO_DATA *data,
3362 print_queue_struct *queue,
3363 NT_PRINTER_INFO_LEVEL *printer,
3364 TALLOC_CTX *mem_ctx)
3366 data->notify_data.value[0]=queue->page_count;
3367 data->notify_data.value[1]=0;
3370 /*******************************************************************
3371 * fill a notify_info_data with pages printed info.
3372 ********************************************************************/
3373 static void spoolss_notify_pages_printed(int snum,
3374 SPOOL_NOTIFY_INFO_DATA *data,
3375 print_queue_struct *queue,
3376 NT_PRINTER_INFO_LEVEL *printer,
3377 TALLOC_CTX *mem_ctx)
3379 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3380 data->notify_data.value[1]=0;
3383 /*******************************************************************
3384 Fill a notify_info_data with job position.
3385 ********************************************************************/
3387 static void spoolss_notify_job_position(int snum,
3388 SPOOL_NOTIFY_INFO_DATA *data,
3389 print_queue_struct *queue,
3390 NT_PRINTER_INFO_LEVEL *printer,
3391 TALLOC_CTX *mem_ctx)
3393 data->notify_data.value[0]=queue->job;
3394 data->notify_data.value[1]=0;
3397 /*******************************************************************
3398 Fill a notify_info_data with submitted time.
3399 ********************************************************************/
3401 static void spoolss_notify_submitted_time(int snum,
3402 SPOOL_NOTIFY_INFO_DATA *data,
3403 print_queue_struct *queue,
3404 NT_PRINTER_INFO_LEVEL *printer,
3405 TALLOC_CTX *mem_ctx)
3412 t=gmtime(&queue->time);
3414 len = sizeof(SYSTEMTIME);
3416 data->notify_data.data.length = len;
3417 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3419 if (!data->notify_data.data.string) {
3420 data->notify_data.data.length = 0;
3424 make_systemtime(&st, t);
3427 * Systemtime must be linearized as a set of UINT16's.
3428 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3431 p = (char *)data->notify_data.data.string;
3432 SSVAL(p, 0, st.year);
3433 SSVAL(p, 2, st.month);
3434 SSVAL(p, 4, st.dayofweek);
3435 SSVAL(p, 6, st.day);
3436 SSVAL(p, 8, st.hour);
3437 SSVAL(p, 10, st.minute);
3438 SSVAL(p, 12, st.second);
3439 SSVAL(p, 14, st.milliseconds);
3442 struct s_notify_info_data_table
3448 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3449 print_queue_struct *queue,
3450 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3453 /* A table describing the various print notification constants and
3454 whether the notification data is a pointer to a variable sized
3455 buffer, a one value uint32 or a two value uint32. */
3457 static const struct s_notify_info_data_table notify_info_data_table[] =
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3508 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3511 /*******************************************************************
3512 Return the size of info_data structure.
3513 ********************************************************************/
3515 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3519 for (i = 0; i < sizeof(notify_info_data_table); i++)
3521 if ( (notify_info_data_table[i].type == type)
3522 && (notify_info_data_table[i].field == field) )
3524 switch(notify_info_data_table[i].size)
3526 case NOTIFY_ONE_VALUE:
3527 case NOTIFY_TWO_VALUE:
3532 /* The only pointer notify data I have seen on
3533 the wire is the submitted time and this has
3534 the notify size set to 4. -tpot */
3536 case NOTIFY_POINTER:
3539 case NOTIFY_SECDESC:
3545 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3550 /*******************************************************************
3551 Return the type of notify_info_data.
3552 ********************************************************************/
3554 static int type_of_notify_info_data(uint16 type, uint16 field)
3558 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3559 if (notify_info_data_table[i].type == type &&
3560 notify_info_data_table[i].field == field)
3561 return notify_info_data_table[i].size;
3567 /****************************************************************************
3568 ****************************************************************************/
3570 static int search_notify(uint16 type, uint16 field, int *value)
3574 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3575 if (notify_info_data_table[i].type == type &&
3576 notify_info_data_table[i].field == field &&
3577 notify_info_data_table[i].fn != NULL) {
3586 /****************************************************************************
3587 ****************************************************************************/
3589 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3591 info_data->type = type;
3592 info_data->field = field;
3593 info_data->reserved = 0;
3595 info_data->size = size_of_notify_info_data(type, field);
3596 info_data->enc_type = type_of_notify_info_data(type, field);
3603 /*******************************************************************
3605 * fill a notify_info struct with info asked
3607 ********************************************************************/
3609 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3610 snum, SPOOL_NOTIFY_OPTION_TYPE
3611 *option_type, uint32 id,
3612 TALLOC_CTX *mem_ctx)
3618 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3619 NT_PRINTER_INFO_LEVEL *printer = NULL;
3620 print_queue_struct *queue=NULL;
3622 type=option_type->type;
3624 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3625 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3626 option_type->count, lp_servicename(snum)));
3628 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3631 for(field_num=0; field_num<option_type->count; field_num++) {
3632 field = option_type->fields[field_num];
3634 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3636 if (!search_notify(type, field, &j) )
3639 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3640 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3645 current_data = &info->data[info->count];
3647 construct_info_data(current_data, type, field, id);
3649 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3650 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3652 notify_info_data_table[j].fn(snum, current_data, queue,
3658 free_a_printer(&printer, 2);
3662 /*******************************************************************
3664 * fill a notify_info struct with info asked
3666 ********************************************************************/
3668 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3669 SPOOL_NOTIFY_INFO *info,
3670 NT_PRINTER_INFO_LEVEL *printer,
3671 int snum, SPOOL_NOTIFY_OPTION_TYPE
3672 *option_type, uint32 id,
3673 TALLOC_CTX *mem_ctx)
3679 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3681 DEBUG(4,("construct_notify_jobs_info\n"));
3683 type = option_type->type;
3685 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3686 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3687 option_type->count));
3689 for(field_num=0; field_num<option_type->count; field_num++) {
3690 field = option_type->fields[field_num];
3692 if (!search_notify(type, field, &j) )
3695 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3696 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3699 else info->data = tid;
3701 current_data=&(info->data[info->count]);
3703 construct_info_data(current_data, type, field, id);
3704 notify_info_data_table[j].fn(snum, current_data, queue,
3713 * JFM: The enumeration is not that simple, it's even non obvious.
3715 * let's take an example: I want to monitor the PRINTER SERVER for
3716 * the printer's name and the number of jobs currently queued.
3717 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3718 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3720 * I have 3 printers on the back of my server.
3722 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3725 * 1 printer 1 name 1
3726 * 2 printer 1 cjob 1
3727 * 3 printer 2 name 2
3728 * 4 printer 2 cjob 2
3729 * 5 printer 3 name 3
3730 * 6 printer 3 name 3
3732 * that's the print server case, the printer case is even worse.
3735 /*******************************************************************
3737 * enumerate all printers on the printserver
3738 * fill a notify_info struct with info asked
3740 ********************************************************************/
3742 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3743 SPOOL_NOTIFY_INFO *info,
3744 TALLOC_CTX *mem_ctx)
3747 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3748 int n_services=lp_numservices();
3750 SPOOL_NOTIFY_OPTION *option;
3751 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3753 DEBUG(4,("printserver_notify_info\n"));
3758 option=Printer->notify.option;
3763 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3764 sending a ffpcn() request first */
3769 for (i=0; i<option->count; i++) {
3770 option_type=&(option->ctr.type[i]);
3772 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3775 for (snum=0; snum<n_services; snum++)
3777 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3778 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3784 * Debugging information, don't delete.
3787 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3788 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3789 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3791 for (i=0; i<info->count; i++) {
3792 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3793 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3794 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3801 /*******************************************************************
3803 * fill a notify_info struct with info asked
3805 ********************************************************************/
3807 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3808 TALLOC_CTX *mem_ctx)
3811 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3814 SPOOL_NOTIFY_OPTION *option;
3815 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3817 print_queue_struct *queue=NULL;
3818 print_status_struct status;
3820 DEBUG(4,("printer_notify_info\n"));
3825 option=Printer->notify.option;
3831 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3832 sending a ffpcn() request first */
3837 get_printer_snum(p, hnd, &snum);
3839 for (i=0; i<option->count; i++) {
3840 option_type=&option->ctr.type[i];
3842 switch ( option_type->type ) {
3843 case PRINTER_NOTIFY_TYPE:
3844 if(construct_notify_printer_info(Printer, info, snum,
3850 case JOB_NOTIFY_TYPE: {
3851 NT_PRINTER_INFO_LEVEL *printer = NULL;
3853 count = print_queue_status(snum, &queue, &status);
3855 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3858 for (j=0; j<count; j++) {
3859 construct_notify_jobs_info(&queue[j], info,
3866 free_a_printer(&printer, 2);
3876 * Debugging information, don't delete.
3879 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3880 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3881 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3883 for (i=0; i<info->count; i++) {
3884 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3885 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3886 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3892 /********************************************************************
3894 ********************************************************************/
3896 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3898 POLICY_HND *handle = &q_u->handle;
3899 SPOOL_NOTIFY_INFO *info = &r_u->info;
3901 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3902 WERROR result = WERR_BADFID;
3904 /* we always have a NOTIFY_INFO struct */
3908 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3909 OUR_HANDLE(handle)));
3913 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3916 * We are now using the change value, and
3917 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3918 * I don't have a global notification system, I'm sending back all the
3919 * informations even when _NOTHING_ has changed.
3922 /* We need to keep track of the change value to send back in
3923 RRPCN replies otherwise our updates are ignored. */
3925 Printer->notify.fnpcn = True;
3927 if (Printer->notify.client_connected) {
3928 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3929 Printer->notify.change = q_u->change;
3932 /* just ignore the SPOOL_NOTIFY_OPTION */
3934 switch (Printer->printer_type) {
3935 case PRINTER_HANDLE_IS_PRINTSERVER:
3936 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3939 case PRINTER_HANDLE_IS_PRINTER:
3940 result = printer_notify_info(p, handle, info, p->mem_ctx);
3944 Printer->notify.fnpcn = False;
3950 /********************************************************************
3951 * construct_printer_info_0
3952 * fill a printer_info_0 struct
3953 ********************************************************************/
3955 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3959 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3960 counter_printer_0 *session_counter;
3961 uint32 global_counter;
3964 print_status_struct status;
3966 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3969 count = print_queue_length(snum, &status);
3971 /* check if we already have a counter for this printer */
3972 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3973 if (session_counter->snum == snum)
3977 /* it's the first time, add it to the list */
3978 if (session_counter==NULL) {
3979 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3980 free_a_printer(&ntprinter, 2);
3983 ZERO_STRUCTP(session_counter);
3984 session_counter->snum=snum;
3985 session_counter->counter=0;
3986 DLIST_ADD(counter_list, session_counter);
3990 session_counter->counter++;
3993 * the global_counter should be stored in a TDB as it's common to all the clients
3994 * and should be zeroed on samba startup
3996 global_counter=session_counter->counter;
3998 pstrcpy(chaine,ntprinter->info_2->printername);
4000 init_unistr(&printer->printername, chaine);
4002 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
4003 init_unistr(&printer->servername, chaine);
4005 printer->cjobs = count;
4006 printer->total_jobs = 0;
4007 printer->total_bytes = 0;
4009 setuptime = (time_t)ntprinter->info_2->setuptime;
4010 t=gmtime(&setuptime);
4012 printer->year = t->tm_year+1900;
4013 printer->month = t->tm_mon+1;
4014 printer->dayofweek = t->tm_wday;
4015 printer->day = t->tm_mday;
4016 printer->hour = t->tm_hour;
4017 printer->minute = t->tm_min;
4018 printer->second = t->tm_sec;
4019 printer->milliseconds = 0;
4021 printer->global_counter = global_counter;
4022 printer->total_pages = 0;
4024 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4025 printer->major_version = 0x0005; /* NT 5 */
4026 printer->build_version = 0x0893; /* build 2195 */
4028 printer->unknown7 = 0x1;
4029 printer->unknown8 = 0x0;
4030 printer->unknown9 = 0x0;
4031 printer->session_counter = session_counter->counter;
4032 printer->unknown11 = 0x0;
4033 printer->printer_errors = 0x0; /* number of print failure */
4034 printer->unknown13 = 0x0;
4035 printer->unknown14 = 0x1;
4036 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4037 printer->unknown16 = 0x0;
4038 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4039 printer->unknown18 = 0x0;
4040 printer->status = nt_printq_status(status.status);
4041 printer->unknown20 = 0x0;
4042 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4043 printer->unknown22 = 0x0;
4044 printer->unknown23 = 0x6; /* 6 ???*/
4045 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4046 printer->unknown25 = 0;
4047 printer->unknown26 = 0;
4048 printer->unknown27 = 0;
4049 printer->unknown28 = 0;
4050 printer->unknown29 = 0;
4052 free_a_printer(&ntprinter,2);
4056 /********************************************************************
4057 * construct_printer_info_1
4058 * fill a printer_info_1 struct
4059 ********************************************************************/
4060 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4064 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4066 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4069 printer->flags=flags;
4071 if (*ntprinter->info_2->comment == '\0') {
4072 init_unistr(&printer->comment, lp_comment(snum));
4073 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4074 ntprinter->info_2->drivername, lp_comment(snum));
4077 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4078 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4079 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4082 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4084 init_unistr(&printer->description, chaine);
4085 init_unistr(&printer->name, chaine2);
4087 free_a_printer(&ntprinter,2);
4092 /****************************************************************************
4093 Free a DEVMODE struct.
4094 ****************************************************************************/
4096 static void free_dev_mode(DEVICEMODE *dev)
4101 SAFE_FREE(dev->dev_private);
4106 /****************************************************************************
4107 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4108 should be valid upon entry
4109 ****************************************************************************/
4111 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4113 if ( !devmode || !ntdevmode )
4116 init_unistr(&devmode->devicename, ntdevmode->devicename);
4118 init_unistr(&devmode->formname, ntdevmode->formname);
4120 devmode->specversion = ntdevmode->specversion;
4121 devmode->driverversion = ntdevmode->driverversion;
4122 devmode->size = ntdevmode->size;
4123 devmode->driverextra = ntdevmode->driverextra;
4124 devmode->fields = ntdevmode->fields;
4126 devmode->orientation = ntdevmode->orientation;
4127 devmode->papersize = ntdevmode->papersize;
4128 devmode->paperlength = ntdevmode->paperlength;
4129 devmode->paperwidth = ntdevmode->paperwidth;
4130 devmode->scale = ntdevmode->scale;
4131 devmode->copies = ntdevmode->copies;
4132 devmode->defaultsource = ntdevmode->defaultsource;
4133 devmode->printquality = ntdevmode->printquality;
4134 devmode->color = ntdevmode->color;
4135 devmode->duplex = ntdevmode->duplex;
4136 devmode->yresolution = ntdevmode->yresolution;
4137 devmode->ttoption = ntdevmode->ttoption;
4138 devmode->collate = ntdevmode->collate;
4139 devmode->icmmethod = ntdevmode->icmmethod;
4140 devmode->icmintent = ntdevmode->icmintent;
4141 devmode->mediatype = ntdevmode->mediatype;
4142 devmode->dithertype = ntdevmode->dithertype;
4144 if (ntdevmode->nt_dev_private != NULL) {
4145 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4152 /****************************************************************************
4153 Create a DEVMODE struct. Returns malloced memory.
4154 ****************************************************************************/
4156 DEVICEMODE *construct_dev_mode(int snum)
4158 NT_PRINTER_INFO_LEVEL *printer = NULL;
4159 DEVICEMODE *devmode = NULL;
4161 DEBUG(7,("construct_dev_mode\n"));
4163 DEBUGADD(8,("getting printer characteristics\n"));
4165 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4168 if ( !printer->info_2->devmode ) {
4169 DEBUG(5, ("BONG! There was no device mode!\n"));
4173 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4174 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4178 ZERO_STRUCTP(devmode);
4180 DEBUGADD(8,("loading DEVICEMODE\n"));
4182 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4183 free_dev_mode( devmode );
4188 free_a_printer(&printer,2);
4193 /********************************************************************
4194 * construct_printer_info_2
4195 * fill a printer_info_2 struct
4196 ********************************************************************/
4198 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4201 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4203 print_status_struct status;
4205 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4208 count = print_queue_length(snum, &status);
4210 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4211 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4212 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4213 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4214 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4216 if (*ntprinter->info_2->comment == '\0')
4217 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4219 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4221 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4222 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4223 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4224 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4225 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4227 printer->attributes = ntprinter->info_2->attributes;
4229 printer->priority = ntprinter->info_2->priority; /* priority */
4230 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4231 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4232 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4233 printer->status = nt_printq_status(status.status); /* status */
4234 printer->cjobs = count; /* jobs */
4235 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4237 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4238 DEBUG(8, ("Returning NULL Devicemode!\n"));
4241 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4242 /* steal the printer info sec_desc structure. [badly done]. */
4243 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4244 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4245 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4246 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4249 printer->secdesc = NULL;
4252 free_a_printer(&ntprinter, 2);
4256 /********************************************************************
4257 * construct_printer_info_3
4258 * fill a printer_info_3 struct
4259 ********************************************************************/
4261 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4263 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4264 PRINTER_INFO_3 *printer = NULL;
4266 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4270 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4271 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4275 ZERO_STRUCTP(printer);
4277 printer->flags = 4; /* These are the components of the SD we are returning. */
4278 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4279 /* steal the printer info sec_desc structure. [badly done]. */
4280 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4284 * Set the flags for the components we are returning.
4287 if (printer->secdesc->owner_sid)
4288 printer->flags |= OWNER_SECURITY_INFORMATION;
4290 if (printer->secdesc->grp_sid)
4291 printer->flags |= GROUP_SECURITY_INFORMATION;
4293 if (printer->secdesc->dacl)
4294 printer->flags |= DACL_SECURITY_INFORMATION;
4296 if (printer->secdesc->sacl)
4297 printer->flags |= SACL_SECURITY_INFORMATION;
4300 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4301 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4302 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4305 free_a_printer(&ntprinter, 2);
4307 *pp_printer = printer;
4311 /********************************************************************
4312 * construct_printer_info_4
4313 * fill a printer_info_4 struct
4314 ********************************************************************/
4316 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4318 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4320 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4323 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4324 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4325 printer->attributes = ntprinter->info_2->attributes;
4327 free_a_printer(&ntprinter, 2);
4331 /********************************************************************
4332 * construct_printer_info_5
4333 * fill a printer_info_5 struct
4334 ********************************************************************/
4336 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4338 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4340 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4343 init_unistr(&printer->printername, ntprinter->info_2->printername);
4344 init_unistr(&printer->portname, ntprinter->info_2->portname);
4345 printer->attributes = ntprinter->info_2->attributes;
4347 /* these two are not used by NT+ according to MSDN */
4349 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4350 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4352 free_a_printer(&ntprinter, 2);
4357 /********************************************************************
4358 * construct_printer_info_7
4359 * fill a printer_info_7 struct
4360 ********************************************************************/
4362 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4364 char *guid_str = NULL;
4367 if (is_printer_published(print_hnd, snum, &guid)) {
4368 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4369 strupper_m(guid_str);
4370 init_unistr(&printer->guid, guid_str);
4371 printer->action = SPOOL_DS_PUBLISH;
4373 init_unistr(&printer->guid, "");
4374 printer->action = SPOOL_DS_UNPUBLISH;
4380 /********************************************************************
4381 Spoolss_enumprinters.
4382 ********************************************************************/
4384 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4388 int n_services=lp_numservices();
4389 PRINTER_INFO_1 *tp, *printers=NULL;
4390 PRINTER_INFO_1 current_prt;
4391 WERROR result = WERR_OK;
4393 DEBUG(4,("enum_all_printers_info_1\n"));
4395 for (snum=0; snum<n_services; snum++) {
4396 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4397 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4399 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4400 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4401 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4402 SAFE_FREE(printers);
4407 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4409 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4415 /* check the required size. */
4416 for (i=0; i<*returned; i++)
4417 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4419 if (*needed > offered) {
4420 result = WERR_INSUFFICIENT_BUFFER;
4424 if (!rpcbuf_alloc_size(buffer, *needed)) {
4425 result = WERR_NOMEM;
4429 /* fill the buffer with the structures */
4430 for (i=0; i<*returned; i++)
4431 smb_io_printer_info_1("", buffer, &printers[i], 0);
4436 SAFE_FREE(printers);
4438 if ( !W_ERROR_IS_OK(result) )
4444 /********************************************************************
4445 enum_all_printers_info_1_local.
4446 *********************************************************************/
4448 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4450 DEBUG(4,("enum_all_printers_info_1_local\n"));
4452 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4455 /********************************************************************
4456 enum_all_printers_info_1_name.
4457 *********************************************************************/
4459 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4463 DEBUG(4,("enum_all_printers_info_1_name\n"));
4465 if ((name[0] == '\\') && (name[1] == '\\'))
4468 if (is_myname_or_ipaddr(s)) {
4469 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4472 return WERR_INVALID_NAME;
4475 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4476 /********************************************************************
4477 enum_all_printers_info_1_remote.
4478 *********************************************************************/
4480 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4482 PRINTER_INFO_1 *printer;
4483 fstring printername;
4486 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4487 WERROR result = WERR_OK;
4489 /* JFM: currently it's more a place holder than anything else.
4490 * In the spooler world there is a notion of server registration.
4491 * the print servers are registered on the PDC (in the same domain)
4493 * We should have a TDB here. The registration is done thru an
4494 * undocumented RPC call.
4497 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4502 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4503 slprintf(desc, sizeof(desc)-1,"%s", name);
4504 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4506 init_unistr(&printer->description, desc);
4507 init_unistr(&printer->name, printername);
4508 init_unistr(&printer->comment, comment);
4509 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4511 /* check the required size. */
4512 *needed += spoolss_size_printer_info_1(printer);
4514 if (*needed > offered) {
4515 result = WERR_INSUFFICIENT_BUFFER;
4519 if (!rpcbuf_alloc_size(buffer, *needed)) {
4520 result = WERR_NOMEM;
4524 /* fill the buffer with the structures */
4525 smb_io_printer_info_1("", buffer, printer, 0);
4531 if ( !W_ERROR_IS_OK(result) )
4539 /********************************************************************
4540 enum_all_printers_info_1_network.
4541 *********************************************************************/
4543 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4547 DEBUG(4,("enum_all_printers_info_1_network\n"));
4549 /* If we respond to a enum_printers level 1 on our name with flags
4550 set to PRINTER_ENUM_REMOTE with a list of printers then these
4551 printers incorrectly appear in the APW browse list.
4552 Specifically the printers for the server appear at the workgroup
4553 level where all the other servers in the domain are
4554 listed. Windows responds to this call with a
4555 WERR_CAN_NOT_COMPLETE so we should do the same. */
4557 if (name[0] == '\\' && name[1] == '\\')
4560 if (is_myname_or_ipaddr(s))
4561 return WERR_CAN_NOT_COMPLETE;
4563 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4566 /********************************************************************
4567 * api_spoolss_enumprinters
4569 * called from api_spoolss_enumprinters (see this to understand)
4570 ********************************************************************/
4572 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4576 int n_services=lp_numservices();
4577 PRINTER_INFO_2 *tp, *printers=NULL;
4578 PRINTER_INFO_2 current_prt;
4579 WERROR result = WERR_OK;
4581 for (snum=0; snum<n_services; snum++) {
4582 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4583 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4585 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4586 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) == NULL) {
4587 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4588 SAFE_FREE(printers);
4593 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4594 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4600 /* check the required size. */
4601 for (i=0; i<*returned; i++)
4602 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4604 if (*needed > offered) {
4605 result = WERR_INSUFFICIENT_BUFFER;
4609 if (!rpcbuf_alloc_size(buffer, *needed)) {
4610 result = WERR_NOMEM;
4614 /* fill the buffer with the structures */
4615 for (i=0; i<*returned; i++)
4616 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4620 for (i=0; i<*returned; i++) {
4621 free_devmode(printers[i].devmode);
4623 SAFE_FREE(printers);
4625 if ( !W_ERROR_IS_OK(result) )
4631 /********************************************************************
4632 * handle enumeration of printers at level 1
4633 ********************************************************************/
4635 static WERROR enumprinters_level1( uint32 flags, fstring name,
4636 RPC_BUFFER *buffer, uint32 offered,
4637 uint32 *needed, uint32 *returned)
4639 /* Not all the flags are equals */
4641 if (flags & PRINTER_ENUM_LOCAL)
4642 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4644 if (flags & PRINTER_ENUM_NAME)
4645 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4647 #if 0 /* JERRY - disabled for now */
4648 if (flags & PRINTER_ENUM_REMOTE)
4649 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4652 if (flags & PRINTER_ENUM_NETWORK)
4653 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4655 return WERR_OK; /* NT4sp5 does that */
4658 /********************************************************************
4659 * handle enumeration of printers at level 2
4660 ********************************************************************/
4662 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4663 RPC_BUFFER *buffer, uint32 offered,
4664 uint32 *needed, uint32 *returned)
4666 char *s = servername;
4668 if (flags & PRINTER_ENUM_LOCAL) {
4669 return enum_all_printers_info_2(buffer, offered, needed, returned);
4672 if (flags & PRINTER_ENUM_NAME) {
4673 if ((servername[0] == '\\') && (servername[1] == '\\'))
4675 if (is_myname_or_ipaddr(s))
4676 return enum_all_printers_info_2(buffer, offered, needed, returned);
4678 return WERR_INVALID_NAME;
4681 if (flags & PRINTER_ENUM_REMOTE)
4682 return WERR_UNKNOWN_LEVEL;
4687 /********************************************************************
4688 * handle enumeration of printers at level 5
4689 ********************************************************************/
4691 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4692 RPC_BUFFER *buffer, uint32 offered,
4693 uint32 *needed, uint32 *returned)
4695 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4699 /********************************************************************
4700 * api_spoolss_enumprinters
4702 * called from api_spoolss_enumprinters (see this to understand)
4703 ********************************************************************/
4705 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4707 uint32 flags = q_u->flags;
4708 UNISTR2 *servername = &q_u->servername;
4709 uint32 level = q_u->level;
4710 RPC_BUFFER *buffer = NULL;
4711 uint32 offered = q_u->offered;
4712 uint32 *needed = &r_u->needed;
4713 uint32 *returned = &r_u->returned;
4717 /* that's an [in out] buffer */
4719 if ( q_u->buffer ) {
4720 rpcbuf_move(q_u->buffer, &r_u->buffer);
4721 buffer = r_u->buffer;
4724 DEBUG(4,("_spoolss_enumprinters\n"));
4731 * flags==PRINTER_ENUM_NAME
4732 * if name=="" then enumerates all printers
4733 * if name!="" then enumerate the printer
4734 * flags==PRINTER_ENUM_REMOTE
4735 * name is NULL, enumerate printers
4736 * Level 2: name!="" enumerates printers, name can't be NULL
4737 * Level 3: doesn't exist
4738 * Level 4: does a local registry lookup
4739 * Level 5: same as Level 2
4742 unistr2_to_ascii(name, servername, sizeof(name)-1);
4747 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4749 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4751 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4756 return WERR_UNKNOWN_LEVEL;
4759 /****************************************************************************
4760 ****************************************************************************/
4762 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4764 PRINTER_INFO_0 *printer=NULL;
4765 WERROR result = WERR_OK;
4767 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4770 construct_printer_info_0(print_hnd, printer, snum);
4772 /* check the required size. */
4773 *needed += spoolss_size_printer_info_0(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 smb_io_printer_info_0("", buffer, printer, 0);
4796 /****************************************************************************
4797 ****************************************************************************/
4799 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4801 PRINTER_INFO_1 *printer=NULL;
4802 WERROR result = WERR_OK;
4804 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4807 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4809 /* check the required size. */
4810 *needed += spoolss_size_printer_info_1(printer);
4812 if (*needed > offered) {
4813 result = WERR_INSUFFICIENT_BUFFER;
4817 if (!rpcbuf_alloc_size(buffer, *needed)) {
4818 result = WERR_NOMEM;
4822 /* fill the buffer with the structures */
4823 smb_io_printer_info_1("", buffer, printer, 0);
4832 /****************************************************************************
4833 ****************************************************************************/
4835 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4837 PRINTER_INFO_2 *printer=NULL;
4838 WERROR result = WERR_OK;
4840 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4843 construct_printer_info_2(print_hnd, printer, snum);
4845 /* check the required size. */
4846 *needed += spoolss_size_printer_info_2(printer);
4848 if (*needed > offered) {
4849 result = WERR_INSUFFICIENT_BUFFER;
4853 if (!rpcbuf_alloc_size(buffer, *needed)) {
4854 result = WERR_NOMEM;
4858 /* fill the buffer with the structures */
4859 if (!smb_io_printer_info_2("", buffer, printer, 0))
4860 result = WERR_NOMEM;
4864 free_printer_info_2(printer);
4869 /****************************************************************************
4870 ****************************************************************************/
4872 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4874 PRINTER_INFO_3 *printer=NULL;
4875 WERROR result = WERR_OK;
4877 if (!construct_printer_info_3(print_hnd, &printer, snum))
4880 /* check the required size. */
4881 *needed += spoolss_size_printer_info_3(printer);
4883 if (*needed > offered) {
4884 result = WERR_INSUFFICIENT_BUFFER;
4888 if (!rpcbuf_alloc_size(buffer, *needed)) {
4889 result = WERR_NOMEM;
4893 /* fill the buffer with the structures */
4894 smb_io_printer_info_3("", buffer, printer, 0);
4898 free_printer_info_3(printer);
4903 /****************************************************************************
4904 ****************************************************************************/
4906 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4908 PRINTER_INFO_4 *printer=NULL;
4909 WERROR result = WERR_OK;
4911 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4914 if (!construct_printer_info_4(print_hnd, printer, snum))
4917 /* check the required size. */
4918 *needed += spoolss_size_printer_info_4(printer);
4920 if (*needed > offered) {
4921 result = WERR_INSUFFICIENT_BUFFER;
4925 if (!rpcbuf_alloc_size(buffer, *needed)) {
4926 result = WERR_NOMEM;
4930 /* fill the buffer with the structures */
4931 smb_io_printer_info_4("", buffer, printer, 0);
4935 free_printer_info_4(printer);
4940 /****************************************************************************
4941 ****************************************************************************/
4943 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4945 PRINTER_INFO_5 *printer=NULL;
4946 WERROR result = WERR_OK;
4948 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4951 if (!construct_printer_info_5(print_hnd, printer, snum))
4954 /* check the required size. */
4955 *needed += spoolss_size_printer_info_5(printer);
4957 if (*needed > offered) {
4958 result = WERR_INSUFFICIENT_BUFFER;
4962 if (!rpcbuf_alloc_size(buffer, *needed)) {
4963 result = WERR_NOMEM;
4967 /* fill the buffer with the structures */
4968 smb_io_printer_info_5("", buffer, printer, 0);
4972 free_printer_info_5(printer);
4977 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4979 PRINTER_INFO_7 *printer=NULL;
4980 WERROR result = WERR_OK;
4982 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4985 if (!construct_printer_info_7(print_hnd, printer, snum))
4988 /* check the required size. */
4989 *needed += spoolss_size_printer_info_7(printer);
4991 if (*needed > offered) {
4992 result = WERR_INSUFFICIENT_BUFFER;
4996 if (!rpcbuf_alloc_size(buffer, *needed)) {
4997 result = WERR_NOMEM;
5002 /* fill the buffer with the structures */
5003 smb_io_printer_info_7("", buffer, printer, 0);
5007 free_printer_info_7(printer);
5012 /****************************************************************************
5013 ****************************************************************************/
5015 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5017 POLICY_HND *handle = &q_u->handle;
5018 uint32 level = q_u->level;
5019 RPC_BUFFER *buffer = NULL;
5020 uint32 offered = q_u->offered;
5021 uint32 *needed = &r_u->needed;
5022 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5026 /* that's an [in out] buffer */
5028 if ( q_u->buffer ) {
5029 rpcbuf_move(q_u->buffer, &r_u->buffer);
5030 buffer = r_u->buffer;
5035 if (!get_printer_snum(p, handle, &snum))
5040 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5042 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5044 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5046 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5048 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5050 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5052 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5054 return WERR_UNKNOWN_LEVEL;
5057 /********************************************************************
5058 * fill a DRIVER_INFO_1 struct
5059 ********************************************************************/
5061 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5063 init_unistr( &info->name, driver.info_3->name);
5066 /********************************************************************
5067 * construct_printer_driver_info_1
5068 ********************************************************************/
5070 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5072 NT_PRINTER_INFO_LEVEL *printer = NULL;
5073 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5075 ZERO_STRUCT(driver);
5077 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5078 return WERR_INVALID_PRINTER_NAME;
5080 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5081 return WERR_UNKNOWN_PRINTER_DRIVER;
5083 fill_printer_driver_info_1(info, driver, servername, architecture);
5085 free_a_printer(&printer,2);
5090 /********************************************************************
5091 * construct_printer_driver_info_2
5092 * fill a printer_info_2 struct
5093 ********************************************************************/
5095 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5099 info->version=driver.info_3->cversion;
5101 init_unistr( &info->name, driver.info_3->name );
5102 init_unistr( &info->architecture, driver.info_3->environment );
5105 if (strlen(driver.info_3->driverpath)) {
5106 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5107 init_unistr( &info->driverpath, temp );
5109 init_unistr( &info->driverpath, "" );
5111 if (strlen(driver.info_3->datafile)) {
5112 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5113 init_unistr( &info->datafile, temp );
5115 init_unistr( &info->datafile, "" );
5117 if (strlen(driver.info_3->configfile)) {
5118 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5119 init_unistr( &info->configfile, temp );
5121 init_unistr( &info->configfile, "" );
5124 /********************************************************************
5125 * construct_printer_driver_info_2
5126 * fill a printer_info_2 struct
5127 ********************************************************************/
5129 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5131 NT_PRINTER_INFO_LEVEL *printer = NULL;
5132 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5134 ZERO_STRUCT(printer);
5135 ZERO_STRUCT(driver);
5137 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5138 return WERR_INVALID_PRINTER_NAME;
5140 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5141 return WERR_UNKNOWN_PRINTER_DRIVER;
5143 fill_printer_driver_info_2(info, driver, servername);
5145 free_a_printer(&printer,2);
5150 /********************************************************************
5151 * copy a strings array and convert to UNICODE
5153 * convert an array of ascii string to a UNICODE string
5154 ********************************************************************/
5156 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5164 DEBUG(6,("init_unistr_array\n"));
5175 v = ""; /* hack to handle null lists */
5178 /* hack to allow this to be used in places other than when generating
5179 the list of dependent files */
5182 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5186 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5188 /* add one extra unit16 for the second terminating NULL */
5190 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5191 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5199 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5204 /* special case for ""; we need to add both NULL's here */
5206 (*uni_array)[j++]=0x0000;
5207 (*uni_array)[j]=0x0000;
5210 DEBUGADD(6,("last one:done\n"));
5212 /* return size of array in uint16's */
5217 /********************************************************************
5218 * construct_printer_info_3
5219 * fill a printer_info_3 struct
5220 ********************************************************************/
5222 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5228 info->version=driver.info_3->cversion;
5230 init_unistr( &info->name, driver.info_3->name );
5231 init_unistr( &info->architecture, driver.info_3->environment );
5233 if (strlen(driver.info_3->driverpath)) {
5234 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5235 init_unistr( &info->driverpath, temp );
5237 init_unistr( &info->driverpath, "" );
5239 if (strlen(driver.info_3->datafile)) {
5240 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5241 init_unistr( &info->datafile, temp );
5243 init_unistr( &info->datafile, "" );
5245 if (strlen(driver.info_3->configfile)) {
5246 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5247 init_unistr( &info->configfile, temp );
5249 init_unistr( &info->configfile, "" );
5251 if (strlen(driver.info_3->helpfile)) {
5252 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5253 init_unistr( &info->helpfile, temp );
5255 init_unistr( &info->helpfile, "" );
5257 init_unistr( &info->monitorname, driver.info_3->monitorname );
5258 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5260 info->dependentfiles=NULL;
5261 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5264 /********************************************************************
5265 * construct_printer_info_3
5266 * fill a printer_info_3 struct
5267 ********************************************************************/
5269 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5271 NT_PRINTER_INFO_LEVEL *printer = NULL;
5272 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5274 ZERO_STRUCT(driver);
5276 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5277 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5278 if (!W_ERROR_IS_OK(status))
5279 return WERR_INVALID_PRINTER_NAME;
5281 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5282 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5287 * I put this code in during testing. Helpful when commenting out the
5288 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5289 * as win2k always queries the driver using an infor level of 6.
5290 * I've left it in (but ifdef'd out) because I'll probably
5291 * use it in experimentation again in the future. --jerry 22/01/2002
5294 if (!W_ERROR_IS_OK(status)) {
5296 * Is this a W2k client ?
5299 /* Yes - try again with a WinNT driver. */
5301 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5302 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5306 if (!W_ERROR_IS_OK(status)) {
5307 free_a_printer(&printer,2);
5308 return WERR_UNKNOWN_PRINTER_DRIVER;
5316 fill_printer_driver_info_3(info, driver, servername);
5318 free_a_printer(&printer,2);
5323 /********************************************************************
5324 * construct_printer_info_6
5325 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5326 ********************************************************************/
5328 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5334 memset(&nullstr, '\0', sizeof(fstring));
5336 info->version=driver.info_3->cversion;
5338 init_unistr( &info->name, driver.info_3->name );
5339 init_unistr( &info->architecture, driver.info_3->environment );
5341 if (strlen(driver.info_3->driverpath)) {
5342 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5343 init_unistr( &info->driverpath, temp );
5345 init_unistr( &info->driverpath, "" );
5347 if (strlen(driver.info_3->datafile)) {
5348 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5349 init_unistr( &info->datafile, temp );
5351 init_unistr( &info->datafile, "" );
5353 if (strlen(driver.info_3->configfile)) {
5354 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5355 init_unistr( &info->configfile, temp );
5357 init_unistr( &info->configfile, "" );
5359 if (strlen(driver.info_3->helpfile)) {
5360 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5361 init_unistr( &info->helpfile, temp );
5363 init_unistr( &info->helpfile, "" );
5365 init_unistr( &info->monitorname, driver.info_3->monitorname );
5366 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5368 info->dependentfiles = NULL;
5369 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5371 info->previousdrivernames=NULL;
5372 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5374 info->driver_date.low=0;
5375 info->driver_date.high=0;
5378 info->driver_version_low=0;
5379 info->driver_version_high=0;
5381 init_unistr( &info->mfgname, "");
5382 init_unistr( &info->oem_url, "");
5383 init_unistr( &info->hardware_id, "");
5384 init_unistr( &info->provider, "");
5387 /********************************************************************
5388 * construct_printer_info_6
5389 * fill a printer_info_6 struct
5390 ********************************************************************/
5392 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5393 fstring servername, fstring architecture, uint32 version)
5395 NT_PRINTER_INFO_LEVEL *printer = NULL;
5396 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5399 ZERO_STRUCT(driver);
5401 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5403 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5405 if (!W_ERROR_IS_OK(status))
5406 return WERR_INVALID_PRINTER_NAME;
5408 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5410 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5412 if (!W_ERROR_IS_OK(status))
5415 * Is this a W2k client ?
5419 free_a_printer(&printer,2);
5420 return WERR_UNKNOWN_PRINTER_DRIVER;
5423 /* Yes - try again with a WinNT driver. */
5425 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5426 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5427 if (!W_ERROR_IS_OK(status)) {
5428 free_a_printer(&printer,2);
5429 return WERR_UNKNOWN_PRINTER_DRIVER;
5433 fill_printer_driver_info_6(info, driver, servername);
5435 free_a_printer(&printer,2);
5436 free_a_printer_driver(driver, 3);
5441 /****************************************************************************
5442 ****************************************************************************/
5444 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5446 SAFE_FREE(info->dependentfiles);
5449 /****************************************************************************
5450 ****************************************************************************/
5452 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5454 SAFE_FREE(info->dependentfiles);
5457 /****************************************************************************
5458 ****************************************************************************/
5460 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5462 DRIVER_INFO_1 *info=NULL;
5465 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5468 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5469 if (!W_ERROR_IS_OK(result))
5472 /* check the required size. */
5473 *needed += spoolss_size_printer_driver_info_1(info);
5475 if (*needed > offered) {
5476 result = WERR_INSUFFICIENT_BUFFER;
5480 if (!rpcbuf_alloc_size(buffer, *needed)) {
5481 result = WERR_NOMEM;
5485 /* fill the buffer with the structures */
5486 smb_io_printer_driver_info_1("", buffer, info, 0);
5495 /****************************************************************************
5496 ****************************************************************************/
5498 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5500 DRIVER_INFO_2 *info=NULL;
5503 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5506 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5507 if (!W_ERROR_IS_OK(result))
5510 /* check the required size. */
5511 *needed += spoolss_size_printer_driver_info_2(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_2("", buffer, info, 0);
5533 /****************************************************************************
5534 ****************************************************************************/
5536 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5543 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5544 if (!W_ERROR_IS_OK(result))
5547 /* check the required size. */
5548 *needed += spoolss_size_printer_driver_info_3(&info);
5550 if (*needed > offered) {
5551 result = WERR_INSUFFICIENT_BUFFER;
5555 if (!rpcbuf_alloc_size(buffer, *needed)) {
5556 result = WERR_NOMEM;
5560 /* fill the buffer with the structures */
5561 smb_io_printer_driver_info_3("", buffer, &info, 0);
5564 free_printer_driver_info_3(&info);
5569 /****************************************************************************
5570 ****************************************************************************/
5572 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5579 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5580 if (!W_ERROR_IS_OK(result))
5583 /* check the required size. */
5584 *needed += spoolss_size_printer_driver_info_6(&info);
5586 if (*needed > offered) {
5587 result = WERR_INSUFFICIENT_BUFFER;
5591 if (!rpcbuf_alloc_size(buffer, *needed)) {
5592 result = WERR_NOMEM;
5596 /* fill the buffer with the structures */
5597 smb_io_printer_driver_info_6("", buffer, &info, 0);
5600 free_printer_driver_info_6(&info);
5605 /****************************************************************************
5606 ****************************************************************************/
5608 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5610 POLICY_HND *handle = &q_u->handle;
5611 UNISTR2 *uni_arch = &q_u->architecture;
5612 uint32 level = q_u->level;
5613 uint32 clientmajorversion = q_u->clientmajorversion;
5614 RPC_BUFFER *buffer = NULL;
5615 uint32 offered = q_u->offered;
5616 uint32 *needed = &r_u->needed;
5617 uint32 *servermajorversion = &r_u->servermajorversion;
5618 uint32 *serverminorversion = &r_u->serverminorversion;
5619 Printer_entry *printer;
5622 fstring architecture;
5625 /* that's an [in out] buffer */
5627 if ( q_u->buffer ) {
5628 rpcbuf_move(q_u->buffer, &r_u->buffer);
5629 buffer = r_u->buffer;
5632 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5634 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5635 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5636 return WERR_INVALID_PRINTER_NAME;
5640 *servermajorversion = 0;
5641 *serverminorversion = 0;
5643 fstrcpy(servername, get_server_name( printer ));
5644 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5646 if (!get_printer_snum(p, handle, &snum))
5651 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5653 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5655 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5657 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5660 /* apparently this call is the equivalent of
5661 EnumPrinterDataEx() for the DsDriver key */
5666 return WERR_UNKNOWN_LEVEL;
5669 /****************************************************************************
5670 ****************************************************************************/
5672 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5674 POLICY_HND *handle = &q_u->handle;
5676 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5679 DEBUG(3,("Error in startpageprinter printer handle\n"));
5683 Printer->page_started=True;
5687 /****************************************************************************
5688 ****************************************************************************/
5690 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5692 POLICY_HND *handle = &q_u->handle;
5695 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5698 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5702 if (!get_printer_snum(p, handle, &snum))
5705 Printer->page_started=False;
5706 print_job_endpage(snum, Printer->jobid);
5711 /********************************************************************
5712 * api_spoolss_getprinter
5713 * called from the spoolss dispatcher
5715 ********************************************************************/
5717 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5719 POLICY_HND *handle = &q_u->handle;
5720 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5721 uint32 *jobid = &r_u->jobid;
5723 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5727 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5728 struct current_user user;
5731 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5735 get_current_user(&user, p);
5738 * a nice thing with NT is it doesn't listen to what you tell it.
5739 * when asked to send _only_ RAW datas, it tries to send datas
5742 * So I add checks like in NT Server ...
5745 if (info_1->p_datatype != 0) {
5746 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5747 if (strcmp(datatype, "RAW") != 0) {
5749 return WERR_INVALID_DATATYPE;
5753 /* get the share number of the printer */
5754 if (!get_printer_snum(p, handle, &snum)) {
5758 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5760 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5762 /* An error occured in print_job_start() so return an appropriate
5765 if (Printer->jobid == -1) {
5766 return map_werror_from_unix(errno);
5769 Printer->document_started=True;
5770 (*jobid) = Printer->jobid;
5775 /********************************************************************
5776 * api_spoolss_getprinter
5777 * called from the spoolss dispatcher
5779 ********************************************************************/
5781 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5783 POLICY_HND *handle = &q_u->handle;
5785 return _spoolss_enddocprinter_internal(p, handle);
5788 /****************************************************************************
5789 ****************************************************************************/
5791 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5793 POLICY_HND *handle = &q_u->handle;
5794 uint32 buffer_size = q_u->buffer_size;
5795 uint8 *buffer = q_u->buffer;
5796 uint32 *buffer_written = &q_u->buffer_size2;
5798 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5801 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5802 r_u->buffer_written = q_u->buffer_size2;
5806 if (!get_printer_snum(p, handle, &snum))
5809 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5810 (SMB_OFF_T)-1, (size_t)buffer_size);
5811 if (*buffer_written == (uint32)-1) {
5812 r_u->buffer_written = 0;
5813 if (errno == ENOSPC)
5814 return WERR_NO_SPOOL_SPACE;
5816 return WERR_ACCESS_DENIED;
5819 r_u->buffer_written = q_u->buffer_size2;
5824 /********************************************************************
5825 * api_spoolss_getprinter
5826 * called from the spoolss dispatcher
5828 ********************************************************************/
5830 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5833 struct current_user user;
5835 WERROR errcode = WERR_BADFUNC;
5836 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5838 get_current_user(&user, p);
5841 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5845 if (!get_printer_snum(p, handle, &snum))
5849 case PRINTER_CONTROL_PAUSE:
5850 if (print_queue_pause(&user, snum, &errcode)) {
5854 case PRINTER_CONTROL_RESUME:
5855 case PRINTER_CONTROL_UNPAUSE:
5856 if (print_queue_resume(&user, snum, &errcode)) {
5860 case PRINTER_CONTROL_PURGE:
5861 if (print_queue_purge(&user, snum, &errcode)) {
5866 return WERR_UNKNOWN_LEVEL;
5872 /********************************************************************
5873 * api_spoolss_abortprinter
5874 * From MSDN: "Deletes printer's spool file if printer is configured
5876 ********************************************************************/
5878 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5880 POLICY_HND *handle = &q_u->handle;
5881 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5883 struct current_user user;
5884 WERROR errcode = WERR_OK;
5887 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5891 if (!get_printer_snum(p, handle, &snum))
5894 get_current_user( &user, p );
5896 print_job_delete( &user, snum, Printer->jobid, &errcode );
5901 /********************************************************************
5902 * called by spoolss_api_setprinter
5903 * when updating a printer description
5904 ********************************************************************/
5906 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5907 const SPOOL_PRINTER_INFO_LEVEL *info,
5908 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5910 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5914 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5916 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5917 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5918 OUR_HANDLE(handle)));
5920 result = WERR_BADFID;
5924 /* Check the user has permissions to change the security
5925 descriptor. By experimentation with two NT machines, the user
5926 requires Full Access to the printer to change security
5929 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5930 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5931 result = WERR_ACCESS_DENIED;
5935 /* NT seems to like setting the security descriptor even though
5936 nothing may have actually changed. */
5938 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5940 if (DEBUGLEVEL >= 10) {
5944 the_acl = old_secdesc_ctr->sec->dacl;
5945 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5946 PRINTERNAME(snum), the_acl->num_aces));
5948 for (i = 0; i < the_acl->num_aces; i++) {
5951 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5953 DEBUG(10, ("%s 0x%08x\n", sid_str,
5954 the_acl->ace[i].info.mask));
5957 the_acl = secdesc_ctr->sec->dacl;
5960 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5961 PRINTERNAME(snum), the_acl->num_aces));
5963 for (i = 0; i < the_acl->num_aces; i++) {
5966 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5968 DEBUG(10, ("%s 0x%08x\n", sid_str,
5969 the_acl->ace[i].info.mask));
5972 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5976 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5978 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5983 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5990 /********************************************************************
5991 Canonicalize printer info from a client
5993 ATTN: It does not matter what we set the servername to hear
5994 since we do the necessary work in get_a_printer() to set it to
5995 the correct value based on what the client sent in the
5996 _spoolss_open_printer_ex().
5997 ********************************************************************/
5999 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6001 fstring printername;
6004 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6005 "portname=%s drivername=%s comment=%s location=%s\n",
6006 info->servername, info->printername, info->sharename,
6007 info->portname, info->drivername, info->comment, info->location));
6009 /* we force some elements to "correct" values */
6010 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6011 fstrcpy(info->sharename, lp_servicename(snum));
6013 /* check to see if we allow printername != sharename */
6015 if ( lp_force_printername(snum) ) {
6016 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6017 global_myname(), info->sharename );
6020 /* make sure printername is in \\server\printername format */
6022 fstrcpy( printername, info->printername );
6024 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6025 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6029 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6030 global_myname(), p );
6033 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6034 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6041 /****************************************************************************
6042 ****************************************************************************/
6044 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6046 char *cmd = lp_addprinter_cmd();
6052 fstring remote_machine = "%m";
6053 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6054 BOOL is_print_op = False;
6056 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6058 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6059 cmd, printer->info_2->printername, printer->info_2->sharename,
6060 printer->info_2->portname, printer->info_2->drivername,
6061 printer->info_2->location, printer->info_2->comment, remote_machine);
6064 is_print_op = user_has_privileges( token, &se_printop );
6066 DEBUG(10,("Running [%s]\n", command));
6068 /********* BEGIN SePrintOperatorPrivilege **********/
6073 if ( (ret = smbrun(command, &fd)) == 0 ) {
6074 /* Tell everyone we updated smb.conf. */
6075 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6081 /********* END SePrintOperatorPrivilege **********/
6083 DEBUGADD(10,("returned [%d]\n", ret));
6091 /* reload our services immediately */
6092 reload_services( False );
6095 /* Get lines and convert them back to dos-codepage */
6096 qlines = fd_lines_load(fd, &numlines);
6097 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6100 /* Set the portname to what the script says the portname should be. */
6101 /* but don't require anything to be return from the script exit a good error code */
6104 /* Set the portname to what the script says the portname should be. */
6105 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6106 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6109 file_lines_free(qlines);
6113 /********************************************************************
6114 * Called by spoolss_api_setprinter
6115 * when updating a printer description.
6116 ********************************************************************/
6118 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6119 const SPOOL_PRINTER_INFO_LEVEL *info,
6120 DEVICEMODE *devmode)
6123 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6124 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6129 DEBUG(8,("update_printer\n"));
6134 result = WERR_BADFID;
6138 if (!get_printer_snum(p, handle, &snum)) {
6139 result = WERR_BADFID;
6143 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6144 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6145 result = WERR_BADFID;
6149 DEBUGADD(8,("Converting info_2 struct\n"));
6152 * convert_printer_info converts the incoming
6153 * info from the client and overwrites the info
6154 * just read from the tdb in the pointer 'printer'.
6157 if (!convert_printer_info(info, printer, level)) {
6158 result = WERR_NOMEM;
6163 /* we have a valid devmode
6164 convert it and link it*/
6166 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6167 if (!convert_devicemode(printer->info_2->printername, devmode,
6168 &printer->info_2->devmode)) {
6169 result = WERR_NOMEM;
6174 /* Do sanity check on the requested changes for Samba */
6176 if (!check_printer_ok(printer->info_2, snum)) {
6177 result = WERR_INVALID_PARAM;
6181 /* FIXME!!! If the driver has changed we really should verify that
6182 it is installed before doing much else --jerry */
6184 /* Check calling user has permission to update printer description */
6186 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6187 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6188 result = WERR_ACCESS_DENIED;
6192 /* Call addprinter hook */
6193 /* Check changes to see if this is really needed */
6195 if ( *lp_addprinter_cmd()
6196 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6197 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6198 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6199 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6201 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6202 result = WERR_ACCESS_DENIED;
6207 * make sure we actually reload the services after
6208 * this as smb.conf could have a new section in it
6209 * .... shouldn't .... but could
6211 reload_services(False);
6215 * When a *new* driver is bound to a printer, the drivername is used to
6216 * lookup previously saved driver initialization info, which is then
6217 * bound to the printer, simulating what happens in the Windows arch.
6219 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6221 if (!set_driver_init(printer, 2))
6223 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6224 printer->info_2->drivername));
6227 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6228 printer->info_2->drivername));
6230 notify_printer_driver(snum, printer->info_2->drivername);
6234 * flag which changes actually occured. This is a small subset of
6235 * all the possible changes. We also have to update things in the
6239 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6240 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6241 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6242 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6244 notify_printer_comment(snum, printer->info_2->comment);
6247 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6248 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6249 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6250 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6252 notify_printer_sharename(snum, printer->info_2->sharename);
6255 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6258 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6261 pname = printer->info_2->printername;
6264 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6265 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6266 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6268 notify_printer_printername( snum, pname );
6271 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6272 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6273 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6274 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6276 notify_printer_port(snum, printer->info_2->portname);
6279 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6280 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6281 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6282 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6284 notify_printer_location(snum, printer->info_2->location);
6287 /* here we need to update some more DsSpooler keys */
6288 /* uNCName, serverName, shortServerName */
6290 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6291 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6292 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6293 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6294 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6296 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6297 global_myname(), printer->info_2->sharename );
6298 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6299 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6300 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6302 /* Update printer info */
6303 result = mod_a_printer(printer, 2);
6306 free_a_printer(&printer, 2);
6307 free_a_printer(&old_printer, 2);
6313 /****************************************************************************
6314 ****************************************************************************/
6315 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6316 const SPOOL_PRINTER_INFO_LEVEL *info)
6319 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6321 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6323 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6328 if (!get_printer_snum(p, handle, &snum))
6331 nt_printer_publish(Printer, snum, info7->action);
6335 return WERR_UNKNOWN_LEVEL;
6338 /****************************************************************************
6339 ****************************************************************************/
6341 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6343 POLICY_HND *handle = &q_u->handle;
6344 uint32 level = q_u->level;
6345 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6346 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6347 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6348 uint32 command = q_u->command;
6351 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6354 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6358 /* check the level */
6361 return control_printer(handle, command, p);
6363 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6364 if (!W_ERROR_IS_OK(result))
6367 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6370 return update_printer_sec(handle, level, info, p,
6373 return publish_or_unpublish_printer(p, handle, info);
6375 return WERR_UNKNOWN_LEVEL;
6379 /****************************************************************************
6380 ****************************************************************************/
6382 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6384 POLICY_HND *handle = &q_u->handle;
6385 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6388 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6392 if (Printer->notify.client_connected==True) {
6395 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6397 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6398 !get_printer_snum(p, handle, &snum) )
6401 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6404 Printer->notify.flags=0;
6405 Printer->notify.options=0;
6406 Printer->notify.localmachine[0]='\0';
6407 Printer->notify.printerlocal=0;
6408 if (Printer->notify.option)
6409 free_spool_notify_option(&Printer->notify.option);
6410 Printer->notify.client_connected=False;
6415 /****************************************************************************
6416 ****************************************************************************/
6418 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6420 /* that's an [in out] buffer */
6423 rpcbuf_move(q_u->buffer, &r_u->buffer);
6426 return WERR_INVALID_PARAM; /* this is what a NT server
6427 returns for AddJob. AddJob
6428 must fail on non-local
6432 /****************************************************************************
6433 ****************************************************************************/
6435 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6436 int position, int snum,
6437 NT_PRINTER_INFO_LEVEL *ntprinter)
6441 t=gmtime(&queue->time);
6443 job_info->jobid=queue->job;
6444 init_unistr(&job_info->printername, lp_servicename(snum));
6445 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6446 init_unistr(&job_info->username, queue->fs_user);
6447 init_unistr(&job_info->document, queue->fs_file);
6448 init_unistr(&job_info->datatype, "RAW");
6449 init_unistr(&job_info->text_status, "");
6450 job_info->status=nt_printj_status(queue->status);
6451 job_info->priority=queue->priority;
6452 job_info->position=position;
6453 job_info->totalpages=queue->page_count;
6454 job_info->pagesprinted=0;
6456 make_systemtime(&job_info->submitted, t);
6459 /****************************************************************************
6460 ****************************************************************************/
6462 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6463 int position, int snum,
6464 NT_PRINTER_INFO_LEVEL *ntprinter,
6465 DEVICEMODE *devmode)
6469 t=gmtime(&queue->time);
6471 job_info->jobid=queue->job;
6473 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6475 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6476 init_unistr(&job_info->username, queue->fs_user);
6477 init_unistr(&job_info->document, queue->fs_file);
6478 init_unistr(&job_info->notifyname, queue->fs_user);
6479 init_unistr(&job_info->datatype, "RAW");
6480 init_unistr(&job_info->printprocessor, "winprint");
6481 init_unistr(&job_info->parameters, "");
6482 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6483 init_unistr(&job_info->text_status, "");
6485 /* and here the security descriptor */
6487 job_info->status=nt_printj_status(queue->status);
6488 job_info->priority=queue->priority;
6489 job_info->position=position;
6490 job_info->starttime=0;
6491 job_info->untiltime=0;
6492 job_info->totalpages=queue->page_count;
6493 job_info->size=queue->size;
6494 make_systemtime(&(job_info->submitted), t);
6495 job_info->timeelapsed=0;
6496 job_info->pagesprinted=0;
6498 job_info->devmode = devmode;
6503 /****************************************************************************
6504 Enumjobs at level 1.
6505 ****************************************************************************/
6507 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6508 NT_PRINTER_INFO_LEVEL *ntprinter,
6509 RPC_BUFFER *buffer, uint32 offered,
6510 uint32 *needed, uint32 *returned)
6514 WERROR result = WERR_OK;
6516 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6523 for (i=0; i<*returned; i++)
6524 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6528 /* check the required size. */
6529 for (i=0; i<*returned; i++)
6530 (*needed) += spoolss_size_job_info_1(&info[i]);
6532 if (*needed > offered) {
6533 result = WERR_INSUFFICIENT_BUFFER;
6537 if (!rpcbuf_alloc_size(buffer, *needed)) {
6538 result = WERR_NOMEM;
6542 /* fill the buffer with the structures */
6543 for (i=0; i<*returned; i++)
6544 smb_io_job_info_1("", buffer, &info[i], 0);
6550 if ( !W_ERROR_IS_OK(result) )
6556 /****************************************************************************
6557 Enumjobs at level 2.
6558 ****************************************************************************/
6560 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6561 NT_PRINTER_INFO_LEVEL *ntprinter,
6562 RPC_BUFFER *buffer, uint32 offered,
6563 uint32 *needed, uint32 *returned)
6565 JOB_INFO_2 *info = NULL;
6567 WERROR result = WERR_OK;
6568 DEVICEMODE *devmode = NULL;
6570 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6575 /* this should not be a failure condition if the devmode is NULL */
6577 devmode = construct_dev_mode(snum);
6579 for (i=0; i<*returned; i++)
6580 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6582 free_a_printer(&ntprinter, 2);
6585 /* check the required size. */
6586 for (i=0; i<*returned; i++)
6587 (*needed) += spoolss_size_job_info_2(&info[i]);
6589 if (*needed > offered) {
6590 result = WERR_INSUFFICIENT_BUFFER;
6594 if (!rpcbuf_alloc_size(buffer, *needed)) {
6595 result = WERR_NOMEM;
6599 /* fill the buffer with the structures */
6600 for (i=0; i<*returned; i++)
6601 smb_io_job_info_2("", buffer, &info[i], 0);
6604 free_devmode(devmode);
6607 if ( !W_ERROR_IS_OK(result) )
6614 /****************************************************************************
6616 ****************************************************************************/
6618 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6620 POLICY_HND *handle = &q_u->handle;
6621 uint32 level = q_u->level;
6622 RPC_BUFFER *buffer = NULL;
6623 uint32 offered = q_u->offered;
6624 uint32 *needed = &r_u->needed;
6625 uint32 *returned = &r_u->returned;
6627 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6629 print_status_struct prt_status;
6630 print_queue_struct *queue=NULL;
6632 /* that's an [in out] buffer */
6634 if ( q_u->buffer ) {
6635 rpcbuf_move(q_u->buffer, &r_u->buffer);
6636 buffer = r_u->buffer;
6639 DEBUG(4,("_spoolss_enumjobs\n"));
6644 /* lookup the printer snum and tdb entry */
6646 if (!get_printer_snum(p, handle, &snum))
6649 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6650 if ( !W_ERROR_IS_OK(wret) )
6653 *returned = print_queue_status(snum, &queue, &prt_status);
6654 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6656 if (*returned == 0) {
6663 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6666 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6671 wret = WERR_UNKNOWN_LEVEL;
6674 free_a_printer( &ntprinter, 2 );
6678 /****************************************************************************
6679 ****************************************************************************/
6681 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6686 /****************************************************************************
6687 ****************************************************************************/
6689 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6691 POLICY_HND *handle = &q_u->handle;
6692 uint32 jobid = q_u->jobid;
6693 uint32 command = q_u->command;
6695 struct current_user user;
6697 WERROR errcode = WERR_BADFUNC;
6699 if (!get_printer_snum(p, handle, &snum)) {
6703 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6704 return WERR_INVALID_PRINTER_NAME;
6707 get_current_user(&user, p);
6710 case JOB_CONTROL_CANCEL:
6711 case JOB_CONTROL_DELETE:
6712 if (print_job_delete(&user, snum, jobid, &errcode)) {
6716 case JOB_CONTROL_PAUSE:
6717 if (print_job_pause(&user, snum, jobid, &errcode)) {
6721 case JOB_CONTROL_RESTART:
6722 case JOB_CONTROL_RESUME:
6723 if (print_job_resume(&user, snum, jobid, &errcode)) {
6728 return WERR_UNKNOWN_LEVEL;
6734 /****************************************************************************
6735 Enumerates all printer drivers at level 1.
6736 ****************************************************************************/
6738 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6743 fstring *list = NULL;
6744 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6745 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6746 WERROR result = WERR_OK;
6750 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6752 ndrivers=get_ntdrivers(&list, architecture, version);
6753 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6759 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6760 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6761 SAFE_FREE(driver_info_1);
6765 else driver_info_1 = tdi1;
6768 for (i=0; i<ndrivers; i++) {
6770 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6771 ZERO_STRUCT(driver);
6772 status = get_a_printer_driver(&driver, 3, list[i],
6773 architecture, version);
6774 if (!W_ERROR_IS_OK(status)) {
6778 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6779 free_a_printer_driver(driver, 3);
6782 *returned+=ndrivers;
6786 /* check the required size. */
6787 for (i=0; i<*returned; i++) {
6788 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6789 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6792 if (*needed > offered) {
6793 result = WERR_INSUFFICIENT_BUFFER;
6797 if (!rpcbuf_alloc_size(buffer, *needed)) {
6798 result = WERR_NOMEM;
6802 /* fill the buffer with the driver structures */
6803 for (i=0; i<*returned; i++) {
6804 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6805 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6809 SAFE_FREE(driver_info_1);
6811 if ( !W_ERROR_IS_OK(result) )
6817 /****************************************************************************
6818 Enumerates all printer drivers at level 2.
6819 ****************************************************************************/
6821 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6826 fstring *list = NULL;
6827 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6828 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6829 WERROR result = WERR_OK;
6833 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6835 ndrivers=get_ntdrivers(&list, architecture, version);
6836 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6842 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6843 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6844 SAFE_FREE(driver_info_2);
6848 else driver_info_2 = tdi2;
6851 for (i=0; i<ndrivers; i++) {
6854 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6855 ZERO_STRUCT(driver);
6856 status = get_a_printer_driver(&driver, 3, list[i],
6857 architecture, version);
6858 if (!W_ERROR_IS_OK(status)) {
6862 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6863 free_a_printer_driver(driver, 3);
6866 *returned+=ndrivers;
6870 /* check the required size. */
6871 for (i=0; i<*returned; i++) {
6872 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6873 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6876 if (*needed > offered) {
6877 result = WERR_INSUFFICIENT_BUFFER;
6881 if (!rpcbuf_alloc_size(buffer, *needed)) {
6882 result = WERR_NOMEM;
6886 /* fill the buffer with the form structures */
6887 for (i=0; i<*returned; i++) {
6888 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6889 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6893 SAFE_FREE(driver_info_2);
6895 if ( !W_ERROR_IS_OK(result) )
6901 /****************************************************************************
6902 Enumerates all printer drivers at level 3.
6903 ****************************************************************************/
6905 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6910 fstring *list = NULL;
6911 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6912 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6913 WERROR result = WERR_OK;
6917 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6919 ndrivers=get_ntdrivers(&list, architecture, version);
6920 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6926 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6927 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6928 SAFE_FREE(driver_info_3);
6932 else driver_info_3 = tdi3;
6935 for (i=0; i<ndrivers; i++) {
6938 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6939 ZERO_STRUCT(driver);
6940 status = get_a_printer_driver(&driver, 3, list[i],
6941 architecture, version);
6942 if (!W_ERROR_IS_OK(status)) {
6946 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6947 free_a_printer_driver(driver, 3);
6950 *returned+=ndrivers;
6954 /* check the required size. */
6955 for (i=0; i<*returned; i++) {
6956 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6957 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6960 if (*needed > offered) {
6961 result = WERR_INSUFFICIENT_BUFFER;
6965 if (!rpcbuf_alloc_size(buffer, *needed)) {
6966 result = WERR_NOMEM;
6970 /* fill the buffer with the driver structures */
6971 for (i=0; i<*returned; i++) {
6972 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6973 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6977 for (i=0; i<*returned; i++)
6978 SAFE_FREE(driver_info_3[i].dependentfiles);
6980 SAFE_FREE(driver_info_3);
6982 if ( !W_ERROR_IS_OK(result) )
6988 /****************************************************************************
6989 Enumerates all printer drivers.
6990 ****************************************************************************/
6992 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6994 uint32 level = q_u->level;
6995 RPC_BUFFER *buffer = NULL;
6996 uint32 offered = q_u->offered;
6997 uint32 *needed = &r_u->needed;
6998 uint32 *returned = &r_u->returned;
7001 fstring architecture;
7003 /* that's an [in out] buffer */
7005 if ( q_u->buffer ) {
7006 rpcbuf_move(q_u->buffer, &r_u->buffer);
7007 buffer = r_u->buffer;
7010 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7015 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7016 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7018 if ( !is_myname_or_ipaddr( servername ) )
7019 return WERR_UNKNOWN_PRINTER_DRIVER;
7023 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7025 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7027 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7029 return WERR_UNKNOWN_LEVEL;
7033 /****************************************************************************
7034 ****************************************************************************/
7036 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7038 form->flag=list->flag;
7039 init_unistr(&form->name, list->name);
7040 form->width=list->width;
7041 form->length=list->length;
7042 form->left=list->left;
7043 form->top=list->top;
7044 form->right=list->right;
7045 form->bottom=list->bottom;
7048 /****************************************************************************
7049 ****************************************************************************/
7051 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7053 uint32 level = q_u->level;
7054 RPC_BUFFER *buffer = NULL;
7055 uint32 offered = q_u->offered;
7056 uint32 *needed = &r_u->needed;
7057 uint32 *numofforms = &r_u->numofforms;
7058 uint32 numbuiltinforms;
7060 nt_forms_struct *list=NULL;
7061 nt_forms_struct *builtinlist=NULL;
7066 /* that's an [in out] buffer */
7068 if ( q_u->buffer ) {
7069 rpcbuf_move(q_u->buffer, &r_u->buffer);
7070 buffer = r_u->buffer;
7073 DEBUG(4,("_spoolss_enumforms\n"));
7074 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7075 DEBUGADD(5,("Info level [%d]\n", level));
7077 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7078 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7079 *numofforms = get_ntforms(&list);
7080 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7081 *numofforms += numbuiltinforms;
7083 if (*numofforms == 0)
7084 return WERR_NO_MORE_ITEMS;
7088 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7093 /* construct the list of form structures */
7094 for (i=0; i<numbuiltinforms; i++) {
7095 DEBUGADD(6,("Filling form number [%d]\n",i));
7096 fill_form_1(&forms_1[i], &builtinlist[i]);
7099 SAFE_FREE(builtinlist);
7101 for (; i<*numofforms; i++) {
7102 DEBUGADD(6,("Filling form number [%d]\n",i));
7103 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7108 /* check the required size. */
7109 for (i=0; i<numbuiltinforms; i++) {
7110 DEBUGADD(6,("adding form [%d]'s size\n",i));
7111 buffer_size += spoolss_size_form_1(&forms_1[i]);
7113 for (; i<*numofforms; i++) {
7114 DEBUGADD(6,("adding form [%d]'s size\n",i));
7115 buffer_size += spoolss_size_form_1(&forms_1[i]);
7118 *needed=buffer_size;
7120 if (*needed > offered) {
7123 return WERR_INSUFFICIENT_BUFFER;
7126 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7132 /* fill the buffer with the form structures */
7133 for (i=0; i<numbuiltinforms; i++) {
7134 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7135 smb_io_form_1("", buffer, &forms_1[i], 0);
7137 for (; i<*numofforms; i++) {
7138 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7139 smb_io_form_1("", buffer, &forms_1[i], 0);
7148 SAFE_FREE(builtinlist);
7149 return WERR_UNKNOWN_LEVEL;
7154 /****************************************************************************
7155 ****************************************************************************/
7157 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7159 uint32 level = q_u->level;
7160 UNISTR2 *uni_formname = &q_u->formname;
7161 RPC_BUFFER *buffer = NULL;
7162 uint32 offered = q_u->offered;
7163 uint32 *needed = &r_u->needed;
7165 nt_forms_struct *list=NULL;
7166 nt_forms_struct builtin_form;
7171 int numofforms=0, i=0;
7173 /* that's an [in out] buffer */
7175 if ( q_u->buffer ) {
7176 rpcbuf_move(q_u->buffer, &r_u->buffer);
7177 buffer = r_u->buffer;
7180 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7182 DEBUG(4,("_spoolss_getform\n"));
7183 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7184 DEBUGADD(5,("Info level [%d]\n", level));
7186 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7187 if (!foundBuiltin) {
7188 numofforms = get_ntforms(&list);
7189 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7191 if (numofforms == 0)
7198 fill_form_1(&form_1, &builtin_form);
7201 /* Check if the requested name is in the list of form structures */
7202 for (i=0; i<numofforms; i++) {
7204 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7206 if (strequal(form_name, list[i].name)) {
7207 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7208 fill_form_1(&form_1, &list[i]);
7214 if (i == numofforms) {
7218 /* check the required size. */
7220 *needed=spoolss_size_form_1(&form_1);
7222 if (*needed > offered)
7223 return WERR_INSUFFICIENT_BUFFER;
7225 if (!rpcbuf_alloc_size(buffer, buffer_size))
7228 /* fill the buffer with the form structures */
7229 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7230 smb_io_form_1("", buffer, &form_1, 0);
7236 return WERR_UNKNOWN_LEVEL;
7240 /****************************************************************************
7241 ****************************************************************************/
7243 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7245 init_unistr(&port->port_name, name);
7248 /****************************************************************************
7249 ****************************************************************************/
7251 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7253 init_unistr(&port->port_name, name);
7254 init_unistr(&port->monitor_name, "Local Monitor");
7255 init_unistr(&port->description, "Local Port");
7256 port->port_type=PORT_TYPE_WRITE;
7261 /****************************************************************************
7262 wrapper around the enumer ports command
7263 ****************************************************************************/
7265 WERROR enumports_hook( int *count, char ***lines )
7267 char *cmd = lp_enumports_cmd();
7275 /* if no hook then just fill in the default port */
7278 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7279 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7284 /* we have a valid enumport command */
7286 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7288 DEBUG(10,("Running [%s]\n", command));
7289 ret = smbrun(command, &fd);
7290 DEBUG(10,("Returned [%d]\n", ret));
7295 return WERR_ACCESS_DENIED;
7299 qlines = fd_lines_load(fd, &numlines);
7300 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7310 /****************************************************************************
7312 ****************************************************************************/
7314 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7316 PORT_INFO_1 *ports=NULL;
7318 WERROR result = WERR_OK;
7322 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7326 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7327 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7328 dos_errstr(WERR_NOMEM)));
7329 file_lines_free(qlines);
7333 for (i=0; i<numlines; i++) {
7334 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7335 fill_port_1(&ports[i], qlines[i]);
7338 file_lines_free(qlines);
7341 *returned = numlines;
7343 /* check the required size. */
7344 for (i=0; i<*returned; i++) {
7345 DEBUGADD(6,("adding port [%d]'s size\n", i));
7346 *needed += spoolss_size_port_info_1(&ports[i]);
7349 if (*needed > offered) {
7350 result = WERR_INSUFFICIENT_BUFFER;
7354 if (!rpcbuf_alloc_size(buffer, *needed)) {
7355 result = WERR_NOMEM;
7359 /* fill the buffer with the ports structures */
7360 for (i=0; i<*returned; i++) {
7361 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7362 smb_io_port_1("", buffer, &ports[i], 0);
7368 if ( !W_ERROR_IS_OK(result) )
7374 /****************************************************************************
7376 ****************************************************************************/
7378 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7380 PORT_INFO_2 *ports=NULL;
7382 WERROR result = WERR_OK;
7386 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7391 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7392 file_lines_free(qlines);
7396 for (i=0; i<numlines; i++) {
7397 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7398 fill_port_2(&(ports[i]), qlines[i]);
7401 file_lines_free(qlines);
7404 *returned = numlines;
7406 /* check the required size. */
7407 for (i=0; i<*returned; i++) {
7408 DEBUGADD(6,("adding port [%d]'s size\n", i));
7409 *needed += spoolss_size_port_info_2(&ports[i]);
7412 if (*needed > offered) {
7413 result = WERR_INSUFFICIENT_BUFFER;
7417 if (!rpcbuf_alloc_size(buffer, *needed)) {
7418 result = WERR_NOMEM;
7422 /* fill the buffer with the ports structures */
7423 for (i=0; i<*returned; i++) {
7424 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7425 smb_io_port_2("", buffer, &ports[i], 0);
7431 if ( !W_ERROR_IS_OK(result) )
7437 /****************************************************************************
7439 ****************************************************************************/
7441 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7443 uint32 level = q_u->level;
7444 RPC_BUFFER *buffer = NULL;
7445 uint32 offered = q_u->offered;
7446 uint32 *needed = &r_u->needed;
7447 uint32 *returned = &r_u->returned;
7449 /* that's an [in out] buffer */
7451 if ( q_u->buffer ) {
7452 rpcbuf_move(q_u->buffer, &r_u->buffer);
7453 buffer = r_u->buffer;
7456 DEBUG(4,("_spoolss_enumports\n"));
7463 return enumports_level_1(buffer, offered, needed, returned);
7465 return enumports_level_2(buffer, offered, needed, returned);
7467 return WERR_UNKNOWN_LEVEL;
7471 /****************************************************************************
7472 ****************************************************************************/
7474 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7475 const SPOOL_PRINTER_INFO_LEVEL *info,
7476 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7477 uint32 user_switch, const SPOOL_USER_CTR *user,
7480 NT_PRINTER_INFO_LEVEL *printer = NULL;
7483 WERROR err = WERR_OK;
7485 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7486 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7490 ZERO_STRUCTP(printer);
7492 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7493 if (!convert_printer_info(info, printer, 2)) {
7494 free_a_printer(&printer, 2);
7498 /* check to see if the printer already exists */
7500 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7501 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7502 printer->info_2->sharename));
7503 free_a_printer(&printer, 2);
7504 return WERR_PRINTER_ALREADY_EXISTS;
7507 /* FIXME!!! smbd should check to see if the driver is installed before
7508 trying to add a printer like this --jerry */
7510 if (*lp_addprinter_cmd() ) {
7511 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7512 free_a_printer(&printer,2);
7513 return WERR_ACCESS_DENIED;
7516 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7517 "smb.conf parameter \"addprinter command\" is defined. This"
7518 "parameter must exist for this call to succeed\n",
7519 printer->info_2->sharename ));
7522 /* use our primary netbios name since get_a_printer() will convert
7523 it to what the client expects on a case by case basis */
7525 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7526 printer->info_2->sharename);
7529 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7530 free_a_printer(&printer,2);
7531 return WERR_ACCESS_DENIED;
7534 /* you must be a printer admin to add a new printer */
7535 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7536 free_a_printer(&printer,2);
7537 return WERR_ACCESS_DENIED;
7541 * Do sanity check on the requested changes for Samba.
7544 if (!check_printer_ok(printer->info_2, snum)) {
7545 free_a_printer(&printer,2);
7546 return WERR_INVALID_PARAM;
7550 * When a printer is created, the drivername bound to the printer is used
7551 * to lookup previously saved driver initialization info, which is then
7552 * bound to the new printer, simulating what happens in the Windows arch.
7557 set_driver_init(printer, 2);
7561 /* A valid devmode was included, convert and link it
7563 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7565 if (!convert_devicemode(printer->info_2->printername, devmode,
7566 &printer->info_2->devmode))
7570 /* write the ASCII on disk */
7571 err = mod_a_printer(printer, 2);
7572 if (!W_ERROR_IS_OK(err)) {
7573 free_a_printer(&printer,2);
7577 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7578 /* Handle open failed - remove addition. */
7579 del_a_printer(printer->info_2->sharename);
7580 free_a_printer(&printer,2);
7581 return WERR_ACCESS_DENIED;
7584 update_c_setprinter(False);
7585 free_a_printer(&printer,2);
7590 /****************************************************************************
7591 ****************************************************************************/
7593 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7595 UNISTR2 *uni_srv_name = q_u->server_name;
7596 uint32 level = q_u->level;
7597 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7598 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7599 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7600 uint32 user_switch = q_u->user_switch;
7601 SPOOL_USER_CTR *user = &q_u->user_ctr;
7602 POLICY_HND *handle = &r_u->handle;
7606 /* we don't handle yet */
7607 /* but I know what to do ... */
7608 return WERR_UNKNOWN_LEVEL;
7610 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7612 user_switch, user, handle);
7614 return WERR_UNKNOWN_LEVEL;
7618 /****************************************************************************
7619 ****************************************************************************/
7621 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7623 uint32 level = q_u->level;
7624 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7625 WERROR err = WERR_OK;
7626 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7627 struct current_user user;
7628 fstring driver_name;
7631 ZERO_STRUCT(driver);
7633 get_current_user(&user, p);
7635 if (!convert_printer_driver_info(info, &driver, level)) {
7640 DEBUG(5,("Cleaning driver's information\n"));
7641 err = clean_up_driver_struct(driver, level, &user);
7642 if (!W_ERROR_IS_OK(err))
7645 DEBUG(5,("Moving driver to final destination\n"));
7646 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7650 if (add_a_printer_driver(driver, level)!=0) {
7651 err = WERR_ACCESS_DENIED;
7655 /* BEGIN_ADMIN_LOG */
7658 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7659 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7660 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7663 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7664 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7665 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7671 * I think this is where he DrvUpgradePrinter() hook would be
7672 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7673 * server. Right now, we just need to send ourselves a message
7674 * to update each printer bound to this driver. --jerry
7677 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7678 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7683 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7684 * decide if the driver init data should be deleted. The rules are:
7685 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7686 * 2) delete init data only if there is no 2k/Xp driver
7687 * 3) always delete init data
7688 * The generalized rule is always use init data from the highest order driver.
7689 * It is necessary to follow the driver install by an initialization step to
7690 * finish off this process.
7693 version = driver.info_3->cversion;
7694 else if (level == 6)
7695 version = driver.info_6->version;
7700 * 9x printer driver - never delete init data
7703 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7708 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7709 * there is no 2k/Xp driver init data for this driver name.
7713 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7715 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7717 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7719 if (!del_driver_init(driver_name))
7720 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7723 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7725 free_a_printer_driver(driver1,3);
7726 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7733 * 2k or Xp printer driver - always delete init data
7736 if (!del_driver_init(driver_name))
7737 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7741 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7747 free_a_printer_driver(driver, level);
7751 /********************************************************************
7752 * spoolss_addprinterdriverex
7753 ********************************************************************/
7755 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7757 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7758 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7761 * we only support the semantics of AddPrinterDriver()
7762 * i.e. only copy files that are newer than existing ones
7765 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7766 return WERR_ACCESS_DENIED;
7768 ZERO_STRUCT(q_u_local);
7769 ZERO_STRUCT(r_u_local);
7771 /* just pass the information off to _spoolss_addprinterdriver() */
7772 q_u_local.server_name_ptr = q_u->server_name_ptr;
7773 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7774 q_u_local.level = q_u->level;
7775 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7777 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7780 /****************************************************************************
7781 ****************************************************************************/
7783 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7785 init_unistr(&info->name, name);
7788 /****************************************************************************
7789 ****************************************************************************/
7791 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7797 const char *short_archi;
7798 DRIVER_DIRECTORY_1 *info=NULL;
7799 WERROR result = WERR_OK;
7801 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7802 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7804 /* check for beginning double '\'s and that the server
7807 pservername = servername;
7808 if ( *pservername == '\\' && strlen(servername)>2 ) {
7812 if ( !is_myname_or_ipaddr( pservername ) )
7813 return WERR_INVALID_PARAM;
7815 if (!(short_archi = get_short_archi(long_archi)))
7816 return WERR_INVALID_ENVIRONMENT;
7818 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7821 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7823 DEBUG(4,("printer driver directory: [%s]\n", path));
7825 fill_driverdir_1(info, path);
7827 *needed += spoolss_size_driverdir_info_1(info);
7829 if (*needed > offered) {
7830 result = WERR_INSUFFICIENT_BUFFER;
7834 if (!rpcbuf_alloc_size(buffer, *needed)) {
7835 result = WERR_NOMEM;
7839 smb_io_driverdir_1("", buffer, info, 0);
7847 /****************************************************************************
7848 ****************************************************************************/
7850 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7852 UNISTR2 *name = &q_u->name;
7853 UNISTR2 *uni_environment = &q_u->environment;
7854 uint32 level = q_u->level;
7855 RPC_BUFFER *buffer = NULL;
7856 uint32 offered = q_u->offered;
7857 uint32 *needed = &r_u->needed;
7859 /* that's an [in out] buffer */
7861 if ( q_u->buffer ) {
7862 rpcbuf_move(q_u->buffer, &r_u->buffer);
7863 buffer = r_u->buffer;
7866 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7872 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7874 return WERR_UNKNOWN_LEVEL;
7878 /****************************************************************************
7879 ****************************************************************************/
7881 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7883 POLICY_HND *handle = &q_u->handle;
7884 uint32 idx = q_u->index;
7885 uint32 in_value_len = q_u->valuesize;
7886 uint32 in_data_len = q_u->datasize;
7887 uint32 *out_max_value_len = &r_u->valuesize;
7888 uint16 **out_value = &r_u->value;
7889 uint32 *out_value_len = &r_u->realvaluesize;
7890 uint32 *out_type = &r_u->type;
7891 uint32 *out_max_data_len = &r_u->datasize;
7892 uint8 **data_out = &r_u->data;
7893 uint32 *out_data_len = &r_u->realdatasize;
7895 NT_PRINTER_INFO_LEVEL *printer = NULL;
7897 uint32 biggest_valuesize;
7898 uint32 biggest_datasize;
7900 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7903 REGISTRY_VALUE *val = NULL;
7904 NT_PRINTER_DATA *p_data;
7905 int i, key_index, num_values;
7908 ZERO_STRUCT( printer );
7912 *out_max_data_len = 0;
7916 DEBUG(5,("spoolss_enumprinterdata\n"));
7919 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7923 if (!get_printer_snum(p,handle, &snum))
7926 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7927 if (!W_ERROR_IS_OK(result))
7930 p_data = &printer->info_2->data;
7931 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7936 * The NT machine wants to know the biggest size of value and data
7938 * cf: MSDN EnumPrinterData remark section
7941 if ( !in_value_len && !in_data_len && (key_index != -1) )
7943 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7945 biggest_valuesize = 0;
7946 biggest_datasize = 0;
7948 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7950 for ( i=0; i<num_values; i++ )
7952 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7954 name_length = strlen(val->valuename);
7955 if ( strlen(val->valuename) > biggest_valuesize )
7956 biggest_valuesize = name_length;
7958 if ( val->size > biggest_datasize )
7959 biggest_datasize = val->size;
7961 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7965 /* the value is an UNICODE string but real_value_size is the length
7966 in bytes including the trailing 0 */
7968 *out_value_len = 2 * (1+biggest_valuesize);
7969 *out_data_len = biggest_datasize;
7971 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7977 * the value len is wrong in NT sp3
7978 * that's the number of bytes not the number of unicode chars
7981 if ( key_index != -1 )
7982 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7987 /* out_value should default to "" or else NT4 has
7988 problems unmarshalling the response */
7990 *out_max_value_len=(in_value_len/sizeof(uint16));
7992 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7994 result = WERR_NOMEM;
7998 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8000 /* the data is counted in bytes */
8002 *out_max_data_len = in_data_len;
8003 *out_data_len = in_data_len;
8005 /* only allocate when given a non-zero data_len */
8007 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8009 result = WERR_NOMEM;
8013 result = WERR_NO_MORE_ITEMS;
8019 * - counted in bytes in the request
8020 * - counted in UNICODE chars in the max reply
8021 * - counted in bytes in the real size
8023 * take a pause *before* coding not *during* coding
8027 *out_max_value_len=(in_value_len/sizeof(uint16));
8028 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8030 result = WERR_NOMEM;
8034 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
8038 *out_type = regval_type( val );
8040 /* data - counted in bytes */
8042 *out_max_data_len = in_data_len;
8043 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8045 result = WERR_NOMEM;
8048 data_len = regval_size(val);
8050 memcpy( *data_out, regval_data_p(val), data_len );
8051 *out_data_len = data_len;
8055 free_a_printer(&printer, 2);
8059 /****************************************************************************
8060 ****************************************************************************/
8062 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8064 POLICY_HND *handle = &q_u->handle;
8065 UNISTR2 *value = &q_u->value;
8066 uint32 type = q_u->type;
8067 uint8 *data = q_u->data;
8068 uint32 real_len = q_u->real_len;
8070 NT_PRINTER_INFO_LEVEL *printer = NULL;
8072 WERROR status = WERR_OK;
8073 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8076 DEBUG(5,("spoolss_setprinterdata\n"));
8079 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8083 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8084 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8085 return WERR_INVALID_PARAM;
8088 if (!get_printer_snum(p,handle, &snum))
8092 * Access check : NT returns "access denied" if you make a
8093 * SetPrinterData call without the necessary privildge.
8094 * we were originally returning OK if nothing changed
8095 * which made Win2k issue **a lot** of SetPrinterData
8096 * when connecting to a printer --jerry
8099 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8101 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8102 status = WERR_ACCESS_DENIED;
8106 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8107 if (!W_ERROR_IS_OK(status))
8110 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8113 * When client side code sets a magic printer data key, detect it and save
8114 * the current printer data and the magic key's data (its the DEVMODE) for
8115 * future printer/driver initializations.
8117 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8119 /* Set devmode and printer initialization info */
8120 status = save_driver_init( printer, 2, data, real_len );
8122 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8126 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8127 type, data, real_len );
8128 if ( W_ERROR_IS_OK(status) )
8129 status = mod_a_printer(printer, 2);
8133 free_a_printer(&printer, 2);
8138 /****************************************************************************
8139 ****************************************************************************/
8141 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8143 POLICY_HND *handle = &q_u->handle;
8144 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8147 DEBUG(5,("_spoolss_resetprinter\n"));
8150 * All we do is to check to see if the handle and queue is valid.
8151 * This call really doesn't mean anything to us because we only
8152 * support RAW printing. --jerry
8156 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8160 if (!get_printer_snum(p,handle, &snum))
8164 /* blindly return success */
8169 /****************************************************************************
8170 ****************************************************************************/
8172 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8174 POLICY_HND *handle = &q_u->handle;
8175 UNISTR2 *value = &q_u->valuename;
8177 NT_PRINTER_INFO_LEVEL *printer = NULL;
8179 WERROR status = WERR_OK;
8180 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8183 DEBUG(5,("spoolss_deleteprinterdata\n"));
8186 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8190 if (!get_printer_snum(p, handle, &snum))
8193 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8194 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8195 return WERR_ACCESS_DENIED;
8198 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8199 if (!W_ERROR_IS_OK(status))
8202 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8204 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8206 if ( W_ERROR_IS_OK(status) )
8207 mod_a_printer( printer, 2 );
8209 free_a_printer(&printer, 2);
8214 /****************************************************************************
8215 ****************************************************************************/
8217 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8219 POLICY_HND *handle = &q_u->handle;
8220 FORM *form = &q_u->form;
8221 nt_forms_struct tmpForm;
8223 WERROR status = WERR_OK;
8224 NT_PRINTER_INFO_LEVEL *printer = NULL;
8227 nt_forms_struct *list=NULL;
8228 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8230 DEBUG(5,("spoolss_addform\n"));
8233 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8238 /* forms can be added on printer of on the print server handle */
8240 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8242 if (!get_printer_snum(p,handle, &snum))
8245 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8246 if (!W_ERROR_IS_OK(status))
8250 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8251 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8252 status = WERR_ACCESS_DENIED;
8256 /* can't add if builtin */
8258 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8259 status = WERR_ALREADY_EXISTS;
8263 count = get_ntforms(&list);
8265 if(!add_a_form(&list, form, &count)) {
8266 status = WERR_NOMEM;
8270 write_ntforms(&list, count);
8273 * ChangeID must always be set if this is a printer
8276 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8277 status = mod_a_printer(printer, 2);
8281 free_a_printer(&printer, 2);
8287 /****************************************************************************
8288 ****************************************************************************/
8290 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8292 POLICY_HND *handle = &q_u->handle;
8293 UNISTR2 *form_name = &q_u->name;
8294 nt_forms_struct tmpForm;
8296 nt_forms_struct *list=NULL;
8297 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8299 WERROR status = WERR_OK;
8300 NT_PRINTER_INFO_LEVEL *printer = NULL;
8302 DEBUG(5,("spoolss_deleteform\n"));
8305 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8309 /* forms can be deleted on printer of on the print server handle */
8311 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8313 if (!get_printer_snum(p,handle, &snum))
8316 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8317 if (!W_ERROR_IS_OK(status))
8321 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8322 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8323 status = WERR_ACCESS_DENIED;
8327 /* can't delete if builtin */
8329 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8330 status = WERR_INVALID_PARAM;
8334 count = get_ntforms(&list);
8336 if ( !delete_a_form(&list, form_name, &count, &status ))
8340 * ChangeID must always be set if this is a printer
8343 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8344 status = mod_a_printer(printer, 2);
8348 free_a_printer(&printer, 2);
8354 /****************************************************************************
8355 ****************************************************************************/
8357 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8359 POLICY_HND *handle = &q_u->handle;
8360 FORM *form = &q_u->form;
8361 nt_forms_struct tmpForm;
8363 WERROR status = WERR_OK;
8364 NT_PRINTER_INFO_LEVEL *printer = NULL;
8367 nt_forms_struct *list=NULL;
8368 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8370 DEBUG(5,("spoolss_setform\n"));
8373 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8377 /* forms can be modified on printer of on the print server handle */
8379 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8381 if (!get_printer_snum(p,handle, &snum))
8384 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8385 if (!W_ERROR_IS_OK(status))
8389 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8390 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8391 status = WERR_ACCESS_DENIED;
8395 /* can't set if builtin */
8396 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8397 status = WERR_INVALID_PARAM;
8401 count = get_ntforms(&list);
8402 update_a_form(&list, form, count);
8403 write_ntforms(&list, count);
8406 * ChangeID must always be set if this is a printer
8409 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8410 status = mod_a_printer(printer, 2);
8415 free_a_printer(&printer, 2);
8421 /****************************************************************************
8422 enumprintprocessors level 1.
8423 ****************************************************************************/
8425 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8427 PRINTPROCESSOR_1 *info_1=NULL;
8428 WERROR result = WERR_OK;
8430 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8435 init_unistr(&info_1->name, "winprint");
8437 *needed += spoolss_size_printprocessor_info_1(info_1);
8439 if (*needed > offered) {
8440 result = WERR_INSUFFICIENT_BUFFER;
8444 if (!rpcbuf_alloc_size(buffer, *needed)) {
8445 result = WERR_NOMEM;
8449 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8454 if ( !W_ERROR_IS_OK(result) )
8460 /****************************************************************************
8461 ****************************************************************************/
8463 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8465 uint32 level = q_u->level;
8466 RPC_BUFFER *buffer = NULL;
8467 uint32 offered = q_u->offered;
8468 uint32 *needed = &r_u->needed;
8469 uint32 *returned = &r_u->returned;
8471 /* that's an [in out] buffer */
8473 if ( q_u->buffer ) {
8474 rpcbuf_move(q_u->buffer, &r_u->buffer);
8475 buffer = r_u->buffer;
8478 DEBUG(5,("spoolss_enumprintprocessors\n"));
8481 * Enumerate the print processors ...
8483 * Just reply with "winprint", to keep NT happy
8484 * and I can use my nice printer checker.
8492 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8494 return WERR_UNKNOWN_LEVEL;
8498 /****************************************************************************
8499 enumprintprocdatatypes level 1.
8500 ****************************************************************************/
8502 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8504 PRINTPROCDATATYPE_1 *info_1=NULL;
8505 WERROR result = WERR_NOMEM;
8507 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8512 init_unistr(&info_1->name, "RAW");
8514 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8516 if (*needed > offered) {
8517 result = WERR_INSUFFICIENT_BUFFER;
8521 if (!rpcbuf_alloc_size(buffer, *needed)) {
8522 result = WERR_NOMEM;
8526 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8531 if ( !W_ERROR_IS_OK(result) )
8537 /****************************************************************************
8538 ****************************************************************************/
8540 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8542 uint32 level = q_u->level;
8543 RPC_BUFFER *buffer = NULL;
8544 uint32 offered = q_u->offered;
8545 uint32 *needed = &r_u->needed;
8546 uint32 *returned = &r_u->returned;
8548 /* that's an [in out] buffer */
8550 if ( q_u->buffer ) {
8551 rpcbuf_move(q_u->buffer, &r_u->buffer);
8552 buffer = r_u->buffer;
8555 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8562 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8564 return WERR_UNKNOWN_LEVEL;
8568 /****************************************************************************
8569 enumprintmonitors level 1.
8570 ****************************************************************************/
8572 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8574 PRINTMONITOR_1 *info_1=NULL;
8575 WERROR result = WERR_OK;
8577 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8582 init_unistr(&info_1->name, "Local Port");
8584 *needed += spoolss_size_printmonitor_info_1(info_1);
8586 if (*needed > offered) {
8587 result = WERR_INSUFFICIENT_BUFFER;
8591 if (!rpcbuf_alloc_size(buffer, *needed)) {
8592 result = WERR_NOMEM;
8596 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8601 if ( !W_ERROR_IS_OK(result) )
8607 /****************************************************************************
8608 enumprintmonitors level 2.
8609 ****************************************************************************/
8611 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8613 PRINTMONITOR_2 *info_2=NULL;
8614 WERROR result = WERR_OK;
8616 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8621 init_unistr(&info_2->name, "Local Port");
8622 init_unistr(&info_2->environment, "Windows NT X86");
8623 init_unistr(&info_2->dll_name, "localmon.dll");
8625 *needed += spoolss_size_printmonitor_info_2(info_2);
8627 if (*needed > offered) {
8628 result = WERR_INSUFFICIENT_BUFFER;
8632 if (!rpcbuf_alloc_size(buffer, *needed)) {
8633 result = WERR_NOMEM;
8637 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8642 if ( !W_ERROR_IS_OK(result) )
8648 /****************************************************************************
8649 ****************************************************************************/
8651 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8653 uint32 level = q_u->level;
8654 RPC_BUFFER *buffer = NULL;
8655 uint32 offered = q_u->offered;
8656 uint32 *needed = &r_u->needed;
8657 uint32 *returned = &r_u->returned;
8659 /* that's an [in out] buffer */
8661 if ( q_u->buffer ) {
8662 rpcbuf_move(q_u->buffer, &r_u->buffer);
8663 buffer = r_u->buffer;
8666 DEBUG(5,("spoolss_enumprintmonitors\n"));
8669 * Enumerate the print monitors ...
8671 * Just reply with "Local Port", to keep NT happy
8672 * and I can use my nice printer checker.
8680 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8682 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8684 return WERR_UNKNOWN_LEVEL;
8688 /****************************************************************************
8689 ****************************************************************************/
8691 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8692 NT_PRINTER_INFO_LEVEL *ntprinter,
8693 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8698 JOB_INFO_1 *info_1=NULL;
8699 WERROR result = WERR_OK;
8701 info_1=SMB_MALLOC_P(JOB_INFO_1);
8703 if (info_1 == NULL) {
8707 for (i=0; i<count && found==False; i++) {
8708 if ((*queue)[i].job==(int)jobid)
8714 /* NT treats not found as bad param... yet another bad choice */
8715 return WERR_INVALID_PARAM;
8718 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8720 *needed += spoolss_size_job_info_1(info_1);
8722 if (*needed > offered) {
8723 result = WERR_INSUFFICIENT_BUFFER;
8727 if (!rpcbuf_alloc_size(buffer, *needed)) {
8728 result = WERR_NOMEM;
8732 smb_io_job_info_1("", buffer, info_1, 0);
8740 /****************************************************************************
8741 ****************************************************************************/
8743 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8744 NT_PRINTER_INFO_LEVEL *ntprinter,
8745 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8752 DEVICEMODE *devmode = NULL;
8753 NT_DEVICEMODE *nt_devmode = NULL;
8755 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8758 ZERO_STRUCTP(info_2);
8760 for ( i=0; i<count && found==False; i++ )
8762 if ((*queue)[i].job == (int)jobid)
8767 /* NT treats not found as bad param... yet another bad
8769 result = WERR_INVALID_PARAM;
8774 * if the print job does not have a DEVMODE associated with it,
8775 * just use the one for the printer. A NULL devicemode is not
8776 * a failure condition
8779 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8780 devmode = construct_dev_mode(snum);
8782 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8783 ZERO_STRUCTP( devmode );
8784 convert_nt_devicemode( devmode, nt_devmode );
8788 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8790 *needed += spoolss_size_job_info_2(info_2);
8792 if (*needed > offered) {
8793 result = WERR_INSUFFICIENT_BUFFER;
8797 if (!rpcbuf_alloc_size(buffer, *needed)) {
8798 result = WERR_NOMEM;
8802 smb_io_job_info_2("", buffer, info_2, 0);
8807 /* Cleanup allocated memory */
8809 free_job_info_2(info_2); /* Also frees devmode */
8815 /****************************************************************************
8816 ****************************************************************************/
8818 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8820 POLICY_HND *handle = &q_u->handle;
8821 uint32 jobid = q_u->jobid;
8822 uint32 level = q_u->level;
8823 RPC_BUFFER *buffer = NULL;
8824 uint32 offered = q_u->offered;
8825 uint32 *needed = &r_u->needed;
8826 WERROR wstatus = WERR_OK;
8827 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8830 print_queue_struct *queue = NULL;
8831 print_status_struct prt_status;
8833 /* that's an [in out] buffer */
8835 if ( q_u->buffer ) {
8836 rpcbuf_move(q_u->buffer, &r_u->buffer);
8837 buffer = r_u->buffer;
8840 DEBUG(5,("spoolss_getjob\n"));
8844 if (!get_printer_snum(p, handle, &snum))
8847 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8848 if ( !W_ERROR_IS_OK(wstatus) )
8851 count = print_queue_status(snum, &queue, &prt_status);
8853 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8854 count, prt_status.status, prt_status.message));
8858 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8859 buffer, offered, needed);
8862 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8863 buffer, offered, needed);
8866 wstatus = WERR_UNKNOWN_LEVEL;
8871 free_a_printer( &ntprinter, 2 );
8876 /********************************************************************
8877 spoolss_getprinterdataex
8879 From MSDN documentation of GetPrinterDataEx: pass request
8880 to GetPrinterData if key is "PrinterDriverData".
8881 ********************************************************************/
8883 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8885 POLICY_HND *handle = &q_u->handle;
8886 uint32 in_size = q_u->size;
8887 uint32 *type = &r_u->type;
8888 uint32 *out_size = &r_u->size;
8889 uint8 **data = &r_u->data;
8890 uint32 *needed = &r_u->needed;
8891 fstring keyname, valuename;
8893 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8895 NT_PRINTER_INFO_LEVEL *printer = NULL;
8897 WERROR status = WERR_OK;
8899 DEBUG(4,("_spoolss_getprinterdataex\n"));
8901 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8902 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8904 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8905 keyname, valuename));
8907 /* in case of problem, return some default values */
8911 *out_size = in_size;
8914 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8915 status = WERR_BADFID;
8919 /* Is the handle to a printer or to the server? */
8921 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8922 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8923 status = WERR_INVALID_PARAM;
8927 if ( !get_printer_snum(p,handle, &snum) )
8930 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8931 if ( !W_ERROR_IS_OK(status) )
8934 /* check to see if the keyname is valid */
8935 if ( !strlen(keyname) ) {
8936 status = WERR_INVALID_PARAM;
8940 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8941 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8942 free_a_printer( &printer, 2 );
8943 status = WERR_BADFILE;
8947 /* When given a new keyname, we should just create it */
8949 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8951 if (*needed > *out_size)
8952 status = WERR_MORE_DATA;
8955 if ( !W_ERROR_IS_OK(status) )
8957 DEBUG(5, ("error: allocating %d\n", *out_size));
8959 /* reply this param doesn't exist */
8963 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8964 status = WERR_NOMEM;
8974 free_a_printer( &printer, 2 );
8979 /********************************************************************
8980 * spoolss_setprinterdataex
8981 ********************************************************************/
8983 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8985 POLICY_HND *handle = &q_u->handle;
8986 uint32 type = q_u->type;
8987 uint8 *data = q_u->data;
8988 uint32 real_len = q_u->real_len;
8990 NT_PRINTER_INFO_LEVEL *printer = NULL;
8992 WERROR status = WERR_OK;
8993 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8998 DEBUG(4,("_spoolss_setprinterdataex\n"));
9000 /* From MSDN documentation of SetPrinterDataEx: pass request to
9001 SetPrinterData if key is "PrinterDriverData" */
9004 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9008 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
9009 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9010 return WERR_INVALID_PARAM;
9013 if ( !get_printer_snum(p,handle, &snum) )
9017 * Access check : NT returns "access denied" if you make a
9018 * SetPrinterData call without the necessary privildge.
9019 * we were originally returning OK if nothing changed
9020 * which made Win2k issue **a lot** of SetPrinterData
9021 * when connecting to a printer --jerry
9024 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9026 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9027 return WERR_ACCESS_DENIED;
9030 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9031 if (!W_ERROR_IS_OK(status))
9034 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9035 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9037 /* check for OID in valuename */
9039 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9045 /* save the registry data */
9047 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9049 if ( W_ERROR_IS_OK(status) )
9051 /* save the OID if one was specified */
9053 fstrcat( keyname, "\\" );
9054 fstrcat( keyname, SPOOL_OID_KEY );
9057 * I'm not checking the status here on purpose. Don't know
9058 * if this is right, but I'm returning the status from the
9059 * previous set_printer_dataex() call. I have no idea if
9060 * this is right. --jerry
9063 set_printer_dataex( printer, keyname, valuename,
9064 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9067 status = mod_a_printer(printer, 2);
9070 free_a_printer(&printer, 2);
9076 /********************************************************************
9077 * spoolss_deleteprinterdataex
9078 ********************************************************************/
9080 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9082 POLICY_HND *handle = &q_u->handle;
9083 UNISTR2 *value = &q_u->valuename;
9084 UNISTR2 *key = &q_u->keyname;
9086 NT_PRINTER_INFO_LEVEL *printer = NULL;
9088 WERROR status = WERR_OK;
9089 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9090 pstring valuename, keyname;
9092 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9095 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9099 if (!get_printer_snum(p, handle, &snum))
9102 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9103 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9104 return WERR_ACCESS_DENIED;
9107 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9108 if (!W_ERROR_IS_OK(status))
9111 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9112 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9114 status = delete_printer_dataex( printer, keyname, valuename );
9116 if ( W_ERROR_IS_OK(status) )
9117 mod_a_printer( printer, 2 );
9119 free_a_printer(&printer, 2);
9124 /********************************************************************
9125 * spoolss_enumprinterkey
9126 ********************************************************************/
9129 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9132 fstring *keynames = NULL;
9133 uint16 *enumkeys = NULL;
9136 POLICY_HND *handle = &q_u->handle;
9137 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9138 NT_PRINTER_DATA *data;
9139 NT_PRINTER_INFO_LEVEL *printer = NULL;
9141 WERROR status = WERR_BADFILE;
9144 DEBUG(4,("_spoolss_enumprinterkey\n"));
9147 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9151 if ( !get_printer_snum(p,handle, &snum) )
9154 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9155 if (!W_ERROR_IS_OK(status))
9158 /* get the list of subkey names */
9160 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9161 data = &printer->info_2->data;
9163 num_keys = get_printer_subkeys( data, key, &keynames );
9165 if ( num_keys == -1 ) {
9166 status = WERR_BADFILE;
9170 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9172 r_u->needed = printerkey_len*2;
9174 if ( q_u->size < r_u->needed ) {
9175 status = WERR_MORE_DATA;
9179 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9180 status = WERR_NOMEM;
9186 if ( q_u->size < r_u->needed )
9187 status = WERR_MORE_DATA;
9190 free_a_printer( &printer, 2 );
9191 SAFE_FREE( keynames );
9196 /********************************************************************
9197 * spoolss_deleteprinterkey
9198 ********************************************************************/
9200 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9202 POLICY_HND *handle = &q_u->handle;
9203 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9205 NT_PRINTER_INFO_LEVEL *printer = NULL;
9209 DEBUG(5,("spoolss_deleteprinterkey\n"));
9212 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9216 /* if keyname == NULL, return error */
9218 if ( !q_u->keyname.buffer )
9219 return WERR_INVALID_PARAM;
9221 if (!get_printer_snum(p, handle, &snum))
9224 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9225 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9226 return WERR_ACCESS_DENIED;
9229 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9230 if (!W_ERROR_IS_OK(status))
9233 /* delete the key and all subneys */
9235 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9237 status = delete_all_printer_data( printer->info_2, key );
9239 if ( W_ERROR_IS_OK(status) )
9240 status = mod_a_printer(printer, 2);
9242 free_a_printer( &printer, 2 );
9248 /********************************************************************
9249 * spoolss_enumprinterdataex
9250 ********************************************************************/
9252 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9254 POLICY_HND *handle = &q_u->handle;
9255 uint32 in_size = q_u->size;
9258 NT_PRINTER_INFO_LEVEL *printer = NULL;
9259 PRINTER_ENUM_VALUES *enum_values = NULL;
9260 NT_PRINTER_DATA *p_data;
9262 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9267 REGISTRY_VALUE *val;
9272 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9275 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9280 * first check for a keyname of NULL or "". Win2k seems to send
9281 * this a lot and we should send back WERR_INVALID_PARAM
9282 * no need to spend time looking up the printer in this case.
9286 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9287 if ( !strlen(key) ) {
9288 result = WERR_INVALID_PARAM;
9292 /* get the printer off of disk */
9294 if (!get_printer_snum(p,handle, &snum))
9297 ZERO_STRUCT(printer);
9298 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9299 if (!W_ERROR_IS_OK(result))
9302 /* now look for a match on the key name */
9304 p_data = &printer->info_2->data;
9306 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9307 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9309 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9310 result = WERR_INVALID_PARAM;
9317 /* allocate the memory for the array of pointers -- if necessary */
9319 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9322 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9324 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9325 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9326 result = WERR_NOMEM;
9330 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9334 * loop through all params and build the array to pass
9335 * back to the client
9338 for ( i=0; i<num_entries; i++ )
9340 /* lookup the registry value */
9342 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9343 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9347 value_name = regval_name( val );
9348 init_unistr( &enum_values[i].valuename, value_name );
9349 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9350 enum_values[i].type = regval_type( val );
9352 data_len = regval_size( val );
9354 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9356 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9358 result = WERR_NOMEM;
9362 enum_values[i].data_len = data_len;
9364 /* keep track of the size of the array in bytes */
9366 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9369 /* housekeeping information in the reply */
9371 r_u->needed = needed;
9372 r_u->returned = num_entries;
9374 if (needed > in_size) {
9375 result = WERR_MORE_DATA;
9379 /* copy data into the reply */
9381 r_u->ctr.size = r_u->needed;
9382 r_u->ctr.size_of_array = r_u->returned;
9383 r_u->ctr.values = enum_values;
9389 free_a_printer(&printer, 2);
9394 /****************************************************************************
9395 ****************************************************************************/
9397 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9399 init_unistr(&info->name, name);
9402 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9403 UNISTR2 *environment,
9410 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9411 WERROR result = WERR_OK;
9413 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9415 if (!get_short_archi(long_archi))
9416 return WERR_INVALID_ENVIRONMENT;
9418 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9421 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9423 fill_printprocessordirectory_1(info, path);
9425 *needed += spoolss_size_printprocessordirectory_info_1(info);
9427 if (*needed > offered) {
9428 result = WERR_INSUFFICIENT_BUFFER;
9432 if (!rpcbuf_alloc_size(buffer, *needed)) {
9433 result = WERR_INSUFFICIENT_BUFFER;
9437 smb_io_printprocessordirectory_1("", buffer, info, 0);
9445 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9447 uint32 level = q_u->level;
9448 RPC_BUFFER *buffer = NULL;
9449 uint32 offered = q_u->offered;
9450 uint32 *needed = &r_u->needed;
9453 /* that's an [in out] buffer */
9455 if ( q_u->buffer ) {
9456 rpcbuf_move(q_u->buffer, &r_u->buffer);
9457 buffer = r_u->buffer;
9460 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9466 result = getprintprocessordirectory_level_1
9467 (&q_u->name, &q_u->environment, buffer, offered, needed);
9470 result = WERR_UNKNOWN_LEVEL;
9478 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9479 SPOOL_R_REPLYOPENPRINTER *r_u)
9481 DEBUG(5,("_spoolss_replyopenprinter\n"));
9483 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9488 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9489 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9491 DEBUG(5,("_spoolss_replycloseprinter\n"));