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. */
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 /* Table to map the driver version */
44 static const char * drv_ver_to_os[] = {
45 "WIN9X", /* driver version/cversion 0 */
47 "WINNT", /* driver version/cversion 2 */
48 "WIN2K", /* driver version/cversion 3 */
51 static const char *get_drv_ver_to_os(int ver)
53 if (ver < 0 || ver > 3)
55 return drv_ver_to_os[ver];
59 const char *long_archi;
60 const char *short_archi;
64 static Printer_entry *printers_list;
66 typedef struct _counter_printer_0 {
67 struct _counter_printer_0 *next;
68 struct _counter_printer_0 *prev;
74 static counter_printer_0 *counter_list;
76 static struct cli_state notify_cli; /* print notify back-channel */
77 static uint32 smb_connections=0;
80 /* in printing/nt_printing.c */
82 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
84 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
85 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
87 /* translate between internal status numbers and NT status numbers */
88 static int nt_printj_status(int v)
94 return JOB_STATUS_PAUSED;
96 return JOB_STATUS_SPOOLING;
98 return JOB_STATUS_PRINTING;
100 return JOB_STATUS_ERROR;
102 return JOB_STATUS_DELETING;
104 return JOB_STATUS_OFFLINE;
106 return JOB_STATUS_PAPEROUT;
108 return JOB_STATUS_PRINTED;
110 return JOB_STATUS_DELETED;
112 return JOB_STATUS_BLOCKED;
113 case LPQ_USER_INTERVENTION:
114 return JOB_STATUS_USER_INTERVENTION;
119 static int nt_printq_status(int v)
123 return PRINTER_STATUS_PAUSED;
132 /****************************************************************************
133 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
134 ****************************************************************************/
136 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
141 SAFE_FREE((*pp)->ctr.type);
145 /***************************************************************************
146 Disconnect from the client
147 ****************************************************************************/
149 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
154 * Tell the specific printing tdb we no longer want messages for this printer
155 * by deregistering our PID.
158 if (!print_notify_deregister_pid(snum))
159 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
161 /* weird if the test succeds !!! */
162 if (smb_connections==0) {
163 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
167 result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle);
169 if (!W_ERROR_IS_OK(result))
170 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171 dos_errstr(result)));
173 /* if it's the last connection, deconnect the IPC$ share */
174 if (smb_connections==1) {
175 cli_nt_session_close(¬ify_cli);
176 cli_ulogoff(¬ify_cli);
177 cli_shutdown(¬ify_cli);
178 message_deregister(MSG_PRINTER_NOTIFY2);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static void free_printer_entry(void *ptr)
195 Printer_entry *Printer = (Printer_entry *)ptr;
197 if (Printer->notify.client_connected==True) {
200 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
202 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
204 snum = print_queue_snum(Printer->sharename);
206 srv_spoolss_replycloseprinter(snum,
207 &Printer->notify.client_hnd);
211 Printer->notify.flags=0;
212 Printer->notify.options=0;
213 Printer->notify.localmachine[0]='\0';
214 Printer->notify.printerlocal=0;
215 free_spool_notify_option(&Printer->notify.option);
216 Printer->notify.option=NULL;
217 Printer->notify.client_connected=False;
219 free_nt_devicemode( &Printer->nt_devmode );
220 free_a_printer( &Printer->printer_info, 2 );
222 talloc_destroy( Printer->ctx );
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list, Printer);
230 /****************************************************************************
231 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
234 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
236 SPOOL_NOTIFY_OPTION *new_sp = NULL;
241 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
248 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
250 if (!new_sp->ctr.type) {
259 /****************************************************************************
260 find printer index by handle
261 ****************************************************************************/
263 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
265 Printer_entry *find_printer = NULL;
267 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
268 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
275 /****************************************************************************
276 look for a printer object cached on an open printer handle
277 ****************************************************************************/
279 WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2,
280 const char *servername, const char *printername )
284 DEBUG(10,("find_printer_in_print_hnd_cache: printer [\\\\%s\\%s]\n",
285 servername, printername));
287 for ( p=printers_list; p; p=p->next )
289 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
291 && strequal( p->sharename, printername )
292 && strequal( p->servername, servername ) )
294 DEBUG(10,("Found printer\n"));
295 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
301 return WERR_INVALID_PRINTER_NAME;
304 /****************************************************************************
305 destroy any cached printer_info_2 structures on open handles
306 ****************************************************************************/
308 void invalidate_printer_hnd_cache( char *printername )
312 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
314 for ( p=printers_list; p; p=p->next )
316 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
318 && StrCaseCmp(p->sharename, printername)==0)
320 DEBUG(10,("invalidating printer_info cache for handl:\n"));
321 free_a_printer( &p->printer_info, 2 );
322 p->printer_info = NULL;
328 /****************************************************************************
329 Close printer index by handle.
330 ****************************************************************************/
332 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
334 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
337 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
341 close_policy_hnd(p, hnd);
346 /****************************************************************************
347 Delete a printer given a handle.
348 ****************************************************************************/
350 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
355 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
360 * It turns out that Windows allows delete printer on a handle
361 * opened by an admin user, then used on a pipe handle created
362 * by an anonymous user..... but they're working on security.... riiight !
366 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
367 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368 return WERR_ACCESS_DENIED;
372 /* Check calling user has permission to delete printer. Note that
373 since we set the snum parameter to -1 only administrators can
374 delete the printer. This stops people with the Full Control
375 permission from deleting the printer. */
377 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
378 DEBUG(3, ("printer delete denied by security descriptor\n"));
379 return WERR_ACCESS_DENIED;
383 /* this does not need a become root since the access check has been
384 done on the handle already */
386 if (del_a_printer( Printer->sharename ) != 0) {
387 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
391 /* the delete printer script shoudl be run as root if the user has perms */
393 if (*lp_deleteprinter_cmd()) {
395 char *cmd = lp_deleteprinter_cmd();
398 SE_PRIV se_printop = SE_PRINT_OPERATOR;
401 pstr_sprintf(command, "%s \"%s\"", cmd, Printer->sharename);
403 is_print_op = user_has_privileges( p->pipe_user.nt_user_token, &se_printop );
405 DEBUG(10,("Running [%s]\n", command));
407 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
412 if ( (ret = smbrun(command, NULL)) == 0 ) {
413 /* Tell everyone we updated smb.conf. */
414 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
420 /********** END SePrintOperatorPrivlege BLOCK **********/
422 DEBUGADD(10,("returned [%d]\n", ret));
425 return WERR_BADFID; /* What to return here? */
427 /* go ahead and re-read the services immediately */
428 reload_services( False );
430 if ( lp_servicenumber( Printer->sharename ) < 0 )
431 return WERR_ACCESS_DENIED;
437 /****************************************************************************
438 Return the snum of a printer corresponding to an handle.
439 ****************************************************************************/
441 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
443 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
446 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
450 switch (Printer->printer_type) {
451 case PRINTER_HANDLE_IS_PRINTER:
452 DEBUG(4,("short name:%s\n", Printer->sharename));
453 *number = print_queue_snum(Printer->sharename);
454 return (*number != -1);
455 case PRINTER_HANDLE_IS_PRINTSERVER:
462 /****************************************************************************
463 Set printer handle type.
464 Check if it's \\server or \\server\printer
465 ****************************************************************************/
467 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
469 DEBUG(3,("Setting printer type=%s\n", handlename));
471 if ( strlen(handlename) < 3 ) {
472 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
476 /* it's a print server */
477 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
478 DEBUGADD(4,("Printer is a print server\n"));
479 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
483 DEBUGADD(4,("Printer is a printer\n"));
484 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
490 /****************************************************************************
491 Set printer handle name.
492 ****************************************************************************/
494 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
497 int n_services=lp_numservices();
498 char *aprinter, *printername;
499 const char *servername;
502 NT_PRINTER_INFO_LEVEL *printer;
505 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
507 aprinter = handlename;
508 if ( *handlename == '\\' ) {
509 servername = handlename + 2;
510 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
519 /* save the servername to fill in replies on this handle */
521 if ( !is_myname_or_ipaddr( servername ) )
524 fstrcpy( Printer->servername, servername );
526 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
529 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
532 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
534 /* Search all sharenames first as this is easier than pulling
535 the printer_info_2 off of disk */
537 snum = find_service(aprinter);
539 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
541 fstrcpy( sname, aprinter );
544 /* do another loop to look for printernames */
546 for (snum=0; !found && snum<n_services; snum++) {
548 /* no point in checking if this is not a printer or
549 we aren't allowing printername != sharename */
551 if ( !(lp_snum_ok(snum)
553 && !lp_force_printername(snum)) )
558 fstrcpy(sname, lp_servicename(snum));
561 result = get_a_printer( NULL, &printer, 2, sname );
562 if ( !W_ERROR_IS_OK(result) ) {
563 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
564 sname, dos_errstr(result)));
568 /* printername is always returned as \\server\printername */
569 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
570 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
571 printer->info_2->printername));
572 free_a_printer( &printer, 2);
578 if ( strequal(printername, aprinter) ) {
582 DEBUGADD(10, ("printername: %s\n", printername));
584 free_a_printer( &printer, 2);
588 DEBUGADD(4,("Printer not found\n"));
592 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
594 fstrcpy(Printer->sharename, sname);
599 /****************************************************************************
600 Find first available printer slot. creates a printer handle for you.
601 ****************************************************************************/
603 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
605 Printer_entry *new_printer;
607 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
609 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
612 ZERO_STRUCTP(new_printer);
614 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
615 SAFE_FREE(new_printer);
619 /* Add to the internal list. */
620 DLIST_ADD(printers_list, new_printer);
622 new_printer->notify.option=NULL;
624 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
625 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
626 close_printer_handle(p, hnd);
630 if (!set_printer_hnd_printertype(new_printer, name)) {
631 close_printer_handle(p, hnd);
635 if (!set_printer_hnd_name(new_printer, name)) {
636 close_printer_handle(p, hnd);
640 new_printer->access_granted = access_granted;
642 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
647 /***************************************************************************
648 check to see if the client motify handle is monitoring the notification
649 given by (notify_type, notify_field).
650 **************************************************************************/
652 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
658 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
661 SPOOL_NOTIFY_OPTION *option = p->notify.option;
665 * Flags should always be zero when the change notify
666 * is registered by the client's spooler. A user Win32 app
667 * might use the flags though instead of the NOTIFY_OPTION_INFO
676 return is_monitoring_event_flags(
677 p->notify.flags, notify_type, notify_field);
679 for (i = 0; i < option->count; i++) {
681 /* Check match for notify_type */
683 if (option->ctr.type[i].type != notify_type)
686 /* Check match for field */
688 for (j = 0; j < option->ctr.type[i].count; j++) {
689 if (option->ctr.type[i].fields[j] == notify_field) {
695 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
696 p->servername, p->sharename, notify_type, notify_field));
701 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
703 static void notify_one_value(struct spoolss_notify_msg *msg,
704 SPOOL_NOTIFY_INFO_DATA *data,
707 data->notify_data.value[0] = msg->notify.value[0];
708 data->notify_data.value[1] = 0;
711 static void notify_string(struct spoolss_notify_msg *msg,
712 SPOOL_NOTIFY_INFO_DATA *data,
717 /* The length of the message includes the trailing \0 */
719 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
721 data->notify_data.data.length = msg->len * 2;
722 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
724 if (!data->notify_data.data.string) {
725 data->notify_data.data.length = 0;
729 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
732 static void notify_system_time(struct spoolss_notify_msg *msg,
733 SPOOL_NOTIFY_INFO_DATA *data,
739 if (msg->len != sizeof(time_t)) {
740 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
745 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
746 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
750 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
751 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
755 if (!spoolss_io_system_time("", &ps, 0, &systime))
758 data->notify_data.data.length = prs_offset(&ps);
759 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
761 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
766 struct notify2_message_table {
768 void (*fn)(struct spoolss_notify_msg *msg,
769 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
772 static struct notify2_message_table printer_notify_table[] = {
773 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
774 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
775 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
776 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
777 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
778 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
779 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
780 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
781 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
782 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
783 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
784 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
785 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
786 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
787 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
788 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
789 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
790 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
791 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
794 static struct notify2_message_table job_notify_table[] = {
795 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
796 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
797 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
798 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
799 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
800 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
801 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
802 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
803 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
804 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
805 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
806 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
807 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
808 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
809 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
810 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
811 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
812 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
813 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
814 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
815 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
816 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
817 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
818 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
822 /***********************************************************************
823 Allocate talloc context for container object
824 **********************************************************************/
826 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
831 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
836 /***********************************************************************
837 release all allocated memory and zero out structure
838 **********************************************************************/
840 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
846 talloc_destroy(ctr->ctx);
853 /***********************************************************************
854 **********************************************************************/
856 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
864 /***********************************************************************
865 **********************************************************************/
867 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
869 if ( !ctr || !ctr->msg_groups )
872 if ( idx >= ctr->num_groups )
875 return &ctr->msg_groups[idx];
879 /***********************************************************************
880 How many groups of change messages do we have ?
881 **********************************************************************/
883 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
888 return ctr->num_groups;
891 /***********************************************************************
892 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
893 **********************************************************************/
895 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
897 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
898 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
899 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
905 /* loop over all groups looking for a matching printer name */
907 for ( i=0; i<ctr->num_groups; i++ ) {
908 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
912 /* add a new group? */
914 if ( i == ctr->num_groups ) {
917 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
918 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
921 ctr->msg_groups = groups;
923 /* clear the new entry and set the printer name */
925 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
926 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
929 /* add the change messages; 'i' is the correct index now regardless */
931 msg_grp = &ctr->msg_groups[i];
935 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
936 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
939 msg_grp->msgs = msg_list;
941 new_slot = msg_grp->num_msgs-1;
942 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
944 /* need to allocate own copy of data */
947 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
949 return ctr->num_groups;
952 /***********************************************************************
953 Send a change notication message on all handles which have a call
955 **********************************************************************/
957 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
960 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
961 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
962 SPOOLSS_NOTIFY_MSG *messages;
963 int sending_msg_count;
966 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
970 messages = msg_group->msgs;
973 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
977 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
979 /* loop over all printers */
981 for (p = printers_list; p; p = p->next) {
982 SPOOL_NOTIFY_INFO_DATA *data;
987 /* Is there notification on this handle? */
989 if ( !p->notify.client_connected )
992 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
994 /* For this printer? Print servers always receive
997 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
998 ( !strequal(msg_group->printername, p->sharename) ) )
1001 DEBUG(10,("Our printer\n"));
1003 /* allocate the max entries possible */
1005 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
1008 /* build the array of change notifications */
1010 sending_msg_count = 0;
1012 for ( i=0; i<msg_group->num_msgs; i++ ) {
1013 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1015 /* Are we monitoring this event? */
1017 if (!is_monitoring_event(p, msg->type, msg->field))
1020 sending_msg_count++;
1023 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1024 msg->type, msg->field, p->sharename));
1027 * if the is a printer notification handle and not a job notification
1028 * type, then set the id to 0. Other wise just use what was specified
1031 * When registering change notification on a print server handle
1032 * we always need to send back the id (snum) matching the printer
1033 * for which the change took place. For change notify registered
1034 * on a printer handle, this does not matter and the id should be 0.
1039 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1045 /* Convert unix jobid to smb jobid */
1047 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1048 id = sysjob_to_jobid(msg->id);
1051 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1056 construct_info_data( &data[data_len], msg->type, msg->field, id );
1059 case PRINTER_NOTIFY_TYPE:
1060 if ( printer_notify_table[msg->field].fn )
1061 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1064 case JOB_NOTIFY_TYPE:
1065 if ( job_notify_table[msg->field].fn )
1066 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1070 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1077 if ( sending_msg_count ) {
1078 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1079 data_len, data, p->notify.change, 0 );
1084 DEBUG(8,("send_notify2_changes: Exit...\n"));
1088 /***********************************************************************
1089 **********************************************************************/
1091 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1094 uint32 tv_sec, tv_usec;
1097 /* Unpack message */
1099 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1102 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1104 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1107 tdb_unpack((char *)buf + offset, len - offset, "dd",
1108 &msg->notify.value[0], &msg->notify.value[1]);
1110 tdb_unpack((char *)buf + offset, len - offset, "B",
1111 &msg->len, &msg->notify.data);
1113 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1114 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1116 tv->tv_sec = tv_sec;
1117 tv->tv_usec = tv_usec;
1120 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1121 msg->notify.value[1]));
1123 dump_data(3, msg->notify.data, msg->len);
1128 /********************************************************************
1129 Receive a notify2 message list
1130 ********************************************************************/
1132 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1134 size_t msg_count, i;
1135 char *buf = (char *)msg;
1138 SPOOLSS_NOTIFY_MSG notify;
1139 SPOOLSS_NOTIFY_MSG_CTR messages;
1143 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1147 msg_count = IVAL(buf, 0);
1150 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1152 if (msg_count == 0) {
1153 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1157 /* initialize the container */
1159 ZERO_STRUCT( messages );
1160 notify_msg_ctr_init( &messages );
1163 * build message groups for each printer identified
1164 * in a change_notify msg. Remember that a PCN message
1165 * includes the handle returned for the srv_spoolss_replyopenprinter()
1166 * call. Therefore messages are grouped according to printer handle.
1169 for ( i=0; i<msg_count; i++ ) {
1170 struct timeval msg_tv;
1172 if (msg_ptr + 4 - buf > len) {
1173 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1177 msg_len = IVAL(msg_ptr,0);
1180 if (msg_ptr + msg_len - buf > len) {
1181 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1185 /* unpack messages */
1187 ZERO_STRUCT( notify );
1188 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1191 /* add to correct list in container */
1193 notify_msg_ctr_addmsg( &messages, ¬ify );
1195 /* free memory that might have been allocated by notify2_unpack_msg() */
1197 if ( notify.len != 0 )
1198 SAFE_FREE( notify.notify.data );
1201 /* process each group of messages */
1203 num_groups = notify_msg_ctr_numgroups( &messages );
1204 for ( i=0; i<num_groups; i++ )
1205 send_notify2_changes( &messages, i );
1210 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1212 notify_msg_ctr_destroy( &messages );
1217 /********************************************************************
1218 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1219 one smbd, all of processes must clear their printer cache immediately.
1220 ********************************************************************/
1222 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1224 fstring printername;
1226 fstrcpy( printername, buf );
1228 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1230 invalidate_printer_hnd_cache( printername );
1233 /********************************************************************
1234 Send a message to ourself about new driver being installed
1235 so we can upgrade the information for each printer bound to this
1237 ********************************************************************/
1239 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1241 int len = strlen(drivername);
1246 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1249 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1254 /**********************************************************************
1255 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1256 over all printers, upgrading ones as necessary
1257 **********************************************************************/
1259 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1263 int n_services = lp_numservices();
1265 len = MIN(len,sizeof(drivername)-1);
1266 strncpy(drivername, buf, len);
1268 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1270 /* Iterate the printer list */
1272 for (snum=0; snum<n_services; snum++)
1274 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1277 NT_PRINTER_INFO_LEVEL *printer = NULL;
1279 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1280 if (!W_ERROR_IS_OK(result))
1283 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1285 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1287 /* all we care about currently is the change_id */
1289 result = mod_a_printer(printer, 2);
1290 if (!W_ERROR_IS_OK(result)) {
1291 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1292 dos_errstr(result)));
1296 free_a_printer(&printer, 2);
1303 /********************************************************************
1304 Update the cache for all printq's with a registered client
1306 ********************************************************************/
1308 void update_monitored_printq_cache( void )
1310 Printer_entry *printer = printers_list;
1313 /* loop through all printers and update the cache where
1314 client_connected == True */
1317 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1318 && printer->notify.client_connected )
1320 snum = print_queue_snum(printer->sharename);
1321 print_queue_status( snum, NULL, NULL );
1324 printer = printer->next;
1329 /********************************************************************
1330 Send a message to ourself about new driver being installed
1331 so we can upgrade the information for each printer bound to this
1333 ********************************************************************/
1335 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1337 int len = strlen(drivername);
1342 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1345 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1350 /**********************************************************************
1351 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1352 over all printers, resetting printer data as neessary
1353 **********************************************************************/
1355 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1359 int n_services = lp_numservices();
1361 len = MIN( len, sizeof(drivername)-1 );
1362 strncpy( drivername, buf, len );
1364 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1366 /* Iterate the printer list */
1368 for ( snum=0; snum<n_services; snum++ )
1370 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1373 NT_PRINTER_INFO_LEVEL *printer = NULL;
1375 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1376 if ( !W_ERROR_IS_OK(result) )
1380 * if the printer is bound to the driver,
1381 * then reset to the new driver initdata
1384 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1386 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1388 if ( !set_driver_init(printer, 2) ) {
1389 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1390 printer->info_2->printername, printer->info_2->drivername));
1393 result = mod_a_printer( printer, 2 );
1394 if ( !W_ERROR_IS_OK(result) ) {
1395 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1396 get_dos_error_msg(result)));
1400 free_a_printer( &printer, 2 );
1409 /********************************************************************
1410 Copy routines used by convert_to_openprinterex()
1411 *******************************************************************/
1413 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1421 DEBUG (8,("dup_devmode\n"));
1423 /* bulk copy first */
1425 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1429 /* dup the pointer members separately */
1431 len = unistrlen(devmode->devicename.buffer);
1433 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1434 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1439 len = unistrlen(devmode->formname.buffer);
1441 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1442 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1446 d->private = TALLOC_MEMDUP(ctx, devmode->private, devmode->driverextra);
1451 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1453 if (!new_ctr || !ctr)
1456 DEBUG(8,("copy_devmode_ctr\n"));
1458 new_ctr->size = ctr->size;
1459 new_ctr->devmode_ptr = ctr->devmode_ptr;
1461 if(ctr->devmode_ptr)
1462 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1465 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1467 if (!new_def || !def)
1470 DEBUG(8,("copy_printer_defaults\n"));
1472 new_def->datatype_ptr = def->datatype_ptr;
1474 if (def->datatype_ptr)
1475 copy_unistr2(&new_def->datatype, &def->datatype);
1477 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1479 new_def->access_required = def->access_required;
1482 /********************************************************************
1483 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1484 * SPOOL_Q_OPEN_PRINTER_EX structure
1485 ********************************************************************/
1487 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1489 if (!q_u_ex || !q_u)
1492 DEBUG(8,("convert_to_openprinterex\n"));
1494 if ( q_u->printername ) {
1495 q_u_ex->printername = TALLOC_P( ctx, UNISTR2 );
1496 copy_unistr2(q_u_ex->printername, q_u->printername);
1499 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1502 /********************************************************************
1503 * spoolss_open_printer
1505 * called from the spoolss dispatcher
1506 ********************************************************************/
1508 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1510 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1511 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1516 ZERO_STRUCT(q_u_ex);
1517 ZERO_STRUCT(r_u_ex);
1519 /* convert the OpenPrinter() call to OpenPrinterEx() */
1521 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1523 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1525 /* convert back to OpenPrinter() */
1527 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1532 /********************************************************************
1533 * spoolss_open_printer
1535 * If the openprinterex rpc call contains a devmode,
1536 * it's a per-user one. This per-user devmode is derivated
1537 * from the global devmode. Openprinterex() contains a per-user
1538 * devmode for when you do EMF printing and spooling.
1539 * In the EMF case, the NT workstation is only doing half the job
1540 * of rendering the page. The other half is done by running the printer
1541 * driver on the server.
1542 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1543 * The EMF file only contains what is to be printed on the page.
1544 * So in order for the server to know how to print, the NT client sends
1545 * a devicemode attached to the openprinterex call.
1546 * But this devicemode is short lived, it's only valid for the current print job.
1548 * If Samba would have supported EMF spooling, this devicemode would
1549 * have been attached to the handle, to sent it to the driver to correctly
1550 * rasterize the EMF file.
1552 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1553 * we just act as a pass-thru between windows and the printer.
1555 * In order to know that Samba supports only RAW spooling, NT has to call
1556 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1557 * and until NT sends a RAW job, we refuse it.
1559 * But to call getprinter() or startdoc(), you first need a valid handle,
1560 * and to get an handle you have to call openprintex(). Hence why you have
1561 * a devicemode in the openprinterex() call.
1564 * Differences between NT4 and NT 2000.
1567 * On NT4, you only have a global devicemode. This global devicemode can be changed
1568 * by the administrator (or by a user with enough privs). Everytime a user
1569 * wants to print, the devicemode is resetted to the default. In Word, everytime
1570 * you print, the printer's characteristics are always reset to the global devicemode.
1574 * In W2K, there is the notion of per-user devicemode. The first time you use
1575 * a printer, a per-user devicemode is build from the global devicemode.
1576 * If you change your per-user devicemode, it is saved in the registry, under the
1577 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1578 * printer preferences available.
1580 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1581 * on the General Tab of the printer properties windows.
1583 * To change the global devicemode: it's the "Printing Defaults..." button
1584 * on the Advanced Tab of the printer properties window.
1587 ********************************************************************/
1589 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1591 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1592 POLICY_HND *handle = &r_u->handle;
1596 struct current_user user;
1597 Printer_entry *Printer=NULL;
1599 if ( !q_u->printername )
1600 return WERR_INVALID_PRINTER_NAME;
1602 /* some sanity check because you can open a printer or a print server */
1603 /* aka: \\server\printer or \\server */
1605 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1607 DEBUGADD(3,("checking name: %s\n",name));
1609 if (!open_printer_hnd(p, handle, name, 0))
1610 return WERR_INVALID_PRINTER_NAME;
1612 Printer=find_printer_index_by_hnd(p, handle);
1614 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1615 "handle we created for printer %s\n", name ));
1616 close_printer_handle(p,handle);
1617 return WERR_INVALID_PRINTER_NAME;
1620 get_current_user(&user, p);
1623 * First case: the user is opening the print server:
1625 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1626 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1628 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1629 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1630 * or if the user is listed in the smb.conf printer admin parameter.
1632 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1633 * client view printer folder, but does not show the MSAPW.
1635 * Note: this test needs code to check access rights here too. Jeremy
1636 * could you look at this?
1638 * Second case: the user is opening a printer:
1639 * NT doesn't let us connect to a printer if the connecting user
1640 * doesn't have print permission.
1643 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1645 /* Printserver handles use global struct... */
1649 /* Map standard access rights to object specific access rights */
1651 se_map_standard(&printer_default->access_required,
1652 &printserver_std_mapping);
1654 /* Deny any object specific bits that don't apply to print
1655 servers (i.e printer and job specific bits) */
1657 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1659 if (printer_default->access_required &
1660 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1661 DEBUG(3, ("access DENIED for non-printserver bits"));
1662 close_printer_handle(p, handle);
1663 return WERR_ACCESS_DENIED;
1666 /* Allow admin access */
1668 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1670 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1672 if (!lp_ms_add_printer_wizard()) {
1673 close_printer_handle(p, handle);
1674 return WERR_ACCESS_DENIED;
1677 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1678 and not a printer admin, then fail */
1681 && !user_has_privileges( user.nt_user_token, &se_printop )
1682 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1684 close_printer_handle(p, handle);
1685 return WERR_ACCESS_DENIED;
1688 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1692 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1695 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1696 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1698 /* We fall through to return WERR_OK */
1703 /* NT doesn't let us connect to a printer if the connecting user
1704 doesn't have print permission. */
1706 if (!get_printer_snum(p, handle, &snum)) {
1707 close_printer_handle(p, handle);
1711 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1713 /* map an empty access mask to the minimum access mask */
1714 if (printer_default->access_required == 0x0)
1715 printer_default->access_required = PRINTER_ACCESS_USE;
1718 * If we are not serving the printer driver for this printer,
1719 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1720 * will keep NT clients happy --jerry
1723 if (lp_use_client_driver(snum)
1724 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1726 printer_default->access_required = PRINTER_ACCESS_USE;
1729 /* check smb.conf parameters and the the sec_desc */
1731 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1732 DEBUG(3, ("access DENIED for printer open\n"));
1733 close_printer_handle(p, handle);
1734 return WERR_ACCESS_DENIED;
1737 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1738 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1739 close_printer_handle(p, handle);
1740 return WERR_ACCESS_DENIED;
1743 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1744 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1746 printer_default->access_required = PRINTER_ACCESS_USE;
1748 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1749 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1753 Printer->access_granted = printer_default->access_required;
1756 * If the client sent a devmode in the OpenPrinter() call, then
1757 * save it here in case we get a job submission on this handle
1760 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1761 && q_u->printer_default.devmode_cont.devmode_ptr )
1763 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1764 &Printer->nt_devmode );
1767 #if 0 /* JERRY -- I'm doubtful this is really effective */
1768 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1769 optimization in Windows 2000 clients --jerry */
1771 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1772 && (RA_WIN2K == get_remote_arch()) )
1774 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1775 sys_usleep( 500000 );
1782 /****************************************************************************
1783 ****************************************************************************/
1785 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1786 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1792 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1801 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1802 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1808 printer->info_3=NULL;
1809 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1813 printer->info_6=NULL;
1814 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1824 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1825 NT_DEVICEMODE **pp_nt_devmode)
1827 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1830 * Ensure nt_devmode is a valid pointer
1831 * as we will be overwriting it.
1834 if (nt_devmode == NULL) {
1835 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1836 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1840 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1841 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1843 nt_devmode->specversion=devmode->specversion;
1844 nt_devmode->driverversion=devmode->driverversion;
1845 nt_devmode->size=devmode->size;
1846 nt_devmode->fields=devmode->fields;
1847 nt_devmode->orientation=devmode->orientation;
1848 nt_devmode->papersize=devmode->papersize;
1849 nt_devmode->paperlength=devmode->paperlength;
1850 nt_devmode->paperwidth=devmode->paperwidth;
1851 nt_devmode->scale=devmode->scale;
1852 nt_devmode->copies=devmode->copies;
1853 nt_devmode->defaultsource=devmode->defaultsource;
1854 nt_devmode->printquality=devmode->printquality;
1855 nt_devmode->color=devmode->color;
1856 nt_devmode->duplex=devmode->duplex;
1857 nt_devmode->yresolution=devmode->yresolution;
1858 nt_devmode->ttoption=devmode->ttoption;
1859 nt_devmode->collate=devmode->collate;
1861 nt_devmode->logpixels=devmode->logpixels;
1862 nt_devmode->bitsperpel=devmode->bitsperpel;
1863 nt_devmode->pelswidth=devmode->pelswidth;
1864 nt_devmode->pelsheight=devmode->pelsheight;
1865 nt_devmode->displayflags=devmode->displayflags;
1866 nt_devmode->displayfrequency=devmode->displayfrequency;
1867 nt_devmode->icmmethod=devmode->icmmethod;
1868 nt_devmode->icmintent=devmode->icmintent;
1869 nt_devmode->mediatype=devmode->mediatype;
1870 nt_devmode->dithertype=devmode->dithertype;
1871 nt_devmode->reserved1=devmode->reserved1;
1872 nt_devmode->reserved2=devmode->reserved2;
1873 nt_devmode->panningwidth=devmode->panningwidth;
1874 nt_devmode->panningheight=devmode->panningheight;
1877 * Only change private and driverextra if the incoming devmode
1878 * has a new one. JRA.
1881 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1882 SAFE_FREE(nt_devmode->private);
1883 nt_devmode->driverextra=devmode->driverextra;
1884 if((nt_devmode->private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1886 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1889 *pp_nt_devmode = nt_devmode;
1894 /********************************************************************
1895 * _spoolss_enddocprinter_internal.
1896 ********************************************************************/
1898 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1900 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1904 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1908 if (!get_printer_snum(p, handle, &snum))
1911 Printer->document_started=False;
1912 print_job_end(snum, Printer->jobid,True);
1913 /* error codes unhandled so far ... */
1918 /********************************************************************
1919 * api_spoolss_closeprinter
1920 ********************************************************************/
1922 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1924 POLICY_HND *handle = &q_u->handle;
1926 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1928 if (Printer && Printer->document_started)
1929 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1931 if (!close_printer_handle(p, handle))
1934 /* clear the returned printer handle. Observed behavior
1935 from Win2k server. Don't think this really matters.
1936 Previous code just copied the value of the closed
1939 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1944 /********************************************************************
1945 * api_spoolss_deleteprinter
1947 ********************************************************************/
1949 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1951 POLICY_HND *handle = &q_u->handle;
1952 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1955 if (Printer && Printer->document_started)
1956 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1958 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1960 result = delete_printer_handle(p, handle);
1962 update_c_setprinter(False);
1967 /*******************************************************************
1968 * static function to lookup the version id corresponding to an
1969 * long architecture string
1970 ******************************************************************/
1972 static int get_version_id (char * arch)
1975 struct table_node archi_table[]= {
1977 {"Windows 4.0", "WIN40", 0 },
1978 {"Windows NT x86", "W32X86", 2 },
1979 {"Windows NT R4000", "W32MIPS", 2 },
1980 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1981 {"Windows NT PowerPC", "W32PPC", 2 },
1982 {"Windows IA64", "IA64", 3 },
1983 {"Windows x64", "x64", 3 },
1987 for (i=0; archi_table[i].long_archi != NULL; i++)
1989 if (strcmp(arch, archi_table[i].long_archi) == 0)
1990 return (archi_table[i].version);
1996 /********************************************************************
1997 * _spoolss_deleteprinterdriver
1998 ********************************************************************/
2000 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2004 NT_PRINTER_DRIVER_INFO_LEVEL info;
2005 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2007 struct current_user user;
2009 WERROR status_win2k = WERR_ACCESS_DENIED;
2011 get_current_user(&user, p);
2013 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2014 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2016 /* check that we have a valid driver name first */
2018 if ((version=get_version_id(arch)) == -1)
2019 return WERR_INVALID_ENVIRONMENT;
2022 ZERO_STRUCT(info_win2k);
2024 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2026 /* try for Win2k driver if "Windows NT x86" */
2028 if ( version == 2 ) {
2030 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2031 status = WERR_UNKNOWN_PRINTER_DRIVER;
2035 /* otherwise it was a failure */
2037 status = WERR_UNKNOWN_PRINTER_DRIVER;
2043 if (printer_driver_in_use(info.info_3)) {
2044 status = WERR_PRINTER_DRIVER_IN_USE;
2050 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2052 /* if we get to here, we now have 2 driver info structures to remove */
2053 /* remove the Win2k driver first*/
2055 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2056 free_a_printer_driver( info_win2k, 3 );
2058 /* this should not have failed---if it did, report to client */
2059 if ( !W_ERROR_IS_OK(status_win2k) )
2064 status = delete_printer_driver(info.info_3, &user, version, False);
2066 /* if at least one of the deletes succeeded return OK */
2068 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2072 free_a_printer_driver( info, 3 );
2077 /********************************************************************
2078 * spoolss_deleteprinterdriverex
2079 ********************************************************************/
2081 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2085 NT_PRINTER_DRIVER_INFO_LEVEL info;
2086 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2088 uint32 flags = q_u->delete_flags;
2090 struct current_user user;
2092 WERROR status_win2k = WERR_ACCESS_DENIED;
2094 get_current_user(&user, p);
2096 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2097 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2099 /* check that we have a valid driver name first */
2100 if ((version=get_version_id(arch)) == -1) {
2101 /* this is what NT returns */
2102 return WERR_INVALID_ENVIRONMENT;
2105 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2106 version = q_u->version;
2109 ZERO_STRUCT(info_win2k);
2111 status = get_a_printer_driver(&info, 3, driver, arch, version);
2113 if ( !W_ERROR_IS_OK(status) )
2116 * if the client asked for a specific version,
2117 * or this is something other than Windows NT x86,
2121 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2124 /* try for Win2k driver if "Windows NT x86" */
2127 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2128 status = WERR_UNKNOWN_PRINTER_DRIVER;
2133 if ( printer_driver_in_use(info.info_3) ) {
2134 status = WERR_PRINTER_DRIVER_IN_USE;
2139 * we have a couple of cases to consider.
2140 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2141 * then the delete should fail if **any** files overlap with
2143 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2144 * non-overlapping files
2145 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2146 * is set, the do not delete any files
2147 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2150 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2152 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2154 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2155 /* no idea of the correct error here */
2156 status = WERR_ACCESS_DENIED;
2161 /* also check for W32X86/3 if necessary; maybe we already have? */
2163 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2164 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2167 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2168 /* no idea of the correct error here */
2169 free_a_printer_driver( info_win2k, 3 );
2170 status = WERR_ACCESS_DENIED;
2174 /* if we get to here, we now have 2 driver info structures to remove */
2175 /* remove the Win2k driver first*/
2177 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2178 free_a_printer_driver( info_win2k, 3 );
2180 /* this should not have failed---if it did, report to client */
2182 if ( !W_ERROR_IS_OK(status_win2k) )
2187 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2189 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2192 free_a_printer_driver( info, 3 );
2198 /****************************************************************************
2199 Internal routine for retreiving printerdata
2200 ***************************************************************************/
2202 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2203 const char *key, const char *value, uint32 *type, uint8 **data,
2204 uint32 *needed, uint32 in_size )
2206 REGISTRY_VALUE *val;
2209 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2210 return WERR_BADFILE;
2212 *type = regval_type( val );
2214 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2216 size = regval_size( val );
2218 /* copy the min(in_size, len) */
2221 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2223 /* special case for 0 length values */
2225 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2229 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2238 DEBUG(5,("get_printer_dataex: copy done\n"));
2243 /****************************************************************************
2244 Internal routine for removing printerdata
2245 ***************************************************************************/
2247 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2249 return delete_printer_data( printer->info_2, key, value );
2252 /****************************************************************************
2253 Internal routine for storing printerdata
2254 ***************************************************************************/
2256 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2257 uint32 type, uint8 *data, int real_len )
2259 delete_printer_data( printer->info_2, key, value );
2261 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2264 /********************************************************************
2265 GetPrinterData on a printer server Handle.
2266 ********************************************************************/
2268 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2272 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2274 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2276 if((*data = (uint8 *)TALLOC_ZERO(ctx, 4*sizeof(uint8) )) == NULL)
2282 if (!StrCaseCmp(value, "BeepEnabled")) {
2284 if((*data = (uint8 *)TALLOC(ctx, 4*sizeof(uint8) )) == NULL)
2286 SIVAL(*data, 0, 0x00);
2291 if (!StrCaseCmp(value, "EventLog")) {
2293 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2295 /* formally was 0x1b */
2296 SIVAL(*data, 0, 0x0);
2301 if (!StrCaseCmp(value, "NetPopup")) {
2303 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2305 SIVAL(*data, 0, 0x00);
2310 if (!StrCaseCmp(value, "MajorVersion")) {
2312 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2315 /* Windows NT 4.0 seems to not allow uploading of drivers
2316 to a server that reports 0x3 as the MajorVersion.
2317 need to investigate more how Win2k gets around this .
2320 if ( RA_WINNT == get_remote_arch() )
2329 if (!StrCaseCmp(value, "MinorVersion")) {
2331 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2339 * uint32 size = 0x114
2341 * uint32 minor = [0|1]
2342 * uint32 build = [2195|2600]
2343 * extra unicode string = e.g. "Service Pack 3"
2345 if (!StrCaseCmp(value, "OSVersion")) {
2349 if((*data = (uint8 *)TALLOC(ctx, *needed)) == NULL)
2351 ZERO_STRUCTP( *data );
2353 SIVAL(*data, 0, *needed); /* size */
2354 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2356 SIVAL(*data, 12, 2195); /* build */
2358 /* leave extra string empty */
2364 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2365 const char *string="C:\\PRINTERS";
2367 *needed = 2*(strlen(string)+1);
2368 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2370 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2372 /* it's done by hand ready to go on the wire */
2373 for (i=0; i<strlen(string); i++) {
2374 (*data)[2*i]=string[i];
2375 (*data)[2*i+1]='\0';
2380 if (!StrCaseCmp(value, "Architecture")) {
2381 const char *string="Windows NT x86";
2383 *needed = 2*(strlen(string)+1);
2384 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2386 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2387 for (i=0; i<strlen(string); i++) {
2388 (*data)[2*i]=string[i];
2389 (*data)[2*i+1]='\0';
2394 if (!StrCaseCmp(value, "DsPresent")) {
2396 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2399 /* only show the publish check box if we are a
2400 memeber of a AD domain */
2402 if ( lp_security() == SEC_ADS )
2403 SIVAL(*data, 0, 0x01);
2405 SIVAL(*data, 0, 0x00);
2411 if (!StrCaseCmp(value, "DNSMachineName")) {
2414 if (!get_mydnsfullname(hostname))
2415 return WERR_BADFILE;
2417 *needed = 2*(strlen(hostname)+1);
2418 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2420 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2421 for (i=0; i<strlen(hostname); i++) {
2422 (*data)[2*i]=hostname[i];
2423 (*data)[2*i+1]='\0';
2429 return WERR_BADFILE;
2432 /********************************************************************
2433 * spoolss_getprinterdata
2434 ********************************************************************/
2436 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2438 POLICY_HND *handle = &q_u->handle;
2439 UNISTR2 *valuename = &q_u->valuename;
2440 uint32 in_size = q_u->size;
2441 uint32 *type = &r_u->type;
2442 uint32 *out_size = &r_u->size;
2443 uint8 **data = &r_u->data;
2444 uint32 *needed = &r_u->needed;
2447 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2448 NT_PRINTER_INFO_LEVEL *printer = NULL;
2452 * Reminder: when it's a string, the length is in BYTES
2453 * even if UNICODE is negociated.
2458 *out_size = in_size;
2460 /* in case of problem, return some default values */
2465 DEBUG(4,("_spoolss_getprinterdata\n"));
2468 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2469 status = WERR_BADFID;
2473 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2475 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2476 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2479 if ( !get_printer_snum(p,handle, &snum) ) {
2480 status = WERR_BADFID;
2484 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2485 if ( !W_ERROR_IS_OK(status) )
2488 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2490 if ( strequal(value, "ChangeId") ) {
2492 *needed = sizeof(uint32);
2493 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2494 status = WERR_NOMEM;
2497 SIVAL( *data, 0, printer->info_2->changeid );
2501 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2504 if (*needed > *out_size)
2505 status = WERR_MORE_DATA;
2508 if ( !W_ERROR_IS_OK(status) )
2510 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2512 /* reply this param doesn't exist */
2515 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2517 free_a_printer( &printer, 2 );
2526 /* cleanup & exit */
2529 free_a_printer( &printer, 2 );
2534 /*********************************************************
2535 Connect to the client machine.
2536 **********************************************************/
2538 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2539 struct in_addr *client_ip, const char *remote_machine)
2541 ZERO_STRUCTP(the_cli);
2543 if(cli_initialise(the_cli) == NULL) {
2544 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2548 if ( is_zero_ip(*client_ip) ) {
2549 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2550 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2551 cli_shutdown(the_cli);
2555 if (ismyip(the_cli->dest_ip)) {
2556 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2557 cli_shutdown(the_cli);
2562 the_cli->dest_ip.s_addr = client_ip->s_addr;
2563 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2564 inet_ntoa(*client_ip) ));
2567 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2568 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) ));
2569 cli_shutdown(the_cli);
2573 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2574 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2576 cli_shutdown(the_cli);
2580 the_cli->protocol = PROTOCOL_NT1;
2581 cli_setup_signing_state(the_cli, lp_client_signing());
2583 if (!cli_negprot(the_cli)) {
2584 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2585 cli_shutdown(the_cli);
2589 if (the_cli->protocol != PROTOCOL_NT1) {
2590 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2591 cli_shutdown(the_cli);
2596 * Do an anonymous session setup.
2599 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2600 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2601 cli_shutdown(the_cli);
2605 if (!(the_cli->sec_mode & 1)) {
2606 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2607 cli_shutdown(the_cli);
2611 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2612 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) ));
2613 cli_shutdown(the_cli);
2618 * Ok - we have an anonymous connection to the IPC$ share.
2619 * Now start the NT Domain stuff :-).
2622 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2623 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)));
2624 cli_nt_session_close(the_cli);
2625 cli_ulogoff(the_cli);
2626 cli_shutdown(the_cli);
2633 /***************************************************************************
2634 Connect to the client.
2635 ****************************************************************************/
2637 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2638 uint32 localprinter, uint32 type,
2639 POLICY_HND *handle, struct in_addr *client_ip)
2644 * If it's the first connection, contact the client
2645 * and connect to the IPC$ share anonymously
2647 if (smb_connections==0) {
2648 fstring unix_printer;
2650 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2652 ZERO_STRUCT(notify_cli);
2654 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2657 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2658 /* Tell the connections db we're now interested in printer
2659 * notify messages. */
2660 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2664 * Tell the specific printing tdb we want messages for this printer
2665 * by registering our PID.
2668 if (!print_notify_register_pid(snum))
2669 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2673 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2676 if (!W_ERROR_IS_OK(result))
2677 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2678 dos_errstr(result)));
2680 return (W_ERROR_IS_OK(result));
2683 /********************************************************************
2685 * ReplyFindFirstPrinterChangeNotifyEx
2687 * before replying OK: status=0 a rpc call is made to the workstation
2688 * asking ReplyOpenPrinter
2690 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2691 * called from api_spoolss_rffpcnex
2692 ********************************************************************/
2694 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2696 POLICY_HND *handle = &q_u->handle;
2697 uint32 flags = q_u->flags;
2698 uint32 options = q_u->options;
2699 UNISTR2 *localmachine = &q_u->localmachine;
2700 uint32 printerlocal = q_u->printerlocal;
2702 SPOOL_NOTIFY_OPTION *option = q_u->option;
2703 struct in_addr client_ip;
2705 /* store the notify value in the printer struct */
2707 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2710 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2714 Printer->notify.flags=flags;
2715 Printer->notify.options=options;
2716 Printer->notify.printerlocal=printerlocal;
2718 if (Printer->notify.option)
2719 free_spool_notify_option(&Printer->notify.option);
2721 Printer->notify.option=dup_spool_notify_option(option);
2723 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2724 sizeof(Printer->notify.localmachine)-1);
2726 /* Connect to the client machine and send a ReplyOpenPrinter */
2728 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2730 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2731 !get_printer_snum(p, handle, &snum) )
2734 client_ip.s_addr = inet_addr(p->conn->client_address);
2736 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2737 Printer->notify.printerlocal, 1,
2738 &Printer->notify.client_hnd, &client_ip))
2739 return WERR_SERVER_UNAVAILABLE;
2741 Printer->notify.client_connected=True;
2746 /*******************************************************************
2747 * fill a notify_info_data with the servername
2748 ********************************************************************/
2750 void spoolss_notify_server_name(int snum,
2751 SPOOL_NOTIFY_INFO_DATA *data,
2752 print_queue_struct *queue,
2753 NT_PRINTER_INFO_LEVEL *printer,
2754 TALLOC_CTX *mem_ctx)
2759 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2761 data->notify_data.data.length = len;
2762 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2764 if (!data->notify_data.data.string) {
2765 data->notify_data.data.length = 0;
2769 memcpy(data->notify_data.data.string, temp, len);
2772 /*******************************************************************
2773 * fill a notify_info_data with the printername (not including the servername).
2774 ********************************************************************/
2776 void spoolss_notify_printer_name(int snum,
2777 SPOOL_NOTIFY_INFO_DATA *data,
2778 print_queue_struct *queue,
2779 NT_PRINTER_INFO_LEVEL *printer,
2780 TALLOC_CTX *mem_ctx)
2785 /* the notify name should not contain the \\server\ part */
2786 char *p = strrchr(printer->info_2->printername, '\\');
2789 p = printer->info_2->printername;
2794 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2796 data->notify_data.data.length = len;
2797 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2799 if (!data->notify_data.data.string) {
2800 data->notify_data.data.length = 0;
2804 memcpy(data->notify_data.data.string, temp, len);
2807 /*******************************************************************
2808 * fill a notify_info_data with the servicename
2809 ********************************************************************/
2811 void spoolss_notify_share_name(int snum,
2812 SPOOL_NOTIFY_INFO_DATA *data,
2813 print_queue_struct *queue,
2814 NT_PRINTER_INFO_LEVEL *printer,
2815 TALLOC_CTX *mem_ctx)
2820 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2822 data->notify_data.data.length = len;
2823 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2825 if (!data->notify_data.data.string) {
2826 data->notify_data.data.length = 0;
2830 memcpy(data->notify_data.data.string, temp, len);
2833 /*******************************************************************
2834 * fill a notify_info_data with the port name
2835 ********************************************************************/
2837 void spoolss_notify_port_name(int snum,
2838 SPOOL_NOTIFY_INFO_DATA *data,
2839 print_queue_struct *queue,
2840 NT_PRINTER_INFO_LEVEL *printer,
2841 TALLOC_CTX *mem_ctx)
2846 /* even if it's strange, that's consistant in all the code */
2848 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2850 data->notify_data.data.length = len;
2851 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2853 if (!data->notify_data.data.string) {
2854 data->notify_data.data.length = 0;
2858 memcpy(data->notify_data.data.string, temp, len);
2861 /*******************************************************************
2862 * fill a notify_info_data with the printername
2863 * but it doesn't exist, have to see what to do
2864 ********************************************************************/
2866 void spoolss_notify_driver_name(int snum,
2867 SPOOL_NOTIFY_INFO_DATA *data,
2868 print_queue_struct *queue,
2869 NT_PRINTER_INFO_LEVEL *printer,
2870 TALLOC_CTX *mem_ctx)
2875 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2877 data->notify_data.data.length = len;
2878 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2880 if (!data->notify_data.data.string) {
2881 data->notify_data.data.length = 0;
2885 memcpy(data->notify_data.data.string, temp, len);
2888 /*******************************************************************
2889 * fill a notify_info_data with the comment
2890 ********************************************************************/
2892 void spoolss_notify_comment(int snum,
2893 SPOOL_NOTIFY_INFO_DATA *data,
2894 print_queue_struct *queue,
2895 NT_PRINTER_INFO_LEVEL *printer,
2896 TALLOC_CTX *mem_ctx)
2901 if (*printer->info_2->comment == '\0')
2902 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2904 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2906 data->notify_data.data.length = len;
2907 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2909 if (!data->notify_data.data.string) {
2910 data->notify_data.data.length = 0;
2914 memcpy(data->notify_data.data.string, temp, len);
2917 /*******************************************************************
2918 * fill a notify_info_data with the comment
2919 * location = "Room 1, floor 2, building 3"
2920 ********************************************************************/
2922 void spoolss_notify_location(int snum,
2923 SPOOL_NOTIFY_INFO_DATA *data,
2924 print_queue_struct *queue,
2925 NT_PRINTER_INFO_LEVEL *printer,
2926 TALLOC_CTX *mem_ctx)
2931 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2933 data->notify_data.data.length = len;
2934 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2936 if (!data->notify_data.data.string) {
2937 data->notify_data.data.length = 0;
2941 memcpy(data->notify_data.data.string, temp, len);
2944 /*******************************************************************
2945 * fill a notify_info_data with the device mode
2946 * jfm:xxxx don't to it for know but that's a real problem !!!
2947 ********************************************************************/
2949 static void spoolss_notify_devmode(int snum,
2950 SPOOL_NOTIFY_INFO_DATA *data,
2951 print_queue_struct *queue,
2952 NT_PRINTER_INFO_LEVEL *printer,
2953 TALLOC_CTX *mem_ctx)
2957 /*******************************************************************
2958 * fill a notify_info_data with the separator file name
2959 ********************************************************************/
2961 void spoolss_notify_sepfile(int snum,
2962 SPOOL_NOTIFY_INFO_DATA *data,
2963 print_queue_struct *queue,
2964 NT_PRINTER_INFO_LEVEL *printer,
2965 TALLOC_CTX *mem_ctx)
2970 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2972 data->notify_data.data.length = len;
2973 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2975 if (!data->notify_data.data.string) {
2976 data->notify_data.data.length = 0;
2980 memcpy(data->notify_data.data.string, temp, len);
2983 /*******************************************************************
2984 * fill a notify_info_data with the print processor
2985 * jfm:xxxx return always winprint to indicate we don't do anything to it
2986 ********************************************************************/
2988 void spoolss_notify_print_processor(int snum,
2989 SPOOL_NOTIFY_INFO_DATA *data,
2990 print_queue_struct *queue,
2991 NT_PRINTER_INFO_LEVEL *printer,
2992 TALLOC_CTX *mem_ctx)
2997 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2999 data->notify_data.data.length = len;
3000 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3002 if (!data->notify_data.data.string) {
3003 data->notify_data.data.length = 0;
3007 memcpy(data->notify_data.data.string, temp, len);
3010 /*******************************************************************
3011 * fill a notify_info_data with the print processor options
3012 * jfm:xxxx send an empty string
3013 ********************************************************************/
3015 void spoolss_notify_parameters(int snum,
3016 SPOOL_NOTIFY_INFO_DATA *data,
3017 print_queue_struct *queue,
3018 NT_PRINTER_INFO_LEVEL *printer,
3019 TALLOC_CTX *mem_ctx)
3024 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3026 data->notify_data.data.length = len;
3027 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3029 if (!data->notify_data.data.string) {
3030 data->notify_data.data.length = 0;
3034 memcpy(data->notify_data.data.string, temp, len);
3037 /*******************************************************************
3038 * fill a notify_info_data with the data type
3039 * jfm:xxxx always send RAW as data type
3040 ********************************************************************/
3042 void spoolss_notify_datatype(int snum,
3043 SPOOL_NOTIFY_INFO_DATA *data,
3044 print_queue_struct *queue,
3045 NT_PRINTER_INFO_LEVEL *printer,
3046 TALLOC_CTX *mem_ctx)
3051 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3053 data->notify_data.data.length = len;
3054 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3056 if (!data->notify_data.data.string) {
3057 data->notify_data.data.length = 0;
3061 memcpy(data->notify_data.data.string, temp, len);
3064 /*******************************************************************
3065 * fill a notify_info_data with the security descriptor
3066 * jfm:xxxx send an null pointer to say no security desc
3067 * have to implement security before !
3068 ********************************************************************/
3070 static void spoolss_notify_security_desc(int snum,
3071 SPOOL_NOTIFY_INFO_DATA *data,
3072 print_queue_struct *queue,
3073 NT_PRINTER_INFO_LEVEL *printer,
3074 TALLOC_CTX *mem_ctx)
3076 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3077 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3080 /*******************************************************************
3081 * fill a notify_info_data with the attributes
3082 * jfm:xxxx a samba printer is always shared
3083 ********************************************************************/
3085 void spoolss_notify_attributes(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.value[0] = printer->info_2->attributes;
3092 data->notify_data.value[1] = 0;
3095 /*******************************************************************
3096 * fill a notify_info_data with the priority
3097 ********************************************************************/
3099 static void spoolss_notify_priority(int snum,
3100 SPOOL_NOTIFY_INFO_DATA *data,
3101 print_queue_struct *queue,
3102 NT_PRINTER_INFO_LEVEL *printer,
3103 TALLOC_CTX *mem_ctx)
3105 data->notify_data.value[0] = printer->info_2->priority;
3106 data->notify_data.value[1] = 0;
3109 /*******************************************************************
3110 * fill a notify_info_data with the default priority
3111 ********************************************************************/
3113 static void spoolss_notify_default_priority(int snum,
3114 SPOOL_NOTIFY_INFO_DATA *data,
3115 print_queue_struct *queue,
3116 NT_PRINTER_INFO_LEVEL *printer,
3117 TALLOC_CTX *mem_ctx)
3119 data->notify_data.value[0] = printer->info_2->default_priority;
3120 data->notify_data.value[1] = 0;
3123 /*******************************************************************
3124 * fill a notify_info_data with the start time
3125 ********************************************************************/
3127 static void spoolss_notify_start_time(int snum,
3128 SPOOL_NOTIFY_INFO_DATA *data,
3129 print_queue_struct *queue,
3130 NT_PRINTER_INFO_LEVEL *printer,
3131 TALLOC_CTX *mem_ctx)
3133 data->notify_data.value[0] = printer->info_2->starttime;
3134 data->notify_data.value[1] = 0;
3137 /*******************************************************************
3138 * fill a notify_info_data with the until time
3139 ********************************************************************/
3141 static void spoolss_notify_until_time(int snum,
3142 SPOOL_NOTIFY_INFO_DATA *data,
3143 print_queue_struct *queue,
3144 NT_PRINTER_INFO_LEVEL *printer,
3145 TALLOC_CTX *mem_ctx)
3147 data->notify_data.value[0] = printer->info_2->untiltime;
3148 data->notify_data.value[1] = 0;
3151 /*******************************************************************
3152 * fill a notify_info_data with the status
3153 ********************************************************************/
3155 static void spoolss_notify_status(int snum,
3156 SPOOL_NOTIFY_INFO_DATA *data,
3157 print_queue_struct *queue,
3158 NT_PRINTER_INFO_LEVEL *printer,
3159 TALLOC_CTX *mem_ctx)
3161 print_status_struct status;
3163 print_queue_length(snum, &status);
3164 data->notify_data.value[0]=(uint32) status.status;
3165 data->notify_data.value[1] = 0;
3168 /*******************************************************************
3169 * fill a notify_info_data with the number of jobs queued
3170 ********************************************************************/
3172 void spoolss_notify_cjobs(int snum,
3173 SPOOL_NOTIFY_INFO_DATA *data,
3174 print_queue_struct *queue,
3175 NT_PRINTER_INFO_LEVEL *printer,
3176 TALLOC_CTX *mem_ctx)
3178 data->notify_data.value[0] = print_queue_length(snum, NULL);
3179 data->notify_data.value[1] = 0;
3182 /*******************************************************************
3183 * fill a notify_info_data with the average ppm
3184 ********************************************************************/
3186 static void spoolss_notify_average_ppm(int snum,
3187 SPOOL_NOTIFY_INFO_DATA *data,
3188 print_queue_struct *queue,
3189 NT_PRINTER_INFO_LEVEL *printer,
3190 TALLOC_CTX *mem_ctx)
3192 /* always respond 8 pages per minutes */
3193 /* a little hard ! */
3194 data->notify_data.value[0] = printer->info_2->averageppm;
3195 data->notify_data.value[1] = 0;
3198 /*******************************************************************
3199 * fill a notify_info_data with username
3200 ********************************************************************/
3202 static void spoolss_notify_username(int snum,
3203 SPOOL_NOTIFY_INFO_DATA *data,
3204 print_queue_struct *queue,
3205 NT_PRINTER_INFO_LEVEL *printer,
3206 TALLOC_CTX *mem_ctx)
3211 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3213 data->notify_data.data.length = len;
3214 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3216 if (!data->notify_data.data.string) {
3217 data->notify_data.data.length = 0;
3221 memcpy(data->notify_data.data.string, temp, len);
3224 /*******************************************************************
3225 * fill a notify_info_data with job status
3226 ********************************************************************/
3228 static void spoolss_notify_job_status(int snum,
3229 SPOOL_NOTIFY_INFO_DATA *data,
3230 print_queue_struct *queue,
3231 NT_PRINTER_INFO_LEVEL *printer,
3232 TALLOC_CTX *mem_ctx)
3234 data->notify_data.value[0]=nt_printj_status(queue->status);
3235 data->notify_data.value[1] = 0;
3238 /*******************************************************************
3239 * fill a notify_info_data with job name
3240 ********************************************************************/
3242 static void spoolss_notify_job_name(int snum,
3243 SPOOL_NOTIFY_INFO_DATA *data,
3244 print_queue_struct *queue,
3245 NT_PRINTER_INFO_LEVEL *printer,
3246 TALLOC_CTX *mem_ctx)
3251 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3253 data->notify_data.data.length = len;
3254 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3256 if (!data->notify_data.data.string) {
3257 data->notify_data.data.length = 0;
3261 memcpy(data->notify_data.data.string, temp, len);
3264 /*******************************************************************
3265 * fill a notify_info_data with job status
3266 ********************************************************************/
3268 static void spoolss_notify_job_status_string(int snum,
3269 SPOOL_NOTIFY_INFO_DATA *data,
3270 print_queue_struct *queue,
3271 NT_PRINTER_INFO_LEVEL *printer,
3272 TALLOC_CTX *mem_ctx)
3275 * Now we're returning job status codes we just return a "" here. JRA.
3282 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3285 switch (queue->status) {
3290 p = ""; /* NT provides the paused string */
3299 #endif /* NO LONGER NEEDED. */
3301 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3303 data->notify_data.data.length = len;
3304 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3306 if (!data->notify_data.data.string) {
3307 data->notify_data.data.length = 0;
3311 memcpy(data->notify_data.data.string, temp, len);
3314 /*******************************************************************
3315 * fill a notify_info_data with job time
3316 ********************************************************************/
3318 static void spoolss_notify_job_time(int snum,
3319 SPOOL_NOTIFY_INFO_DATA *data,
3320 print_queue_struct *queue,
3321 NT_PRINTER_INFO_LEVEL *printer,
3322 TALLOC_CTX *mem_ctx)
3324 data->notify_data.value[0]=0x0;
3325 data->notify_data.value[1]=0;
3328 /*******************************************************************
3329 * fill a notify_info_data with job size
3330 ********************************************************************/
3332 static void spoolss_notify_job_size(int snum,
3333 SPOOL_NOTIFY_INFO_DATA *data,
3334 print_queue_struct *queue,
3335 NT_PRINTER_INFO_LEVEL *printer,
3336 TALLOC_CTX *mem_ctx)
3338 data->notify_data.value[0]=queue->size;
3339 data->notify_data.value[1]=0;
3342 /*******************************************************************
3343 * fill a notify_info_data with page info
3344 ********************************************************************/
3345 static void spoolss_notify_total_pages(int snum,
3346 SPOOL_NOTIFY_INFO_DATA *data,
3347 print_queue_struct *queue,
3348 NT_PRINTER_INFO_LEVEL *printer,
3349 TALLOC_CTX *mem_ctx)
3351 data->notify_data.value[0]=queue->page_count;
3352 data->notify_data.value[1]=0;
3355 /*******************************************************************
3356 * fill a notify_info_data with pages printed info.
3357 ********************************************************************/
3358 static void spoolss_notify_pages_printed(int snum,
3359 SPOOL_NOTIFY_INFO_DATA *data,
3360 print_queue_struct *queue,
3361 NT_PRINTER_INFO_LEVEL *printer,
3362 TALLOC_CTX *mem_ctx)
3364 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3365 data->notify_data.value[1]=0;
3368 /*******************************************************************
3369 Fill a notify_info_data with job position.
3370 ********************************************************************/
3372 static void spoolss_notify_job_position(int snum,
3373 SPOOL_NOTIFY_INFO_DATA *data,
3374 print_queue_struct *queue,
3375 NT_PRINTER_INFO_LEVEL *printer,
3376 TALLOC_CTX *mem_ctx)
3378 data->notify_data.value[0]=queue->job;
3379 data->notify_data.value[1]=0;
3382 /*******************************************************************
3383 Fill a notify_info_data with submitted time.
3384 ********************************************************************/
3386 static void spoolss_notify_submitted_time(int snum,
3387 SPOOL_NOTIFY_INFO_DATA *data,
3388 print_queue_struct *queue,
3389 NT_PRINTER_INFO_LEVEL *printer,
3390 TALLOC_CTX *mem_ctx)
3397 t=gmtime(&queue->time);
3399 len = sizeof(SYSTEMTIME);
3401 data->notify_data.data.length = len;
3402 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3404 if (!data->notify_data.data.string) {
3405 data->notify_data.data.length = 0;
3409 make_systemtime(&st, t);
3412 * Systemtime must be linearized as a set of UINT16's.
3413 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3416 p = (char *)data->notify_data.data.string;
3417 SSVAL(p, 0, st.year);
3418 SSVAL(p, 2, st.month);
3419 SSVAL(p, 4, st.dayofweek);
3420 SSVAL(p, 6, st.day);
3421 SSVAL(p, 8, st.hour);
3422 SSVAL(p, 10, st.minute);
3423 SSVAL(p, 12, st.second);
3424 SSVAL(p, 14, st.milliseconds);
3427 struct s_notify_info_data_table
3433 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3434 print_queue_struct *queue,
3435 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3438 /* A table describing the various print notification constants and
3439 whether the notification data is a pointer to a variable sized
3440 buffer, a one value uint32 or a two value uint32. */
3442 static const struct s_notify_info_data_table notify_info_data_table[] =
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3493 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3496 /*******************************************************************
3497 Return the size of info_data structure.
3498 ********************************************************************/
3500 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3504 for (i = 0; i < sizeof(notify_info_data_table); i++)
3506 if ( (notify_info_data_table[i].type == type)
3507 && (notify_info_data_table[i].field == field) )
3509 switch(notify_info_data_table[i].size)
3511 case NOTIFY_ONE_VALUE:
3512 case NOTIFY_TWO_VALUE:
3517 /* The only pointer notify data I have seen on
3518 the wire is the submitted time and this has
3519 the notify size set to 4. -tpot */
3521 case NOTIFY_POINTER:
3524 case NOTIFY_SECDESC:
3530 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3535 /*******************************************************************
3536 Return the type of notify_info_data.
3537 ********************************************************************/
3539 static int type_of_notify_info_data(uint16 type, uint16 field)
3543 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3544 if (notify_info_data_table[i].type == type &&
3545 notify_info_data_table[i].field == field)
3546 return notify_info_data_table[i].size;
3552 /****************************************************************************
3553 ****************************************************************************/
3555 static int search_notify(uint16 type, uint16 field, int *value)
3559 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3560 if (notify_info_data_table[i].type == type &&
3561 notify_info_data_table[i].field == field &&
3562 notify_info_data_table[i].fn != NULL) {
3571 /****************************************************************************
3572 ****************************************************************************/
3574 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3576 info_data->type = type;
3577 info_data->field = field;
3578 info_data->reserved = 0;
3580 info_data->size = size_of_notify_info_data(type, field);
3581 info_data->enc_type = type_of_notify_info_data(type, field);
3588 /*******************************************************************
3590 * fill a notify_info struct with info asked
3592 ********************************************************************/
3594 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3595 snum, SPOOL_NOTIFY_OPTION_TYPE
3596 *option_type, uint32 id,
3597 TALLOC_CTX *mem_ctx)
3603 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3604 NT_PRINTER_INFO_LEVEL *printer = NULL;
3605 print_queue_struct *queue=NULL;
3607 type=option_type->type;
3609 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3610 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3611 option_type->count, lp_servicename(snum)));
3613 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3616 for(field_num=0; field_num<option_type->count; field_num++) {
3617 field = option_type->fields[field_num];
3619 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3621 if (!search_notify(type, field, &j) )
3624 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3625 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3630 current_data = &info->data[info->count];
3632 construct_info_data(current_data, type, field, id);
3634 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3635 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3637 notify_info_data_table[j].fn(snum, current_data, queue,
3643 free_a_printer(&printer, 2);
3647 /*******************************************************************
3649 * fill a notify_info struct with info asked
3651 ********************************************************************/
3653 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3654 SPOOL_NOTIFY_INFO *info,
3655 NT_PRINTER_INFO_LEVEL *printer,
3656 int snum, SPOOL_NOTIFY_OPTION_TYPE
3657 *option_type, uint32 id,
3658 TALLOC_CTX *mem_ctx)
3664 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3666 DEBUG(4,("construct_notify_jobs_info\n"));
3668 type = option_type->type;
3670 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3671 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3672 option_type->count));
3674 for(field_num=0; field_num<option_type->count; field_num++) {
3675 field = option_type->fields[field_num];
3677 if (!search_notify(type, field, &j) )
3680 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3681 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3684 else info->data = tid;
3686 current_data=&(info->data[info->count]);
3688 construct_info_data(current_data, type, field, id);
3689 notify_info_data_table[j].fn(snum, current_data, queue,
3698 * JFM: The enumeration is not that simple, it's even non obvious.
3700 * let's take an example: I want to monitor the PRINTER SERVER for
3701 * the printer's name and the number of jobs currently queued.
3702 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3703 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3705 * I have 3 printers on the back of my server.
3707 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3710 * 1 printer 1 name 1
3711 * 2 printer 1 cjob 1
3712 * 3 printer 2 name 2
3713 * 4 printer 2 cjob 2
3714 * 5 printer 3 name 3
3715 * 6 printer 3 name 3
3717 * that's the print server case, the printer case is even worse.
3720 /*******************************************************************
3722 * enumerate all printers on the printserver
3723 * fill a notify_info struct with info asked
3725 ********************************************************************/
3727 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3728 SPOOL_NOTIFY_INFO *info,
3729 TALLOC_CTX *mem_ctx)
3732 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3733 int n_services=lp_numservices();
3735 SPOOL_NOTIFY_OPTION *option;
3736 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3738 DEBUG(4,("printserver_notify_info\n"));
3743 option=Printer->notify.option;
3748 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3749 sending a ffpcn() request first */
3754 for (i=0; i<option->count; i++) {
3755 option_type=&(option->ctr.type[i]);
3757 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3760 for (snum=0; snum<n_services; snum++)
3762 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3763 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3769 * Debugging information, don't delete.
3772 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3773 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3774 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3776 for (i=0; i<info->count; i++) {
3777 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3778 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3779 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3786 /*******************************************************************
3788 * fill a notify_info struct with info asked
3790 ********************************************************************/
3792 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3793 TALLOC_CTX *mem_ctx)
3796 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3799 SPOOL_NOTIFY_OPTION *option;
3800 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3802 print_queue_struct *queue=NULL;
3803 print_status_struct status;
3805 DEBUG(4,("printer_notify_info\n"));
3810 option=Printer->notify.option;
3816 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3817 sending a ffpcn() request first */
3822 get_printer_snum(p, hnd, &snum);
3824 for (i=0; i<option->count; i++) {
3825 option_type=&option->ctr.type[i];
3827 switch ( option_type->type ) {
3828 case PRINTER_NOTIFY_TYPE:
3829 if(construct_notify_printer_info(Printer, info, snum,
3835 case JOB_NOTIFY_TYPE: {
3836 NT_PRINTER_INFO_LEVEL *printer = NULL;
3838 count = print_queue_status(snum, &queue, &status);
3840 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3843 for (j=0; j<count; j++) {
3844 construct_notify_jobs_info(&queue[j], info,
3851 free_a_printer(&printer, 2);
3861 * Debugging information, don't delete.
3864 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3865 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3866 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3868 for (i=0; i<info->count; i++) {
3869 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3870 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3871 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3877 /********************************************************************
3879 ********************************************************************/
3881 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3883 POLICY_HND *handle = &q_u->handle;
3884 SPOOL_NOTIFY_INFO *info = &r_u->info;
3886 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3887 WERROR result = WERR_BADFID;
3889 /* we always have a NOTIFY_INFO struct */
3893 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3894 OUR_HANDLE(handle)));
3898 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3901 * We are now using the change value, and
3902 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3903 * I don't have a global notification system, I'm sending back all the
3904 * informations even when _NOTHING_ has changed.
3907 /* We need to keep track of the change value to send back in
3908 RRPCN replies otherwise our updates are ignored. */
3910 Printer->notify.fnpcn = True;
3912 if (Printer->notify.client_connected) {
3913 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3914 Printer->notify.change = q_u->change;
3917 /* just ignore the SPOOL_NOTIFY_OPTION */
3919 switch (Printer->printer_type) {
3920 case PRINTER_HANDLE_IS_PRINTSERVER:
3921 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3924 case PRINTER_HANDLE_IS_PRINTER:
3925 result = printer_notify_info(p, handle, info, p->mem_ctx);
3929 Printer->notify.fnpcn = False;
3935 /********************************************************************
3936 * construct_printer_info_0
3937 * fill a printer_info_0 struct
3938 ********************************************************************/
3940 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3944 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3945 counter_printer_0 *session_counter;
3946 uint32 global_counter;
3949 print_status_struct status;
3951 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3954 count = print_queue_length(snum, &status);
3956 /* check if we already have a counter for this printer */
3957 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3958 if (session_counter->snum == snum)
3962 /* it's the first time, add it to the list */
3963 if (session_counter==NULL) {
3964 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3965 free_a_printer(&ntprinter, 2);
3968 ZERO_STRUCTP(session_counter);
3969 session_counter->snum=snum;
3970 session_counter->counter=0;
3971 DLIST_ADD(counter_list, session_counter);
3975 session_counter->counter++;
3978 * the global_counter should be stored in a TDB as it's common to all the clients
3979 * and should be zeroed on samba startup
3981 global_counter=session_counter->counter;
3983 pstrcpy(chaine,ntprinter->info_2->printername);
3985 init_unistr(&printer->printername, chaine);
3987 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3988 init_unistr(&printer->servername, chaine);
3990 printer->cjobs = count;
3991 printer->total_jobs = 0;
3992 printer->total_bytes = 0;
3994 setuptime = (time_t)ntprinter->info_2->setuptime;
3995 t=gmtime(&setuptime);
3997 printer->year = t->tm_year+1900;
3998 printer->month = t->tm_mon+1;
3999 printer->dayofweek = t->tm_wday;
4000 printer->day = t->tm_mday;
4001 printer->hour = t->tm_hour;
4002 printer->minute = t->tm_min;
4003 printer->second = t->tm_sec;
4004 printer->milliseconds = 0;
4006 printer->global_counter = global_counter;
4007 printer->total_pages = 0;
4009 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4010 printer->major_version = 0x0005; /* NT 5 */
4011 printer->build_version = 0x0893; /* build 2195 */
4013 printer->unknown7 = 0x1;
4014 printer->unknown8 = 0x0;
4015 printer->unknown9 = 0x0;
4016 printer->session_counter = session_counter->counter;
4017 printer->unknown11 = 0x0;
4018 printer->printer_errors = 0x0; /* number of print failure */
4019 printer->unknown13 = 0x0;
4020 printer->unknown14 = 0x1;
4021 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4022 printer->unknown16 = 0x0;
4023 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4024 printer->unknown18 = 0x0;
4025 printer->status = nt_printq_status(status.status);
4026 printer->unknown20 = 0x0;
4027 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4028 printer->unknown22 = 0x0;
4029 printer->unknown23 = 0x6; /* 6 ???*/
4030 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4031 printer->unknown25 = 0;
4032 printer->unknown26 = 0;
4033 printer->unknown27 = 0;
4034 printer->unknown28 = 0;
4035 printer->unknown29 = 0;
4037 free_a_printer(&ntprinter,2);
4041 /********************************************************************
4042 * construct_printer_info_1
4043 * fill a printer_info_1 struct
4044 ********************************************************************/
4045 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4049 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4051 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4054 printer->flags=flags;
4056 if (*ntprinter->info_2->comment == '\0') {
4057 init_unistr(&printer->comment, lp_comment(snum));
4058 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4059 ntprinter->info_2->drivername, lp_comment(snum));
4062 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4063 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4064 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4067 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4069 init_unistr(&printer->description, chaine);
4070 init_unistr(&printer->name, chaine2);
4072 free_a_printer(&ntprinter,2);
4077 /****************************************************************************
4078 Free a DEVMODE struct.
4079 ****************************************************************************/
4081 static void free_dev_mode(DEVICEMODE *dev)
4086 SAFE_FREE(dev->private);
4091 /****************************************************************************
4092 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4093 should be valid upon entry
4094 ****************************************************************************/
4096 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4098 if ( !devmode || !ntdevmode )
4101 init_unistr(&devmode->devicename, ntdevmode->devicename);
4103 init_unistr(&devmode->formname, ntdevmode->formname);
4105 devmode->specversion = ntdevmode->specversion;
4106 devmode->driverversion = ntdevmode->driverversion;
4107 devmode->size = ntdevmode->size;
4108 devmode->driverextra = ntdevmode->driverextra;
4109 devmode->fields = ntdevmode->fields;
4111 devmode->orientation = ntdevmode->orientation;
4112 devmode->papersize = ntdevmode->papersize;
4113 devmode->paperlength = ntdevmode->paperlength;
4114 devmode->paperwidth = ntdevmode->paperwidth;
4115 devmode->scale = ntdevmode->scale;
4116 devmode->copies = ntdevmode->copies;
4117 devmode->defaultsource = ntdevmode->defaultsource;
4118 devmode->printquality = ntdevmode->printquality;
4119 devmode->color = ntdevmode->color;
4120 devmode->duplex = ntdevmode->duplex;
4121 devmode->yresolution = ntdevmode->yresolution;
4122 devmode->ttoption = ntdevmode->ttoption;
4123 devmode->collate = ntdevmode->collate;
4124 devmode->icmmethod = ntdevmode->icmmethod;
4125 devmode->icmintent = ntdevmode->icmintent;
4126 devmode->mediatype = ntdevmode->mediatype;
4127 devmode->dithertype = ntdevmode->dithertype;
4129 if (ntdevmode->private != NULL) {
4130 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4137 /****************************************************************************
4138 Create a DEVMODE struct. Returns malloced memory.
4139 ****************************************************************************/
4141 DEVICEMODE *construct_dev_mode(int snum)
4143 NT_PRINTER_INFO_LEVEL *printer = NULL;
4144 DEVICEMODE *devmode = NULL;
4146 DEBUG(7,("construct_dev_mode\n"));
4148 DEBUGADD(8,("getting printer characteristics\n"));
4150 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4153 if ( !printer->info_2->devmode ) {
4154 DEBUG(5, ("BONG! There was no device mode!\n"));
4158 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4159 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4163 ZERO_STRUCTP(devmode);
4165 DEBUGADD(8,("loading DEVICEMODE\n"));
4167 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4168 free_dev_mode( devmode );
4173 free_a_printer(&printer,2);
4178 /********************************************************************
4179 * construct_printer_info_2
4180 * fill a printer_info_2 struct
4181 ********************************************************************/
4183 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4186 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4188 print_status_struct status;
4190 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4193 count = print_queue_length(snum, &status);
4195 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4196 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4197 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4198 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4199 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4201 if (*ntprinter->info_2->comment == '\0')
4202 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4204 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4206 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4207 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4208 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4209 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4210 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4212 printer->attributes = ntprinter->info_2->attributes;
4214 printer->priority = ntprinter->info_2->priority; /* priority */
4215 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4216 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4217 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4218 printer->status = nt_printq_status(status.status); /* status */
4219 printer->cjobs = count; /* jobs */
4220 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4222 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4223 DEBUG(8, ("Returning NULL Devicemode!\n"));
4226 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4227 /* steal the printer info sec_desc structure. [badly done]. */
4228 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4229 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4230 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4231 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4234 printer->secdesc = NULL;
4237 free_a_printer(&ntprinter, 2);
4241 /********************************************************************
4242 * construct_printer_info_3
4243 * fill a printer_info_3 struct
4244 ********************************************************************/
4246 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4248 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4249 PRINTER_INFO_3 *printer = NULL;
4251 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4255 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4256 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4260 ZERO_STRUCTP(printer);
4262 printer->flags = 4; /* These are the components of the SD we are returning. */
4263 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4264 /* steal the printer info sec_desc structure. [badly done]. */
4265 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4269 * Set the flags for the components we are returning.
4272 if (printer->secdesc->owner_sid)
4273 printer->flags |= OWNER_SECURITY_INFORMATION;
4275 if (printer->secdesc->grp_sid)
4276 printer->flags |= GROUP_SECURITY_INFORMATION;
4278 if (printer->secdesc->dacl)
4279 printer->flags |= DACL_SECURITY_INFORMATION;
4281 if (printer->secdesc->sacl)
4282 printer->flags |= SACL_SECURITY_INFORMATION;
4285 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4286 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4287 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4290 free_a_printer(&ntprinter, 2);
4292 *pp_printer = printer;
4296 /********************************************************************
4297 * construct_printer_info_4
4298 * fill a printer_info_4 struct
4299 ********************************************************************/
4301 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4303 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4305 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4308 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4309 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4310 printer->attributes = ntprinter->info_2->attributes;
4312 free_a_printer(&ntprinter, 2);
4316 /********************************************************************
4317 * construct_printer_info_5
4318 * fill a printer_info_5 struct
4319 ********************************************************************/
4321 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4323 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4325 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4328 init_unistr(&printer->printername, ntprinter->info_2->printername);
4329 init_unistr(&printer->portname, ntprinter->info_2->portname);
4330 printer->attributes = ntprinter->info_2->attributes;
4332 /* these two are not used by NT+ according to MSDN */
4334 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4335 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4337 free_a_printer(&ntprinter, 2);
4342 /********************************************************************
4343 * construct_printer_info_7
4344 * fill a printer_info_7 struct
4345 ********************************************************************/
4347 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4349 char *guid_str = NULL;
4352 if (is_printer_published(print_hnd, snum, &guid)) {
4353 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4354 strupper_m(guid_str);
4355 init_unistr(&printer->guid, guid_str);
4356 printer->action = SPOOL_DS_PUBLISH;
4358 init_unistr(&printer->guid, "");
4359 printer->action = SPOOL_DS_UNPUBLISH;
4365 /********************************************************************
4366 Spoolss_enumprinters.
4367 ********************************************************************/
4369 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4373 int n_services=lp_numservices();
4374 PRINTER_INFO_1 *tp, *printers=NULL;
4375 PRINTER_INFO_1 current_prt;
4376 WERROR result = WERR_OK;
4378 DEBUG(4,("enum_all_printers_info_1\n"));
4380 for (snum=0; snum<n_services; snum++) {
4381 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4382 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4384 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4385 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4386 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4387 SAFE_FREE(printers);
4392 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4394 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4400 /* check the required size. */
4401 for (i=0; i<*returned; i++)
4402 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4404 if (*needed > offered) {
4405 result = WERR_INSUFFICIENT_BUFFER;
4409 if (!rpcbuf_alloc_size(buffer, *needed)) {
4410 result = WERR_NOMEM;
4414 /* fill the buffer with the structures */
4415 for (i=0; i<*returned; i++)
4416 smb_io_printer_info_1("", buffer, &printers[i], 0);
4421 SAFE_FREE(printers);
4423 if ( !W_ERROR_IS_OK(result) )
4429 /********************************************************************
4430 enum_all_printers_info_1_local.
4431 *********************************************************************/
4433 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4435 DEBUG(4,("enum_all_printers_info_1_local\n"));
4437 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4440 /********************************************************************
4441 enum_all_printers_info_1_name.
4442 *********************************************************************/
4444 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4448 DEBUG(4,("enum_all_printers_info_1_name\n"));
4450 if ((name[0] == '\\') && (name[1] == '\\'))
4453 if (is_myname_or_ipaddr(s)) {
4454 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4457 return WERR_INVALID_NAME;
4460 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4461 /********************************************************************
4462 enum_all_printers_info_1_remote.
4463 *********************************************************************/
4465 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4467 PRINTER_INFO_1 *printer;
4468 fstring printername;
4471 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4472 WERROR result = WERR_OK;
4474 /* JFM: currently it's more a place holder than anything else.
4475 * In the spooler world there is a notion of server registration.
4476 * the print servers are registered on the PDC (in the same domain)
4478 * We should have a TDB here. The registration is done thru an
4479 * undocumented RPC call.
4482 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4487 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4488 slprintf(desc, sizeof(desc)-1,"%s", name);
4489 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4491 init_unistr(&printer->description, desc);
4492 init_unistr(&printer->name, printername);
4493 init_unistr(&printer->comment, comment);
4494 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4496 /* check the required size. */
4497 *needed += spoolss_size_printer_info_1(printer);
4499 if (*needed > offered) {
4500 result = WERR_INSUFFICIENT_BUFFER;
4504 if (!rpcbuf_alloc_size(buffer, *needed)) {
4505 result = WERR_NOMEM;
4509 /* fill the buffer with the structures */
4510 smb_io_printer_info_1("", buffer, printer, 0);
4516 if ( !W_ERROR_IS_OK(result) )
4524 /********************************************************************
4525 enum_all_printers_info_1_network.
4526 *********************************************************************/
4528 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4532 DEBUG(4,("enum_all_printers_info_1_network\n"));
4534 /* If we respond to a enum_printers level 1 on our name with flags
4535 set to PRINTER_ENUM_REMOTE with a list of printers then these
4536 printers incorrectly appear in the APW browse list.
4537 Specifically the printers for the server appear at the workgroup
4538 level where all the other servers in the domain are
4539 listed. Windows responds to this call with a
4540 WERR_CAN_NOT_COMPLETE so we should do the same. */
4542 if (name[0] == '\\' && name[1] == '\\')
4545 if (is_myname_or_ipaddr(s))
4546 return WERR_CAN_NOT_COMPLETE;
4548 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4551 /********************************************************************
4552 * api_spoolss_enumprinters
4554 * called from api_spoolss_enumprinters (see this to understand)
4555 ********************************************************************/
4557 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4561 int n_services=lp_numservices();
4562 PRINTER_INFO_2 *tp, *printers=NULL;
4563 PRINTER_INFO_2 current_prt;
4564 WERROR result = WERR_OK;
4566 for (snum=0; snum<n_services; snum++) {
4567 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4568 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4570 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4571 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) == NULL) {
4572 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4573 SAFE_FREE(printers);
4578 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4579 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4585 /* check the required size. */
4586 for (i=0; i<*returned; i++)
4587 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4589 if (*needed > offered) {
4590 result = WERR_INSUFFICIENT_BUFFER;
4594 if (!rpcbuf_alloc_size(buffer, *needed)) {
4595 result = WERR_NOMEM;
4599 /* fill the buffer with the structures */
4600 for (i=0; i<*returned; i++)
4601 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4605 for (i=0; i<*returned; i++) {
4606 free_devmode(printers[i].devmode);
4608 SAFE_FREE(printers);
4610 if ( !W_ERROR_IS_OK(result) )
4616 /********************************************************************
4617 * handle enumeration of printers at level 1
4618 ********************************************************************/
4620 static WERROR enumprinters_level1( uint32 flags, fstring name,
4621 RPC_BUFFER *buffer, uint32 offered,
4622 uint32 *needed, uint32 *returned)
4624 /* Not all the flags are equals */
4626 if (flags & PRINTER_ENUM_LOCAL)
4627 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4629 if (flags & PRINTER_ENUM_NAME)
4630 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4632 #if 0 /* JERRY - disabled for now */
4633 if (flags & PRINTER_ENUM_REMOTE)
4634 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4637 if (flags & PRINTER_ENUM_NETWORK)
4638 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4640 return WERR_OK; /* NT4sp5 does that */
4643 /********************************************************************
4644 * handle enumeration of printers at level 2
4645 ********************************************************************/
4647 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4648 RPC_BUFFER *buffer, uint32 offered,
4649 uint32 *needed, uint32 *returned)
4651 char *s = servername;
4653 if (flags & PRINTER_ENUM_LOCAL) {
4654 return enum_all_printers_info_2(buffer, offered, needed, returned);
4657 if (flags & PRINTER_ENUM_NAME) {
4658 if ((servername[0] == '\\') && (servername[1] == '\\'))
4660 if (is_myname_or_ipaddr(s))
4661 return enum_all_printers_info_2(buffer, offered, needed, returned);
4663 return WERR_INVALID_NAME;
4666 if (flags & PRINTER_ENUM_REMOTE)
4667 return WERR_UNKNOWN_LEVEL;
4672 /********************************************************************
4673 * handle enumeration of printers at level 5
4674 ********************************************************************/
4676 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4677 RPC_BUFFER *buffer, uint32 offered,
4678 uint32 *needed, uint32 *returned)
4680 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4684 /********************************************************************
4685 * api_spoolss_enumprinters
4687 * called from api_spoolss_enumprinters (see this to understand)
4688 ********************************************************************/
4690 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4692 uint32 flags = q_u->flags;
4693 UNISTR2 *servername = &q_u->servername;
4694 uint32 level = q_u->level;
4695 RPC_BUFFER *buffer = NULL;
4696 uint32 offered = q_u->offered;
4697 uint32 *needed = &r_u->needed;
4698 uint32 *returned = &r_u->returned;
4702 /* that's an [in out] buffer */
4704 if ( q_u->buffer ) {
4705 rpcbuf_move(q_u->buffer, &r_u->buffer);
4706 buffer = r_u->buffer;
4709 DEBUG(4,("_spoolss_enumprinters\n"));
4716 * flags==PRINTER_ENUM_NAME
4717 * if name=="" then enumerates all printers
4718 * if name!="" then enumerate the printer
4719 * flags==PRINTER_ENUM_REMOTE
4720 * name is NULL, enumerate printers
4721 * Level 2: name!="" enumerates printers, name can't be NULL
4722 * Level 3: doesn't exist
4723 * Level 4: does a local registry lookup
4724 * Level 5: same as Level 2
4727 unistr2_to_ascii(name, servername, sizeof(name)-1);
4732 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4734 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4736 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4741 return WERR_UNKNOWN_LEVEL;
4744 /****************************************************************************
4745 ****************************************************************************/
4747 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4749 PRINTER_INFO_0 *printer=NULL;
4750 WERROR result = WERR_OK;
4752 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4755 construct_printer_info_0(print_hnd, printer, snum);
4757 /* check the required size. */
4758 *needed += spoolss_size_printer_info_0(printer);
4760 if (*needed > offered) {
4761 result = WERR_INSUFFICIENT_BUFFER;
4765 if (!rpcbuf_alloc_size(buffer, *needed)) {
4766 result = WERR_NOMEM;
4770 /* fill the buffer with the structures */
4771 smb_io_printer_info_0("", buffer, printer, 0);
4781 /****************************************************************************
4782 ****************************************************************************/
4784 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4786 PRINTER_INFO_1 *printer=NULL;
4787 WERROR result = WERR_OK;
4789 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4792 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4794 /* check the required size. */
4795 *needed += spoolss_size_printer_info_1(printer);
4797 if (*needed > offered) {
4798 result = WERR_INSUFFICIENT_BUFFER;
4802 if (!rpcbuf_alloc_size(buffer, *needed)) {
4803 result = WERR_NOMEM;
4807 /* fill the buffer with the structures */
4808 smb_io_printer_info_1("", buffer, printer, 0);
4817 /****************************************************************************
4818 ****************************************************************************/
4820 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4822 PRINTER_INFO_2 *printer=NULL;
4823 WERROR result = WERR_OK;
4825 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4828 construct_printer_info_2(print_hnd, printer, snum);
4830 /* check the required size. */
4831 *needed += spoolss_size_printer_info_2(printer);
4833 if (*needed > offered) {
4834 result = WERR_INSUFFICIENT_BUFFER;
4838 if (!rpcbuf_alloc_size(buffer, *needed)) {
4839 result = WERR_NOMEM;
4843 /* fill the buffer with the structures */
4844 if (!smb_io_printer_info_2("", buffer, printer, 0))
4845 result = WERR_NOMEM;
4849 free_printer_info_2(printer);
4854 /****************************************************************************
4855 ****************************************************************************/
4857 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4859 PRINTER_INFO_3 *printer=NULL;
4860 WERROR result = WERR_OK;
4862 if (!construct_printer_info_3(print_hnd, &printer, snum))
4865 /* check the required size. */
4866 *needed += spoolss_size_printer_info_3(printer);
4868 if (*needed > offered) {
4869 result = WERR_INSUFFICIENT_BUFFER;
4873 if (!rpcbuf_alloc_size(buffer, *needed)) {
4874 result = WERR_NOMEM;
4878 /* fill the buffer with the structures */
4879 smb_io_printer_info_3("", buffer, printer, 0);
4883 free_printer_info_3(printer);
4888 /****************************************************************************
4889 ****************************************************************************/
4891 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4893 PRINTER_INFO_4 *printer=NULL;
4894 WERROR result = WERR_OK;
4896 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4899 if (!construct_printer_info_4(print_hnd, printer, snum))
4902 /* check the required size. */
4903 *needed += spoolss_size_printer_info_4(printer);
4905 if (*needed > offered) {
4906 result = WERR_INSUFFICIENT_BUFFER;
4910 if (!rpcbuf_alloc_size(buffer, *needed)) {
4911 result = WERR_NOMEM;
4915 /* fill the buffer with the structures */
4916 smb_io_printer_info_4("", buffer, printer, 0);
4920 free_printer_info_4(printer);
4925 /****************************************************************************
4926 ****************************************************************************/
4928 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4930 PRINTER_INFO_5 *printer=NULL;
4931 WERROR result = WERR_OK;
4933 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4936 if (!construct_printer_info_5(print_hnd, printer, snum))
4939 /* check the required size. */
4940 *needed += spoolss_size_printer_info_5(printer);
4942 if (*needed > offered) {
4943 result = WERR_INSUFFICIENT_BUFFER;
4947 if (!rpcbuf_alloc_size(buffer, *needed)) {
4948 result = WERR_NOMEM;
4952 /* fill the buffer with the structures */
4953 smb_io_printer_info_5("", buffer, printer, 0);
4957 free_printer_info_5(printer);
4962 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4964 PRINTER_INFO_7 *printer=NULL;
4965 WERROR result = WERR_OK;
4967 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4970 if (!construct_printer_info_7(print_hnd, printer, snum))
4973 /* check the required size. */
4974 *needed += spoolss_size_printer_info_7(printer);
4976 if (*needed > offered) {
4977 result = WERR_INSUFFICIENT_BUFFER;
4981 if (!rpcbuf_alloc_size(buffer, *needed)) {
4982 result = WERR_NOMEM;
4987 /* fill the buffer with the structures */
4988 smb_io_printer_info_7("", buffer, printer, 0);
4992 free_printer_info_7(printer);
4997 /****************************************************************************
4998 ****************************************************************************/
5000 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5002 POLICY_HND *handle = &q_u->handle;
5003 uint32 level = q_u->level;
5004 RPC_BUFFER *buffer = NULL;
5005 uint32 offered = q_u->offered;
5006 uint32 *needed = &r_u->needed;
5007 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5011 /* that's an [in out] buffer */
5013 if ( q_u->buffer ) {
5014 rpcbuf_move(q_u->buffer, &r_u->buffer);
5015 buffer = r_u->buffer;
5020 if (!get_printer_snum(p, handle, &snum))
5025 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5027 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5029 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5031 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5033 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5035 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5037 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5039 return WERR_UNKNOWN_LEVEL;
5042 /********************************************************************
5043 * fill a DRIVER_INFO_1 struct
5044 ********************************************************************/
5046 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5048 init_unistr( &info->name, driver.info_3->name);
5051 /********************************************************************
5052 * construct_printer_driver_info_1
5053 ********************************************************************/
5055 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5057 NT_PRINTER_INFO_LEVEL *printer = NULL;
5058 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5060 ZERO_STRUCT(driver);
5062 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5063 return WERR_INVALID_PRINTER_NAME;
5065 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5066 return WERR_UNKNOWN_PRINTER_DRIVER;
5068 fill_printer_driver_info_1(info, driver, servername, architecture);
5070 free_a_printer(&printer,2);
5075 /********************************************************************
5076 * construct_printer_driver_info_2
5077 * fill a printer_info_2 struct
5078 ********************************************************************/
5080 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5084 info->version=driver.info_3->cversion;
5086 init_unistr( &info->name, driver.info_3->name );
5087 init_unistr( &info->architecture, driver.info_3->environment );
5090 if (strlen(driver.info_3->driverpath)) {
5091 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5092 init_unistr( &info->driverpath, temp );
5094 init_unistr( &info->driverpath, "" );
5096 if (strlen(driver.info_3->datafile)) {
5097 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5098 init_unistr( &info->datafile, temp );
5100 init_unistr( &info->datafile, "" );
5102 if (strlen(driver.info_3->configfile)) {
5103 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5104 init_unistr( &info->configfile, temp );
5106 init_unistr( &info->configfile, "" );
5109 /********************************************************************
5110 * construct_printer_driver_info_2
5111 * fill a printer_info_2 struct
5112 ********************************************************************/
5114 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5116 NT_PRINTER_INFO_LEVEL *printer = NULL;
5117 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5119 ZERO_STRUCT(printer);
5120 ZERO_STRUCT(driver);
5122 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5123 return WERR_INVALID_PRINTER_NAME;
5125 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5126 return WERR_UNKNOWN_PRINTER_DRIVER;
5128 fill_printer_driver_info_2(info, driver, servername);
5130 free_a_printer(&printer,2);
5135 /********************************************************************
5136 * copy a strings array and convert to UNICODE
5138 * convert an array of ascii string to a UNICODE string
5139 ********************************************************************/
5141 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5149 DEBUG(6,("init_unistr_array\n"));
5160 v = ""; /* hack to handle null lists */
5163 /* hack to allow this to be used in places other than when generating
5164 the list of dependent files */
5167 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5171 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5173 /* add one extra unit16 for the second terminating NULL */
5175 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5176 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5184 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5189 /* special case for ""; we need to add both NULL's here */
5191 (*uni_array)[j++]=0x0000;
5192 (*uni_array)[j]=0x0000;
5195 DEBUGADD(6,("last one:done\n"));
5197 /* return size of array in uint16's */
5202 /********************************************************************
5203 * construct_printer_info_3
5204 * fill a printer_info_3 struct
5205 ********************************************************************/
5207 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5213 info->version=driver.info_3->cversion;
5215 init_unistr( &info->name, driver.info_3->name );
5216 init_unistr( &info->architecture, driver.info_3->environment );
5218 if (strlen(driver.info_3->driverpath)) {
5219 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5220 init_unistr( &info->driverpath, temp );
5222 init_unistr( &info->driverpath, "" );
5224 if (strlen(driver.info_3->datafile)) {
5225 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5226 init_unistr( &info->datafile, temp );
5228 init_unistr( &info->datafile, "" );
5230 if (strlen(driver.info_3->configfile)) {
5231 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5232 init_unistr( &info->configfile, temp );
5234 init_unistr( &info->configfile, "" );
5236 if (strlen(driver.info_3->helpfile)) {
5237 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5238 init_unistr( &info->helpfile, temp );
5240 init_unistr( &info->helpfile, "" );
5242 init_unistr( &info->monitorname, driver.info_3->monitorname );
5243 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5245 info->dependentfiles=NULL;
5246 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5249 /********************************************************************
5250 * construct_printer_info_3
5251 * fill a printer_info_3 struct
5252 ********************************************************************/
5254 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5256 NT_PRINTER_INFO_LEVEL *printer = NULL;
5257 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5259 ZERO_STRUCT(driver);
5261 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5262 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5263 if (!W_ERROR_IS_OK(status))
5264 return WERR_INVALID_PRINTER_NAME;
5266 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5267 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5272 * I put this code in during testing. Helpful when commenting out the
5273 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5274 * as win2k always queries the driver using an infor level of 6.
5275 * I've left it in (but ifdef'd out) because I'll probably
5276 * use it in experimentation again in the future. --jerry 22/01/2002
5279 if (!W_ERROR_IS_OK(status)) {
5281 * Is this a W2k client ?
5284 /* Yes - try again with a WinNT driver. */
5286 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5287 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5291 if (!W_ERROR_IS_OK(status)) {
5292 free_a_printer(&printer,2);
5293 return WERR_UNKNOWN_PRINTER_DRIVER;
5301 fill_printer_driver_info_3(info, driver, servername);
5303 free_a_printer(&printer,2);
5308 /********************************************************************
5309 * construct_printer_info_6
5310 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5311 ********************************************************************/
5313 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5319 memset(&nullstr, '\0', sizeof(fstring));
5321 info->version=driver.info_3->cversion;
5323 init_unistr( &info->name, driver.info_3->name );
5324 init_unistr( &info->architecture, driver.info_3->environment );
5326 if (strlen(driver.info_3->driverpath)) {
5327 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5328 init_unistr( &info->driverpath, temp );
5330 init_unistr( &info->driverpath, "" );
5332 if (strlen(driver.info_3->datafile)) {
5333 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5334 init_unistr( &info->datafile, temp );
5336 init_unistr( &info->datafile, "" );
5338 if (strlen(driver.info_3->configfile)) {
5339 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5340 init_unistr( &info->configfile, temp );
5342 init_unistr( &info->configfile, "" );
5344 if (strlen(driver.info_3->helpfile)) {
5345 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5346 init_unistr( &info->helpfile, temp );
5348 init_unistr( &info->helpfile, "" );
5350 init_unistr( &info->monitorname, driver.info_3->monitorname );
5351 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5353 info->dependentfiles = NULL;
5354 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5356 info->previousdrivernames=NULL;
5357 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5359 info->driver_date.low=0;
5360 info->driver_date.high=0;
5363 info->driver_version_low=0;
5364 info->driver_version_high=0;
5366 init_unistr( &info->mfgname, "");
5367 init_unistr( &info->oem_url, "");
5368 init_unistr( &info->hardware_id, "");
5369 init_unistr( &info->provider, "");
5372 /********************************************************************
5373 * construct_printer_info_6
5374 * fill a printer_info_6 struct
5375 ********************************************************************/
5377 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5378 fstring servername, fstring architecture, uint32 version)
5380 NT_PRINTER_INFO_LEVEL *printer = NULL;
5381 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5384 ZERO_STRUCT(driver);
5386 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5388 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5390 if (!W_ERROR_IS_OK(status))
5391 return WERR_INVALID_PRINTER_NAME;
5393 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5395 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5397 if (!W_ERROR_IS_OK(status))
5400 * Is this a W2k client ?
5404 free_a_printer(&printer,2);
5405 return WERR_UNKNOWN_PRINTER_DRIVER;
5408 /* Yes - try again with a WinNT driver. */
5410 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5411 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5412 if (!W_ERROR_IS_OK(status)) {
5413 free_a_printer(&printer,2);
5414 return WERR_UNKNOWN_PRINTER_DRIVER;
5418 fill_printer_driver_info_6(info, driver, servername);
5420 free_a_printer(&printer,2);
5421 free_a_printer_driver(driver, 3);
5426 /****************************************************************************
5427 ****************************************************************************/
5429 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5431 SAFE_FREE(info->dependentfiles);
5434 /****************************************************************************
5435 ****************************************************************************/
5437 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5439 SAFE_FREE(info->dependentfiles);
5442 /****************************************************************************
5443 ****************************************************************************/
5445 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5447 DRIVER_INFO_1 *info=NULL;
5450 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5453 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5454 if (!W_ERROR_IS_OK(result))
5457 /* check the required size. */
5458 *needed += spoolss_size_printer_driver_info_1(info);
5460 if (*needed > offered) {
5461 result = WERR_INSUFFICIENT_BUFFER;
5465 if (!rpcbuf_alloc_size(buffer, *needed)) {
5466 result = WERR_NOMEM;
5470 /* fill the buffer with the structures */
5471 smb_io_printer_driver_info_1("", buffer, info, 0);
5480 /****************************************************************************
5481 ****************************************************************************/
5483 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5485 DRIVER_INFO_2 *info=NULL;
5488 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5491 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5492 if (!W_ERROR_IS_OK(result))
5495 /* check the required size. */
5496 *needed += spoolss_size_printer_driver_info_2(info);
5498 if (*needed > offered) {
5499 result = WERR_INSUFFICIENT_BUFFER;
5503 if (!rpcbuf_alloc_size(buffer, *needed)) {
5504 result = WERR_NOMEM;
5508 /* fill the buffer with the structures */
5509 smb_io_printer_driver_info_2("", buffer, info, 0);
5518 /****************************************************************************
5519 ****************************************************************************/
5521 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5528 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5529 if (!W_ERROR_IS_OK(result))
5532 /* check the required size. */
5533 *needed += spoolss_size_printer_driver_info_3(&info);
5535 if (*needed > offered) {
5536 result = WERR_INSUFFICIENT_BUFFER;
5540 if (!rpcbuf_alloc_size(buffer, *needed)) {
5541 result = WERR_NOMEM;
5545 /* fill the buffer with the structures */
5546 smb_io_printer_driver_info_3("", buffer, &info, 0);
5549 free_printer_driver_info_3(&info);
5554 /****************************************************************************
5555 ****************************************************************************/
5557 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5564 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5565 if (!W_ERROR_IS_OK(result))
5568 /* check the required size. */
5569 *needed += spoolss_size_printer_driver_info_6(&info);
5571 if (*needed > offered) {
5572 result = WERR_INSUFFICIENT_BUFFER;
5576 if (!rpcbuf_alloc_size(buffer, *needed)) {
5577 result = WERR_NOMEM;
5581 /* fill the buffer with the structures */
5582 smb_io_printer_driver_info_6("", buffer, &info, 0);
5585 free_printer_driver_info_6(&info);
5590 /****************************************************************************
5591 ****************************************************************************/
5593 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5595 POLICY_HND *handle = &q_u->handle;
5596 UNISTR2 *uni_arch = &q_u->architecture;
5597 uint32 level = q_u->level;
5598 uint32 clientmajorversion = q_u->clientmajorversion;
5599 RPC_BUFFER *buffer = NULL;
5600 uint32 offered = q_u->offered;
5601 uint32 *needed = &r_u->needed;
5602 uint32 *servermajorversion = &r_u->servermajorversion;
5603 uint32 *serverminorversion = &r_u->serverminorversion;
5604 Printer_entry *printer;
5607 fstring architecture;
5610 /* that's an [in out] buffer */
5612 if ( q_u->buffer ) {
5613 rpcbuf_move(q_u->buffer, &r_u->buffer);
5614 buffer = r_u->buffer;
5617 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5619 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5620 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5621 return WERR_INVALID_PRINTER_NAME;
5625 *servermajorversion = 0;
5626 *serverminorversion = 0;
5628 fstrcpy(servername, get_server_name( printer ));
5629 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5631 if (!get_printer_snum(p, handle, &snum))
5636 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5638 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5640 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5642 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5645 /* apparently this call is the equivalent of
5646 EnumPrinterDataEx() for the DsDriver key */
5651 return WERR_UNKNOWN_LEVEL;
5654 /****************************************************************************
5655 ****************************************************************************/
5657 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5659 POLICY_HND *handle = &q_u->handle;
5661 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5664 DEBUG(3,("Error in startpageprinter printer handle\n"));
5668 Printer->page_started=True;
5672 /****************************************************************************
5673 ****************************************************************************/
5675 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5677 POLICY_HND *handle = &q_u->handle;
5680 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5683 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5687 if (!get_printer_snum(p, handle, &snum))
5690 Printer->page_started=False;
5691 print_job_endpage(snum, Printer->jobid);
5696 /********************************************************************
5697 * api_spoolss_getprinter
5698 * called from the spoolss dispatcher
5700 ********************************************************************/
5702 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5704 POLICY_HND *handle = &q_u->handle;
5705 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5706 uint32 *jobid = &r_u->jobid;
5708 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5712 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5713 struct current_user user;
5716 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5720 get_current_user(&user, p);
5723 * a nice thing with NT is it doesn't listen to what you tell it.
5724 * when asked to send _only_ RAW datas, it tries to send datas
5727 * So I add checks like in NT Server ...
5730 if (info_1->p_datatype != 0) {
5731 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5732 if (strcmp(datatype, "RAW") != 0) {
5734 return WERR_INVALID_DATATYPE;
5738 /* get the share number of the printer */
5739 if (!get_printer_snum(p, handle, &snum)) {
5743 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5745 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5747 /* An error occured in print_job_start() so return an appropriate
5750 if (Printer->jobid == -1) {
5751 return map_werror_from_unix(errno);
5754 Printer->document_started=True;
5755 (*jobid) = Printer->jobid;
5760 /********************************************************************
5761 * api_spoolss_getprinter
5762 * called from the spoolss dispatcher
5764 ********************************************************************/
5766 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5768 POLICY_HND *handle = &q_u->handle;
5770 return _spoolss_enddocprinter_internal(p, handle);
5773 /****************************************************************************
5774 ****************************************************************************/
5776 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5778 POLICY_HND *handle = &q_u->handle;
5779 uint32 buffer_size = q_u->buffer_size;
5780 uint8 *buffer = q_u->buffer;
5781 uint32 *buffer_written = &q_u->buffer_size2;
5783 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5786 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5787 r_u->buffer_written = q_u->buffer_size2;
5791 if (!get_printer_snum(p, handle, &snum))
5794 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5795 if (*buffer_written == -1) {
5796 r_u->buffer_written = 0;
5797 if (errno == ENOSPC)
5798 return WERR_NO_SPOOL_SPACE;
5800 return WERR_ACCESS_DENIED;
5803 r_u->buffer_written = q_u->buffer_size2;
5808 /********************************************************************
5809 * api_spoolss_getprinter
5810 * called from the spoolss dispatcher
5812 ********************************************************************/
5814 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5817 struct current_user user;
5819 WERROR errcode = WERR_BADFUNC;
5820 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5822 get_current_user(&user, p);
5825 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5829 if (!get_printer_snum(p, handle, &snum))
5833 case PRINTER_CONTROL_PAUSE:
5834 if (print_queue_pause(&user, snum, &errcode)) {
5838 case PRINTER_CONTROL_RESUME:
5839 case PRINTER_CONTROL_UNPAUSE:
5840 if (print_queue_resume(&user, snum, &errcode)) {
5844 case PRINTER_CONTROL_PURGE:
5845 if (print_queue_purge(&user, snum, &errcode)) {
5850 return WERR_UNKNOWN_LEVEL;
5856 /********************************************************************
5857 * api_spoolss_abortprinter
5858 * From MSDN: "Deletes printer's spool file if printer is configured
5860 ********************************************************************/
5862 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5864 POLICY_HND *handle = &q_u->handle;
5865 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5867 struct current_user user;
5868 WERROR errcode = WERR_OK;
5871 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5875 if (!get_printer_snum(p, handle, &snum))
5878 get_current_user( &user, p );
5880 print_job_delete( &user, snum, Printer->jobid, &errcode );
5885 /********************************************************************
5886 * called by spoolss_api_setprinter
5887 * when updating a printer description
5888 ********************************************************************/
5890 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5891 const SPOOL_PRINTER_INFO_LEVEL *info,
5892 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5894 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5898 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5900 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5901 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5902 OUR_HANDLE(handle)));
5904 result = WERR_BADFID;
5908 /* Check the user has permissions to change the security
5909 descriptor. By experimentation with two NT machines, the user
5910 requires Full Access to the printer to change security
5913 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5914 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5915 result = WERR_ACCESS_DENIED;
5919 /* NT seems to like setting the security descriptor even though
5920 nothing may have actually changed. */
5922 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5924 if (DEBUGLEVEL >= 10) {
5928 the_acl = old_secdesc_ctr->sec->dacl;
5929 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5930 PRINTERNAME(snum), the_acl->num_aces));
5932 for (i = 0; i < the_acl->num_aces; i++) {
5935 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5937 DEBUG(10, ("%s 0x%08x\n", sid_str,
5938 the_acl->ace[i].info.mask));
5941 the_acl = secdesc_ctr->sec->dacl;
5944 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5945 PRINTERNAME(snum), the_acl->num_aces));
5947 for (i = 0; i < the_acl->num_aces; i++) {
5950 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5952 DEBUG(10, ("%s 0x%08x\n", sid_str,
5953 the_acl->ace[i].info.mask));
5956 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5960 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5962 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5967 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5974 /********************************************************************
5975 Canonicalize printer info from a client
5977 ATTN: It does not matter what we set the servername to hear
5978 since we do the necessary work in get_a_printer() to set it to
5979 the correct value based on what the client sent in the
5980 _spoolss_open_printer_ex().
5981 ********************************************************************/
5983 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5985 fstring printername;
5988 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5989 "portname=%s drivername=%s comment=%s location=%s\n",
5990 info->servername, info->printername, info->sharename,
5991 info->portname, info->drivername, info->comment, info->location));
5993 /* we force some elements to "correct" values */
5994 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5995 fstrcpy(info->sharename, lp_servicename(snum));
5997 /* check to see if we allow printername != sharename */
5999 if ( lp_force_printername(snum) ) {
6000 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6001 global_myname(), info->sharename );
6004 /* make sure printername is in \\server\printername format */
6006 fstrcpy( printername, info->printername );
6008 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6009 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6013 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6014 global_myname(), p );
6017 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6018 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6025 /****************************************************************************
6026 ****************************************************************************/
6028 static BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6030 extern userdom_struct current_user_info;
6031 char *cmd = lp_addprinter_cmd();
6037 fstring remote_machine = "%m";
6038 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6041 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6043 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6044 cmd, printer->info_2->printername, printer->info_2->sharename,
6045 printer->info_2->portname, printer->info_2->drivername,
6046 printer->info_2->location, printer->info_2->comment, remote_machine);
6048 is_print_op = user_has_privileges( token, &se_printop );
6050 DEBUG(10,("Running [%s]\n", command));
6052 /********* BEGIN SePrintOperatorPrivilege **********/
6057 if ( (ret = smbrun(command, &fd)) == 0 ) {
6058 /* Tell everyone we updated smb.conf. */
6059 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6065 /********* END SePrintOperatorPrivilege **********/
6067 DEBUGADD(10,("returned [%d]\n", ret));
6075 /* reload our services immediately */
6076 reload_services( False );
6079 /* Get lines and convert them back to dos-codepage */
6080 qlines = fd_lines_load(fd, &numlines);
6081 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6084 /* Set the portname to what the script says the portname should be. */
6085 /* but don't require anything to be return from the script exit a good error code */
6088 /* Set the portname to what the script says the portname should be. */
6089 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6090 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6093 file_lines_free(qlines);
6097 /********************************************************************
6098 * Called by spoolss_api_setprinter
6099 * when updating a printer description.
6100 ********************************************************************/
6102 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6103 const SPOOL_PRINTER_INFO_LEVEL *info,
6104 DEVICEMODE *devmode)
6107 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6108 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6113 DEBUG(8,("update_printer\n"));
6118 result = WERR_BADFID;
6122 if (!get_printer_snum(p, handle, &snum)) {
6123 result = WERR_BADFID;
6127 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6128 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6129 result = WERR_BADFID;
6133 DEBUGADD(8,("Converting info_2 struct\n"));
6136 * convert_printer_info converts the incoming
6137 * info from the client and overwrites the info
6138 * just read from the tdb in the pointer 'printer'.
6141 if (!convert_printer_info(info, printer, level)) {
6142 result = WERR_NOMEM;
6147 /* we have a valid devmode
6148 convert it and link it*/
6150 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6151 if (!convert_devicemode(printer->info_2->printername, devmode,
6152 &printer->info_2->devmode)) {
6153 result = WERR_NOMEM;
6158 /* Do sanity check on the requested changes for Samba */
6160 if (!check_printer_ok(printer->info_2, snum)) {
6161 result = WERR_INVALID_PARAM;
6165 /* FIXME!!! If the driver has changed we really should verify that
6166 it is installed before doing much else --jerry */
6168 /* Check calling user has permission to update printer description */
6170 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6171 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6172 result = WERR_ACCESS_DENIED;
6176 /* Call addprinter hook */
6177 /* Check changes to see if this is really needed */
6179 if ( *lp_addprinter_cmd()
6180 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6181 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6182 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6183 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6185 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6186 result = WERR_ACCESS_DENIED;
6191 * make sure we actually reload the services after
6192 * this as smb.conf could have a new section in it
6193 * .... shouldn't .... but could
6195 reload_services(False);
6199 * When a *new* driver is bound to a printer, the drivername is used to
6200 * lookup previously saved driver initialization info, which is then
6201 * bound to the printer, simulating what happens in the Windows arch.
6203 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6205 if (!set_driver_init(printer, 2))
6207 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6208 printer->info_2->drivername));
6211 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6212 printer->info_2->drivername));
6214 notify_printer_driver(snum, printer->info_2->drivername);
6218 * flag which changes actually occured. This is a small subset of
6219 * all the possible changes. We also have to update things in the
6223 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6224 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6225 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6226 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6228 notify_printer_comment(snum, printer->info_2->comment);
6231 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6232 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6233 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6234 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6236 notify_printer_sharename(snum, printer->info_2->sharename);
6239 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6242 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6245 pname = printer->info_2->printername;
6248 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6249 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6250 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6252 notify_printer_printername( snum, pname );
6255 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6256 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6257 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6258 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6260 notify_printer_port(snum, printer->info_2->portname);
6263 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6264 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6265 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6266 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6268 notify_printer_location(snum, printer->info_2->location);
6271 /* here we need to update some more DsSpooler keys */
6272 /* uNCName, serverName, shortServerName */
6274 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6275 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6276 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6277 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6278 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6280 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6281 global_myname(), printer->info_2->sharename );
6282 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6283 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6284 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6286 /* Update printer info */
6287 result = mod_a_printer(printer, 2);
6290 free_a_printer(&printer, 2);
6291 free_a_printer(&old_printer, 2);
6297 /****************************************************************************
6298 ****************************************************************************/
6299 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6300 const SPOOL_PRINTER_INFO_LEVEL *info)
6303 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6305 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6307 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6312 if (!get_printer_snum(p, handle, &snum))
6315 nt_printer_publish(Printer, snum, info7->action);
6319 return WERR_UNKNOWN_LEVEL;
6322 /****************************************************************************
6323 ****************************************************************************/
6325 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6327 POLICY_HND *handle = &q_u->handle;
6328 uint32 level = q_u->level;
6329 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6330 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6331 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6332 uint32 command = q_u->command;
6335 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6338 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6342 /* check the level */
6345 return control_printer(handle, command, p);
6347 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6348 if (!W_ERROR_IS_OK(result))
6351 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6354 return update_printer_sec(handle, level, info, p,
6357 return publish_or_unpublish_printer(p, handle, info);
6359 return WERR_UNKNOWN_LEVEL;
6363 /****************************************************************************
6364 ****************************************************************************/
6366 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6368 POLICY_HND *handle = &q_u->handle;
6369 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6372 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6376 if (Printer->notify.client_connected==True) {
6379 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6381 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6382 !get_printer_snum(p, handle, &snum) )
6385 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6388 Printer->notify.flags=0;
6389 Printer->notify.options=0;
6390 Printer->notify.localmachine[0]='\0';
6391 Printer->notify.printerlocal=0;
6392 if (Printer->notify.option)
6393 free_spool_notify_option(&Printer->notify.option);
6394 Printer->notify.client_connected=False;
6399 /****************************************************************************
6400 ****************************************************************************/
6402 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6404 /* that's an [in out] buffer */
6407 rpcbuf_move(q_u->buffer, &r_u->buffer);
6410 return WERR_INVALID_PARAM; /* this is what a NT server
6411 returns for AddJob. AddJob
6412 must fail on non-local
6416 /****************************************************************************
6417 ****************************************************************************/
6419 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6420 int position, int snum,
6421 NT_PRINTER_INFO_LEVEL *ntprinter)
6425 t=gmtime(&queue->time);
6427 job_info->jobid=queue->job;
6428 init_unistr(&job_info->printername, lp_servicename(snum));
6429 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6430 init_unistr(&job_info->username, queue->fs_user);
6431 init_unistr(&job_info->document, queue->fs_file);
6432 init_unistr(&job_info->datatype, "RAW");
6433 init_unistr(&job_info->text_status, "");
6434 job_info->status=nt_printj_status(queue->status);
6435 job_info->priority=queue->priority;
6436 job_info->position=position;
6437 job_info->totalpages=queue->page_count;
6438 job_info->pagesprinted=0;
6440 make_systemtime(&job_info->submitted, t);
6443 /****************************************************************************
6444 ****************************************************************************/
6446 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6447 int position, int snum,
6448 NT_PRINTER_INFO_LEVEL *ntprinter,
6449 DEVICEMODE *devmode)
6453 t=gmtime(&queue->time);
6455 job_info->jobid=queue->job;
6457 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6459 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6460 init_unistr(&job_info->username, queue->fs_user);
6461 init_unistr(&job_info->document, queue->fs_file);
6462 init_unistr(&job_info->notifyname, queue->fs_user);
6463 init_unistr(&job_info->datatype, "RAW");
6464 init_unistr(&job_info->printprocessor, "winprint");
6465 init_unistr(&job_info->parameters, "");
6466 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6467 init_unistr(&job_info->text_status, "");
6469 /* and here the security descriptor */
6471 job_info->status=nt_printj_status(queue->status);
6472 job_info->priority=queue->priority;
6473 job_info->position=position;
6474 job_info->starttime=0;
6475 job_info->untiltime=0;
6476 job_info->totalpages=queue->page_count;
6477 job_info->size=queue->size;
6478 make_systemtime(&(job_info->submitted), t);
6479 job_info->timeelapsed=0;
6480 job_info->pagesprinted=0;
6482 job_info->devmode = devmode;
6487 /****************************************************************************
6488 Enumjobs at level 1.
6489 ****************************************************************************/
6491 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6492 NT_PRINTER_INFO_LEVEL *ntprinter,
6493 RPC_BUFFER *buffer, uint32 offered,
6494 uint32 *needed, uint32 *returned)
6498 WERROR result = WERR_OK;
6500 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6507 for (i=0; i<*returned; i++)
6508 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6512 /* check the required size. */
6513 for (i=0; i<*returned; i++)
6514 (*needed) += spoolss_size_job_info_1(&info[i]);
6516 if (*needed > offered) {
6517 result = WERR_INSUFFICIENT_BUFFER;
6521 if (!rpcbuf_alloc_size(buffer, *needed)) {
6522 result = WERR_NOMEM;
6526 /* fill the buffer with the structures */
6527 for (i=0; i<*returned; i++)
6528 smb_io_job_info_1("", buffer, &info[i], 0);
6534 if ( !W_ERROR_IS_OK(result) )
6540 /****************************************************************************
6541 Enumjobs at level 2.
6542 ****************************************************************************/
6544 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6545 NT_PRINTER_INFO_LEVEL *ntprinter,
6546 RPC_BUFFER *buffer, uint32 offered,
6547 uint32 *needed, uint32 *returned)
6549 JOB_INFO_2 *info = NULL;
6551 WERROR result = WERR_OK;
6552 DEVICEMODE *devmode = NULL;
6554 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6559 /* this should not be a failure condition if the devmode is NULL */
6561 devmode = construct_dev_mode(snum);
6563 for (i=0; i<*returned; i++)
6564 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6566 free_a_printer(&ntprinter, 2);
6569 /* check the required size. */
6570 for (i=0; i<*returned; i++)
6571 (*needed) += spoolss_size_job_info_2(&info[i]);
6573 if (*needed > offered) {
6574 result = WERR_INSUFFICIENT_BUFFER;
6578 if (!rpcbuf_alloc_size(buffer, *needed)) {
6579 result = WERR_NOMEM;
6583 /* fill the buffer with the structures */
6584 for (i=0; i<*returned; i++)
6585 smb_io_job_info_2("", buffer, &info[i], 0);
6588 free_devmode(devmode);
6591 if ( !W_ERROR_IS_OK(result) )
6598 /****************************************************************************
6600 ****************************************************************************/
6602 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6604 POLICY_HND *handle = &q_u->handle;
6605 uint32 level = q_u->level;
6606 RPC_BUFFER *buffer = NULL;
6607 uint32 offered = q_u->offered;
6608 uint32 *needed = &r_u->needed;
6609 uint32 *returned = &r_u->returned;
6611 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6613 print_status_struct prt_status;
6614 print_queue_struct *queue=NULL;
6616 /* that's an [in out] buffer */
6618 if ( q_u->buffer ) {
6619 rpcbuf_move(q_u->buffer, &r_u->buffer);
6620 buffer = r_u->buffer;
6623 DEBUG(4,("_spoolss_enumjobs\n"));
6628 /* lookup the printer snum and tdb entry */
6630 if (!get_printer_snum(p, handle, &snum))
6633 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6634 if ( !W_ERROR_IS_OK(wret) )
6637 *returned = print_queue_status(snum, &queue, &prt_status);
6638 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6640 if (*returned == 0) {
6647 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6650 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6655 wret = WERR_UNKNOWN_LEVEL;
6658 free_a_printer( &ntprinter, 2 );
6662 /****************************************************************************
6663 ****************************************************************************/
6665 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6670 /****************************************************************************
6671 ****************************************************************************/
6673 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6675 POLICY_HND *handle = &q_u->handle;
6676 uint32 jobid = q_u->jobid;
6677 uint32 command = q_u->command;
6679 struct current_user user;
6681 WERROR errcode = WERR_BADFUNC;
6683 if (!get_printer_snum(p, handle, &snum)) {
6687 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6688 return WERR_INVALID_PRINTER_NAME;
6691 get_current_user(&user, p);
6694 case JOB_CONTROL_CANCEL:
6695 case JOB_CONTROL_DELETE:
6696 if (print_job_delete(&user, snum, jobid, &errcode)) {
6700 case JOB_CONTROL_PAUSE:
6701 if (print_job_pause(&user, snum, jobid, &errcode)) {
6705 case JOB_CONTROL_RESTART:
6706 case JOB_CONTROL_RESUME:
6707 if (print_job_resume(&user, snum, jobid, &errcode)) {
6712 return WERR_UNKNOWN_LEVEL;
6718 /****************************************************************************
6719 Enumerates all printer drivers at level 1.
6720 ****************************************************************************/
6722 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6727 fstring *list = NULL;
6728 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6729 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6730 WERROR result = WERR_OK;
6734 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6736 ndrivers=get_ntdrivers(&list, architecture, version);
6737 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6743 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6744 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6745 SAFE_FREE(driver_info_1);
6749 else driver_info_1 = tdi1;
6752 for (i=0; i<ndrivers; i++) {
6754 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6755 ZERO_STRUCT(driver);
6756 status = get_a_printer_driver(&driver, 3, list[i],
6757 architecture, version);
6758 if (!W_ERROR_IS_OK(status)) {
6762 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6763 free_a_printer_driver(driver, 3);
6766 *returned+=ndrivers;
6770 /* check the required size. */
6771 for (i=0; i<*returned; i++) {
6772 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6773 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6776 if (*needed > offered) {
6777 result = WERR_INSUFFICIENT_BUFFER;
6781 if (!rpcbuf_alloc_size(buffer, *needed)) {
6782 result = WERR_NOMEM;
6786 /* fill the buffer with the driver structures */
6787 for (i=0; i<*returned; i++) {
6788 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6789 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6793 SAFE_FREE(driver_info_1);
6795 if ( !W_ERROR_IS_OK(result) )
6801 /****************************************************************************
6802 Enumerates all printer drivers at level 2.
6803 ****************************************************************************/
6805 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6810 fstring *list = NULL;
6811 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6812 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6813 WERROR result = WERR_OK;
6817 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6819 ndrivers=get_ntdrivers(&list, architecture, version);
6820 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6826 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6827 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6828 SAFE_FREE(driver_info_2);
6832 else driver_info_2 = tdi2;
6835 for (i=0; i<ndrivers; i++) {
6838 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6839 ZERO_STRUCT(driver);
6840 status = get_a_printer_driver(&driver, 3, list[i],
6841 architecture, version);
6842 if (!W_ERROR_IS_OK(status)) {
6846 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6847 free_a_printer_driver(driver, 3);
6850 *returned+=ndrivers;
6854 /* check the required size. */
6855 for (i=0; i<*returned; i++) {
6856 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6857 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6860 if (*needed > offered) {
6861 result = WERR_INSUFFICIENT_BUFFER;
6865 if (!rpcbuf_alloc_size(buffer, *needed)) {
6866 result = WERR_NOMEM;
6870 /* fill the buffer with the form structures */
6871 for (i=0; i<*returned; i++) {
6872 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6873 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6877 SAFE_FREE(driver_info_2);
6879 if ( !W_ERROR_IS_OK(result) )
6885 /****************************************************************************
6886 Enumerates all printer drivers at level 3.
6887 ****************************************************************************/
6889 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6894 fstring *list = NULL;
6895 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6896 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6897 WERROR result = WERR_OK;
6901 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6903 ndrivers=get_ntdrivers(&list, architecture, version);
6904 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6910 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6911 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6912 SAFE_FREE(driver_info_3);
6916 else driver_info_3 = tdi3;
6919 for (i=0; i<ndrivers; i++) {
6922 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6923 ZERO_STRUCT(driver);
6924 status = get_a_printer_driver(&driver, 3, list[i],
6925 architecture, version);
6926 if (!W_ERROR_IS_OK(status)) {
6930 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6931 free_a_printer_driver(driver, 3);
6934 *returned+=ndrivers;
6938 /* check the required size. */
6939 for (i=0; i<*returned; i++) {
6940 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6941 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6944 if (*needed > offered) {
6945 result = WERR_INSUFFICIENT_BUFFER;
6949 if (!rpcbuf_alloc_size(buffer, *needed)) {
6950 result = WERR_NOMEM;
6954 /* fill the buffer with the driver structures */
6955 for (i=0; i<*returned; i++) {
6956 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6957 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6961 for (i=0; i<*returned; i++)
6962 SAFE_FREE(driver_info_3[i].dependentfiles);
6964 SAFE_FREE(driver_info_3);
6966 if ( !W_ERROR_IS_OK(result) )
6972 /****************************************************************************
6973 Enumerates all printer drivers.
6974 ****************************************************************************/
6976 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6978 uint32 level = q_u->level;
6979 RPC_BUFFER *buffer = NULL;
6980 uint32 offered = q_u->offered;
6981 uint32 *needed = &r_u->needed;
6982 uint32 *returned = &r_u->returned;
6985 fstring architecture;
6987 /* that's an [in out] buffer */
6989 if ( q_u->buffer ) {
6990 rpcbuf_move(q_u->buffer, &r_u->buffer);
6991 buffer = r_u->buffer;
6994 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6999 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7000 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7002 if ( !is_myname_or_ipaddr( servername ) )
7003 return WERR_UNKNOWN_PRINTER_DRIVER;
7007 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7009 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7011 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7013 return WERR_UNKNOWN_LEVEL;
7017 /****************************************************************************
7018 ****************************************************************************/
7020 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7022 form->flag=list->flag;
7023 init_unistr(&form->name, list->name);
7024 form->width=list->width;
7025 form->length=list->length;
7026 form->left=list->left;
7027 form->top=list->top;
7028 form->right=list->right;
7029 form->bottom=list->bottom;
7032 /****************************************************************************
7033 ****************************************************************************/
7035 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7037 uint32 level = q_u->level;
7038 RPC_BUFFER *buffer = NULL;
7039 uint32 offered = q_u->offered;
7040 uint32 *needed = &r_u->needed;
7041 uint32 *numofforms = &r_u->numofforms;
7042 uint32 numbuiltinforms;
7044 nt_forms_struct *list=NULL;
7045 nt_forms_struct *builtinlist=NULL;
7050 /* that's an [in out] buffer */
7052 if ( q_u->buffer ) {
7053 rpcbuf_move(q_u->buffer, &r_u->buffer);
7054 buffer = r_u->buffer;
7057 DEBUG(4,("_spoolss_enumforms\n"));
7058 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7059 DEBUGADD(5,("Info level [%d]\n", level));
7061 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7062 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7063 *numofforms = get_ntforms(&list);
7064 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7065 *numofforms += numbuiltinforms;
7067 if (*numofforms == 0)
7068 return WERR_NO_MORE_ITEMS;
7072 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7077 /* construct the list of form structures */
7078 for (i=0; i<numbuiltinforms; i++) {
7079 DEBUGADD(6,("Filling form number [%d]\n",i));
7080 fill_form_1(&forms_1[i], &builtinlist[i]);
7083 SAFE_FREE(builtinlist);
7085 for (; i<*numofforms; i++) {
7086 DEBUGADD(6,("Filling form number [%d]\n",i));
7087 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7092 /* check the required size. */
7093 for (i=0; i<numbuiltinforms; i++) {
7094 DEBUGADD(6,("adding form [%d]'s size\n",i));
7095 buffer_size += spoolss_size_form_1(&forms_1[i]);
7097 for (; i<*numofforms; i++) {
7098 DEBUGADD(6,("adding form [%d]'s size\n",i));
7099 buffer_size += spoolss_size_form_1(&forms_1[i]);
7102 *needed=buffer_size;
7104 if (*needed > offered) {
7107 return WERR_INSUFFICIENT_BUFFER;
7110 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7116 /* fill the buffer with the form structures */
7117 for (i=0; i<numbuiltinforms; i++) {
7118 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7119 smb_io_form_1("", buffer, &forms_1[i], 0);
7121 for (; i<*numofforms; i++) {
7122 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7123 smb_io_form_1("", buffer, &forms_1[i], 0);
7132 SAFE_FREE(builtinlist);
7133 return WERR_UNKNOWN_LEVEL;
7138 /****************************************************************************
7139 ****************************************************************************/
7141 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7143 uint32 level = q_u->level;
7144 UNISTR2 *uni_formname = &q_u->formname;
7145 RPC_BUFFER *buffer = NULL;
7146 uint32 offered = q_u->offered;
7147 uint32 *needed = &r_u->needed;
7149 nt_forms_struct *list=NULL;
7150 nt_forms_struct builtin_form;
7155 int numofforms=0, i=0;
7157 /* that's an [in out] buffer */
7159 if ( q_u->buffer ) {
7160 rpcbuf_move(q_u->buffer, &r_u->buffer);
7161 buffer = r_u->buffer;
7164 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7166 DEBUG(4,("_spoolss_getform\n"));
7167 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7168 DEBUGADD(5,("Info level [%d]\n", level));
7170 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7171 if (!foundBuiltin) {
7172 numofforms = get_ntforms(&list);
7173 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7175 if (numofforms == 0)
7182 fill_form_1(&form_1, &builtin_form);
7185 /* Check if the requested name is in the list of form structures */
7186 for (i=0; i<numofforms; i++) {
7188 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7190 if (strequal(form_name, list[i].name)) {
7191 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7192 fill_form_1(&form_1, &list[i]);
7198 if (i == numofforms) {
7202 /* check the required size. */
7204 *needed=spoolss_size_form_1(&form_1);
7206 if (*needed > offered)
7207 return WERR_INSUFFICIENT_BUFFER;
7209 if (!rpcbuf_alloc_size(buffer, buffer_size))
7212 /* fill the buffer with the form structures */
7213 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7214 smb_io_form_1("", buffer, &form_1, 0);
7220 return WERR_UNKNOWN_LEVEL;
7224 /****************************************************************************
7225 ****************************************************************************/
7227 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7229 init_unistr(&port->port_name, name);
7232 /****************************************************************************
7233 ****************************************************************************/
7235 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7237 init_unistr(&port->port_name, name);
7238 init_unistr(&port->monitor_name, "Local Monitor");
7239 init_unistr(&port->description, "Local Port");
7240 port->port_type=PORT_TYPE_WRITE;
7244 /****************************************************************************
7246 ****************************************************************************/
7248 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7250 PORT_INFO_1 *ports=NULL;
7252 WERROR result = WERR_OK;
7254 if (*lp_enumports_cmd()) {
7255 char *cmd = lp_enumports_cmd();
7262 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7264 DEBUG(10,("Running [%s]\n", command));
7265 ret = smbrun(command, &fd);
7266 DEBUG(10,("Returned [%d]\n", ret));
7270 /* Is this the best error to return here? */
7271 return WERR_ACCESS_DENIED;
7275 qlines = fd_lines_load(fd, &numlines);
7276 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7280 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7281 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7282 dos_errstr(WERR_NOMEM)));
7283 file_lines_free(qlines);
7287 for (i=0; i<numlines; i++) {
7288 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7289 fill_port_1(&ports[i], qlines[i]);
7292 file_lines_free(qlines);
7295 *returned = numlines;
7298 *returned = 1; /* Sole Samba port returned. */
7300 if((ports=SMB_MALLOC_P(PORT_INFO_1)) == NULL)
7303 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7305 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7308 /* check the required size. */
7309 for (i=0; i<*returned; i++) {
7310 DEBUGADD(6,("adding port [%d]'s size\n", i));
7311 *needed += spoolss_size_port_info_1(&ports[i]);
7314 if (*needed > offered) {
7315 result = WERR_INSUFFICIENT_BUFFER;
7319 if (!rpcbuf_alloc_size(buffer, *needed)) {
7320 result = WERR_NOMEM;
7324 /* fill the buffer with the ports structures */
7325 for (i=0; i<*returned; i++) {
7326 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7327 smb_io_port_1("", buffer, &ports[i], 0);
7333 if ( !W_ERROR_IS_OK(result) )
7339 /****************************************************************************
7341 ****************************************************************************/
7343 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7345 PORT_INFO_2 *ports=NULL;
7347 WERROR result = WERR_OK;
7349 if (*lp_enumports_cmd()) {
7350 char *cmd = lp_enumports_cmd();
7359 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7360 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7362 path = lp_lockdir();
7364 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7365 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7368 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7369 ret = smbrun(command, &fd);
7370 DEBUGADD(10,("returned [%d]\n", ret));
7374 /* Is this the best error to return here? */
7375 return WERR_ACCESS_DENIED;
7379 qlines = fd_lines_load(fd, &numlines);
7380 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7384 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7385 file_lines_free(qlines);
7389 for (i=0; i<numlines; i++) {
7390 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7391 fill_port_2(&(ports[i]), qlines[i]);
7394 file_lines_free(qlines);
7397 *returned = numlines;
7403 if((ports=SMB_MALLOC_P(PORT_INFO_2)) == NULL)
7406 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7408 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7411 /* check the required size. */
7412 for (i=0; i<*returned; i++) {
7413 DEBUGADD(6,("adding port [%d]'s size\n", i));
7414 *needed += spoolss_size_port_info_2(&ports[i]);
7417 if (*needed > offered) {
7418 result = WERR_INSUFFICIENT_BUFFER;
7422 if (!rpcbuf_alloc_size(buffer, *needed)) {
7423 result = WERR_NOMEM;
7427 /* fill the buffer with the ports structures */
7428 for (i=0; i<*returned; i++) {
7429 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7430 smb_io_port_2("", buffer, &ports[i], 0);
7436 if ( !W_ERROR_IS_OK(result) )
7442 /****************************************************************************
7444 ****************************************************************************/
7446 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7448 uint32 level = q_u->level;
7449 RPC_BUFFER *buffer = NULL;
7450 uint32 offered = q_u->offered;
7451 uint32 *needed = &r_u->needed;
7452 uint32 *returned = &r_u->returned;
7454 /* that's an [in out] buffer */
7456 if ( q_u->buffer ) {
7457 rpcbuf_move(q_u->buffer, &r_u->buffer);
7458 buffer = r_u->buffer;
7461 DEBUG(4,("_spoolss_enumports\n"));
7468 return enumports_level_1(buffer, offered, needed, returned);
7470 return enumports_level_2(buffer, offered, needed, returned);
7472 return WERR_UNKNOWN_LEVEL;
7476 /****************************************************************************
7477 ****************************************************************************/
7479 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7480 const SPOOL_PRINTER_INFO_LEVEL *info,
7481 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7482 uint32 user_switch, const SPOOL_USER_CTR *user,
7485 NT_PRINTER_INFO_LEVEL *printer = NULL;
7488 WERROR err = WERR_OK;
7490 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7491 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7495 ZERO_STRUCTP(printer);
7497 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7498 if (!convert_printer_info(info, printer, 2)) {
7499 free_a_printer(&printer, 2);
7503 /* check to see if the printer already exists */
7505 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7506 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7507 printer->info_2->sharename));
7508 free_a_printer(&printer, 2);
7509 return WERR_PRINTER_ALREADY_EXISTS;
7512 /* FIXME!!! smbd should check to see if the driver is installed before
7513 trying to add a printer like this --jerry */
7515 if (*lp_addprinter_cmd() ) {
7516 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7517 free_a_printer(&printer,2);
7518 return WERR_ACCESS_DENIED;
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(!move_driver_to_download_area(driver, level, &user, &err)) {
7647 if (W_ERROR_IS_OK(err))
7648 err = WERR_ACCESS_DENIED;
7652 if (add_a_printer_driver(driver, level)!=0) {
7653 err = WERR_ACCESS_DENIED;
7657 /* BEGIN_ADMIN_LOG */
7660 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7661 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7662 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7665 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7666 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7667 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7673 * I think this is where he DrvUpgradePrinter() hook would be
7674 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7675 * server. Right now, we just need to send ourselves a message
7676 * to update each printer bound to this driver. --jerry
7679 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7680 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7685 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7686 * decide if the driver init data should be deleted. The rules are:
7687 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7688 * 2) delete init data only if there is no 2k/Xp driver
7689 * 3) always delete init data
7690 * The generalized rule is always use init data from the highest order driver.
7691 * It is necessary to follow the driver install by an initialization step to
7692 * finish off this process.
7695 version = driver.info_3->cversion;
7696 else if (level == 6)
7697 version = driver.info_6->version;
7702 * 9x printer driver - never delete init data
7705 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7710 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7711 * there is no 2k/Xp driver init data for this driver name.
7715 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7717 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7719 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7721 if (!del_driver_init(driver_name))
7722 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7725 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7727 free_a_printer_driver(driver1,3);
7728 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7735 * 2k or Xp printer driver - always delete init data
7738 if (!del_driver_init(driver_name))
7739 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7743 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7749 free_a_printer_driver(driver, level);
7753 /********************************************************************
7754 * spoolss_addprinterdriverex
7755 ********************************************************************/
7757 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7759 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7760 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7763 * we only support the semantics of AddPrinterDriver()
7764 * i.e. only copy files that are newer than existing ones
7767 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7768 return WERR_ACCESS_DENIED;
7770 ZERO_STRUCT(q_u_local);
7771 ZERO_STRUCT(r_u_local);
7773 /* just pass the information off to _spoolss_addprinterdriver() */
7774 q_u_local.server_name_ptr = q_u->server_name_ptr;
7775 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7776 q_u_local.level = q_u->level;
7777 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7779 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7782 /****************************************************************************
7783 ****************************************************************************/
7785 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7787 init_unistr(&info->name, name);
7790 /****************************************************************************
7791 ****************************************************************************/
7793 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7799 const char *short_archi;
7800 DRIVER_DIRECTORY_1 *info=NULL;
7801 WERROR result = WERR_OK;
7803 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7804 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7806 /* check for beginning double '\'s and that the server
7809 pservername = servername;
7810 if ( *pservername == '\\' && strlen(servername)>2 ) {
7814 if ( !is_myname_or_ipaddr( pservername ) )
7815 return WERR_INVALID_PARAM;
7817 if (!(short_archi = get_short_archi(long_archi)))
7818 return WERR_INVALID_ENVIRONMENT;
7820 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7823 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7825 DEBUG(4,("printer driver directory: [%s]\n", path));
7827 fill_driverdir_1(info, path);
7829 *needed += spoolss_size_driverdir_info_1(info);
7831 if (*needed > offered) {
7832 result = WERR_INSUFFICIENT_BUFFER;
7836 if (!rpcbuf_alloc_size(buffer, *needed)) {
7837 result = WERR_NOMEM;
7841 smb_io_driverdir_1("", buffer, info, 0);
7849 /****************************************************************************
7850 ****************************************************************************/
7852 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7854 UNISTR2 *name = &q_u->name;
7855 UNISTR2 *uni_environment = &q_u->environment;
7856 uint32 level = q_u->level;
7857 RPC_BUFFER *buffer = NULL;
7858 uint32 offered = q_u->offered;
7859 uint32 *needed = &r_u->needed;
7861 /* that's an [in out] buffer */
7863 if ( q_u->buffer ) {
7864 rpcbuf_move(q_u->buffer, &r_u->buffer);
7865 buffer = r_u->buffer;
7868 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7874 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7876 return WERR_UNKNOWN_LEVEL;
7880 /****************************************************************************
7881 ****************************************************************************/
7883 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7885 POLICY_HND *handle = &q_u->handle;
7886 uint32 idx = q_u->index;
7887 uint32 in_value_len = q_u->valuesize;
7888 uint32 in_data_len = q_u->datasize;
7889 uint32 *out_max_value_len = &r_u->valuesize;
7890 uint16 **out_value = &r_u->value;
7891 uint32 *out_value_len = &r_u->realvaluesize;
7892 uint32 *out_type = &r_u->type;
7893 uint32 *out_max_data_len = &r_u->datasize;
7894 uint8 **data_out = &r_u->data;
7895 uint32 *out_data_len = &r_u->realdatasize;
7897 NT_PRINTER_INFO_LEVEL *printer = NULL;
7899 uint32 biggest_valuesize;
7900 uint32 biggest_datasize;
7902 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7905 REGISTRY_VALUE *val = NULL;
7906 NT_PRINTER_DATA *p_data;
7907 int i, key_index, num_values;
7910 ZERO_STRUCT( printer );
7914 *out_max_data_len = 0;
7918 DEBUG(5,("spoolss_enumprinterdata\n"));
7921 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7925 if (!get_printer_snum(p,handle, &snum))
7928 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7929 if (!W_ERROR_IS_OK(result))
7932 p_data = &printer->info_2->data;
7933 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7938 * The NT machine wants to know the biggest size of value and data
7940 * cf: MSDN EnumPrinterData remark section
7943 if ( !in_value_len && !in_data_len && (key_index != -1) )
7945 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7947 biggest_valuesize = 0;
7948 biggest_datasize = 0;
7950 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7952 for ( i=0; i<num_values; i++ )
7954 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7956 name_length = strlen(val->valuename);
7957 if ( strlen(val->valuename) > biggest_valuesize )
7958 biggest_valuesize = name_length;
7960 if ( val->size > biggest_datasize )
7961 biggest_datasize = val->size;
7963 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7967 /* the value is an UNICODE string but real_value_size is the length
7968 in bytes including the trailing 0 */
7970 *out_value_len = 2 * (1+biggest_valuesize);
7971 *out_data_len = biggest_datasize;
7973 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7979 * the value len is wrong in NT sp3
7980 * that's the number of bytes not the number of unicode chars
7983 if ( key_index != -1 )
7984 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7989 /* out_value should default to "" or else NT4 has
7990 problems unmarshalling the response */
7992 *out_max_value_len=(in_value_len/sizeof(uint16));
7994 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7996 result = WERR_NOMEM;
8000 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8002 /* the data is counted in bytes */
8004 *out_max_data_len = in_data_len;
8005 *out_data_len = in_data_len;
8007 /* only allocate when given a non-zero data_len */
8009 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8011 result = WERR_NOMEM;
8015 result = WERR_NO_MORE_ITEMS;
8021 * - counted in bytes in the request
8022 * - counted in UNICODE chars in the max reply
8023 * - counted in bytes in the real size
8025 * take a pause *before* coding not *during* coding
8029 *out_max_value_len=(in_value_len/sizeof(uint16));
8030 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8032 result = WERR_NOMEM;
8036 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
8040 *out_type = regval_type( val );
8042 /* data - counted in bytes */
8044 *out_max_data_len = in_data_len;
8045 if ( (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8047 result = WERR_NOMEM;
8050 data_len = (size_t)regval_size(val);
8051 memcpy( *data_out, regval_data_p(val), data_len );
8052 *out_data_len = data_len;
8056 free_a_printer(&printer, 2);
8060 /****************************************************************************
8061 ****************************************************************************/
8063 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8065 POLICY_HND *handle = &q_u->handle;
8066 UNISTR2 *value = &q_u->value;
8067 uint32 type = q_u->type;
8068 uint8 *data = q_u->data;
8069 uint32 real_len = q_u->real_len;
8071 NT_PRINTER_INFO_LEVEL *printer = NULL;
8073 WERROR status = WERR_OK;
8074 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8077 DEBUG(5,("spoolss_setprinterdata\n"));
8080 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8084 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8085 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8086 return WERR_INVALID_PARAM;
8089 if (!get_printer_snum(p,handle, &snum))
8093 * Access check : NT returns "access denied" if you make a
8094 * SetPrinterData call without the necessary privildge.
8095 * we were originally returning OK if nothing changed
8096 * which made Win2k issue **a lot** of SetPrinterData
8097 * when connecting to a printer --jerry
8100 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8102 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8103 status = WERR_ACCESS_DENIED;
8107 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8108 if (!W_ERROR_IS_OK(status))
8111 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8114 * When client side code sets a magic printer data key, detect it and save
8115 * the current printer data and the magic key's data (its the DEVMODE) for
8116 * future printer/driver initializations.
8118 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8120 /* Set devmode and printer initialization info */
8121 status = save_driver_init( printer, 2, data, real_len );
8123 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8127 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8128 type, data, real_len );
8129 if ( W_ERROR_IS_OK(status) )
8130 status = mod_a_printer(printer, 2);
8134 free_a_printer(&printer, 2);
8139 /****************************************************************************
8140 ****************************************************************************/
8142 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8144 POLICY_HND *handle = &q_u->handle;
8145 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8148 DEBUG(5,("_spoolss_resetprinter\n"));
8151 * All we do is to check to see if the handle and queue is valid.
8152 * This call really doesn't mean anything to us because we only
8153 * support RAW printing. --jerry
8157 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8161 if (!get_printer_snum(p,handle, &snum))
8165 /* blindly return success */
8170 /****************************************************************************
8171 ****************************************************************************/
8173 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8175 POLICY_HND *handle = &q_u->handle;
8176 UNISTR2 *value = &q_u->valuename;
8178 NT_PRINTER_INFO_LEVEL *printer = NULL;
8180 WERROR status = WERR_OK;
8181 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8184 DEBUG(5,("spoolss_deleteprinterdata\n"));
8187 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8191 if (!get_printer_snum(p, handle, &snum))
8194 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8195 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8196 return WERR_ACCESS_DENIED;
8199 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8200 if (!W_ERROR_IS_OK(status))
8203 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8205 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8207 if ( W_ERROR_IS_OK(status) )
8208 mod_a_printer( printer, 2 );
8210 free_a_printer(&printer, 2);
8215 /****************************************************************************
8216 ****************************************************************************/
8218 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8220 POLICY_HND *handle = &q_u->handle;
8221 FORM *form = &q_u->form;
8222 nt_forms_struct tmpForm;
8224 WERROR status = WERR_OK;
8225 NT_PRINTER_INFO_LEVEL *printer = NULL;
8228 nt_forms_struct *list=NULL;
8229 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8231 DEBUG(5,("spoolss_addform\n"));
8234 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8239 /* forms can be added on printer of on the print server handle */
8241 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8243 if (!get_printer_snum(p,handle, &snum))
8246 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8247 if (!W_ERROR_IS_OK(status))
8251 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8252 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8253 status = WERR_ACCESS_DENIED;
8257 /* can't add if builtin */
8259 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8260 status = WERR_ALREADY_EXISTS;
8264 count = get_ntforms(&list);
8266 if(!add_a_form(&list, form, &count)) {
8267 status = WERR_NOMEM;
8271 write_ntforms(&list, count);
8274 * ChangeID must always be set if this is a printer
8277 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8278 status = mod_a_printer(printer, 2);
8282 free_a_printer(&printer, 2);
8288 /****************************************************************************
8289 ****************************************************************************/
8291 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8293 POLICY_HND *handle = &q_u->handle;
8294 UNISTR2 *form_name = &q_u->name;
8295 nt_forms_struct tmpForm;
8297 nt_forms_struct *list=NULL;
8298 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8300 WERROR status = WERR_OK;
8301 NT_PRINTER_INFO_LEVEL *printer = NULL;
8303 DEBUG(5,("spoolss_deleteform\n"));
8306 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8310 /* forms can be deleted on printer of on the print server handle */
8312 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8314 if (!get_printer_snum(p,handle, &snum))
8317 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8318 if (!W_ERROR_IS_OK(status))
8322 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8323 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8324 status = WERR_ACCESS_DENIED;
8328 /* can't delete if builtin */
8330 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8331 status = WERR_INVALID_PARAM;
8335 count = get_ntforms(&list);
8337 if ( !delete_a_form(&list, form_name, &count, &status ))
8341 * ChangeID must always be set if this is a printer
8344 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8345 status = mod_a_printer(printer, 2);
8349 free_a_printer(&printer, 2);
8355 /****************************************************************************
8356 ****************************************************************************/
8358 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8360 POLICY_HND *handle = &q_u->handle;
8361 FORM *form = &q_u->form;
8362 nt_forms_struct tmpForm;
8364 WERROR status = WERR_OK;
8365 NT_PRINTER_INFO_LEVEL *printer = NULL;
8368 nt_forms_struct *list=NULL;
8369 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8371 DEBUG(5,("spoolss_setform\n"));
8374 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8378 /* forms can be modified on printer of on the print server handle */
8380 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8382 if (!get_printer_snum(p,handle, &snum))
8385 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8386 if (!W_ERROR_IS_OK(status))
8390 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8391 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8392 status = WERR_ACCESS_DENIED;
8396 /* can't set if builtin */
8397 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8398 status = WERR_INVALID_PARAM;
8402 count = get_ntforms(&list);
8403 update_a_form(&list, form, count);
8404 write_ntforms(&list, count);
8407 * ChangeID must always be set if this is a printer
8410 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8411 status = mod_a_printer(printer, 2);
8416 free_a_printer(&printer, 2);
8422 /****************************************************************************
8423 enumprintprocessors level 1.
8424 ****************************************************************************/
8426 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8428 PRINTPROCESSOR_1 *info_1=NULL;
8429 WERROR result = WERR_OK;
8431 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8436 init_unistr(&info_1->name, "winprint");
8438 *needed += spoolss_size_printprocessor_info_1(info_1);
8440 if (*needed > offered) {
8441 result = WERR_INSUFFICIENT_BUFFER;
8445 if (!rpcbuf_alloc_size(buffer, *needed)) {
8446 result = WERR_NOMEM;
8450 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8455 if ( !W_ERROR_IS_OK(result) )
8461 /****************************************************************************
8462 ****************************************************************************/
8464 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8466 uint32 level = q_u->level;
8467 RPC_BUFFER *buffer = NULL;
8468 uint32 offered = q_u->offered;
8469 uint32 *needed = &r_u->needed;
8470 uint32 *returned = &r_u->returned;
8472 /* that's an [in out] buffer */
8474 if ( q_u->buffer ) {
8475 rpcbuf_move(q_u->buffer, &r_u->buffer);
8476 buffer = r_u->buffer;
8479 DEBUG(5,("spoolss_enumprintprocessors\n"));
8482 * Enumerate the print processors ...
8484 * Just reply with "winprint", to keep NT happy
8485 * and I can use my nice printer checker.
8493 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8495 return WERR_UNKNOWN_LEVEL;
8499 /****************************************************************************
8500 enumprintprocdatatypes level 1.
8501 ****************************************************************************/
8503 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8505 PRINTPROCDATATYPE_1 *info_1=NULL;
8506 WERROR result = WERR_NOMEM;
8508 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8513 init_unistr(&info_1->name, "RAW");
8515 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8517 if (*needed > offered) {
8518 result = WERR_INSUFFICIENT_BUFFER;
8522 if (!rpcbuf_alloc_size(buffer, *needed)) {
8523 result = WERR_NOMEM;
8527 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8532 if ( !W_ERROR_IS_OK(result) )
8538 /****************************************************************************
8539 ****************************************************************************/
8541 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8543 uint32 level = q_u->level;
8544 RPC_BUFFER *buffer = NULL;
8545 uint32 offered = q_u->offered;
8546 uint32 *needed = &r_u->needed;
8547 uint32 *returned = &r_u->returned;
8549 /* that's an [in out] buffer */
8551 if ( q_u->buffer ) {
8552 rpcbuf_move(q_u->buffer, &r_u->buffer);
8553 buffer = r_u->buffer;
8556 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8563 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8565 return WERR_UNKNOWN_LEVEL;
8569 /****************************************************************************
8570 enumprintmonitors level 1.
8571 ****************************************************************************/
8573 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8575 PRINTMONITOR_1 *info_1=NULL;
8576 WERROR result = WERR_OK;
8578 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8583 init_unistr(&info_1->name, "Local Port");
8585 *needed += spoolss_size_printmonitor_info_1(info_1);
8587 if (*needed > offered) {
8588 result = WERR_INSUFFICIENT_BUFFER;
8592 if (!rpcbuf_alloc_size(buffer, *needed)) {
8593 result = WERR_NOMEM;
8597 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8602 if ( !W_ERROR_IS_OK(result) )
8608 /****************************************************************************
8609 enumprintmonitors level 2.
8610 ****************************************************************************/
8612 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8614 PRINTMONITOR_2 *info_2=NULL;
8615 WERROR result = WERR_OK;
8617 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8622 init_unistr(&info_2->name, "Local Port");
8623 init_unistr(&info_2->environment, "Windows NT X86");
8624 init_unistr(&info_2->dll_name, "localmon.dll");
8626 *needed += spoolss_size_printmonitor_info_2(info_2);
8628 if (*needed > offered) {
8629 result = WERR_INSUFFICIENT_BUFFER;
8633 if (!rpcbuf_alloc_size(buffer, *needed)) {
8634 result = WERR_NOMEM;
8638 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8643 if ( !W_ERROR_IS_OK(result) )
8649 /****************************************************************************
8650 ****************************************************************************/
8652 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8654 uint32 level = q_u->level;
8655 RPC_BUFFER *buffer = NULL;
8656 uint32 offered = q_u->offered;
8657 uint32 *needed = &r_u->needed;
8658 uint32 *returned = &r_u->returned;
8660 /* that's an [in out] buffer */
8662 if ( q_u->buffer ) {
8663 rpcbuf_move(q_u->buffer, &r_u->buffer);
8664 buffer = r_u->buffer;
8667 DEBUG(5,("spoolss_enumprintmonitors\n"));
8670 * Enumerate the print monitors ...
8672 * Just reply with "Local Port", to keep NT happy
8673 * and I can use my nice printer checker.
8681 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8683 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8685 return WERR_UNKNOWN_LEVEL;
8689 /****************************************************************************
8690 ****************************************************************************/
8692 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8693 NT_PRINTER_INFO_LEVEL *ntprinter,
8694 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8699 JOB_INFO_1 *info_1=NULL;
8700 WERROR result = WERR_OK;
8702 info_1=SMB_MALLOC_P(JOB_INFO_1);
8704 if (info_1 == NULL) {
8708 for (i=0; i<count && found==False; i++) {
8709 if ((*queue)[i].job==(int)jobid)
8715 /* NT treats not found as bad param... yet another bad choice */
8716 return WERR_INVALID_PARAM;
8719 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8721 *needed += spoolss_size_job_info_1(info_1);
8723 if (*needed > offered) {
8724 result = WERR_INSUFFICIENT_BUFFER;
8728 if (!rpcbuf_alloc_size(buffer, *needed)) {
8729 result = WERR_NOMEM;
8733 smb_io_job_info_1("", buffer, info_1, 0);
8741 /****************************************************************************
8742 ****************************************************************************/
8744 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8745 NT_PRINTER_INFO_LEVEL *ntprinter,
8746 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8753 DEVICEMODE *devmode = NULL;
8754 NT_DEVICEMODE *nt_devmode = NULL;
8756 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8759 ZERO_STRUCTP(info_2);
8761 for ( i=0; i<count && found==False; i++ )
8763 if ((*queue)[i].job == (int)jobid)
8768 /* NT treats not found as bad param... yet another bad
8770 result = WERR_INVALID_PARAM;
8775 * if the print job does not have a DEVMODE associated with it,
8776 * just use the one for the printer. A NULL devicemode is not
8777 * a failure condition
8780 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8781 devmode = construct_dev_mode(snum);
8783 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8784 ZERO_STRUCTP( devmode );
8785 convert_nt_devicemode( devmode, nt_devmode );
8789 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8791 *needed += spoolss_size_job_info_2(info_2);
8793 if (*needed > offered) {
8794 result = WERR_INSUFFICIENT_BUFFER;
8798 if (!rpcbuf_alloc_size(buffer, *needed)) {
8799 result = WERR_NOMEM;
8803 smb_io_job_info_2("", buffer, info_2, 0);
8808 /* Cleanup allocated memory */
8810 free_job_info_2(info_2); /* Also frees devmode */
8816 /****************************************************************************
8817 ****************************************************************************/
8819 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8821 POLICY_HND *handle = &q_u->handle;
8822 uint32 jobid = q_u->jobid;
8823 uint32 level = q_u->level;
8824 RPC_BUFFER *buffer = NULL;
8825 uint32 offered = q_u->offered;
8826 uint32 *needed = &r_u->needed;
8827 WERROR wstatus = WERR_OK;
8828 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8831 print_queue_struct *queue = NULL;
8832 print_status_struct prt_status;
8834 /* that's an [in out] buffer */
8836 if ( q_u->buffer ) {
8837 rpcbuf_move(q_u->buffer, &r_u->buffer);
8838 buffer = r_u->buffer;
8841 DEBUG(5,("spoolss_getjob\n"));
8845 if (!get_printer_snum(p, handle, &snum))
8848 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8849 if ( !W_ERROR_IS_OK(wstatus) )
8852 count = print_queue_status(snum, &queue, &prt_status);
8854 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8855 count, prt_status.status, prt_status.message));
8859 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8860 buffer, offered, needed);
8863 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8864 buffer, offered, needed);
8867 wstatus = WERR_UNKNOWN_LEVEL;
8872 free_a_printer( &ntprinter, 2 );
8877 /********************************************************************
8878 spoolss_getprinterdataex
8880 From MSDN documentation of GetPrinterDataEx: pass request
8881 to GetPrinterData if key is "PrinterDriverData".
8882 ********************************************************************/
8884 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8886 POLICY_HND *handle = &q_u->handle;
8887 uint32 in_size = q_u->size;
8888 uint32 *type = &r_u->type;
8889 uint32 *out_size = &r_u->size;
8890 uint8 **data = &r_u->data;
8891 uint32 *needed = &r_u->needed;
8892 fstring keyname, valuename;
8894 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8896 NT_PRINTER_INFO_LEVEL *printer = NULL;
8898 WERROR status = WERR_OK;
8900 DEBUG(4,("_spoolss_getprinterdataex\n"));
8902 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8903 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8905 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8906 keyname, valuename));
8908 /* in case of problem, return some default values */
8912 *out_size = in_size;
8915 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8916 status = WERR_BADFID;
8920 /* Is the handle to a printer or to the server? */
8922 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8923 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8924 status = WERR_INVALID_PARAM;
8928 if ( !get_printer_snum(p,handle, &snum) )
8931 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8932 if ( !W_ERROR_IS_OK(status) )
8935 /* check to see if the keyname is valid */
8936 if ( !strlen(keyname) ) {
8937 status = WERR_INVALID_PARAM;
8941 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8942 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8943 free_a_printer( &printer, 2 );
8944 status = WERR_BADFILE;
8948 /* When given a new keyname, we should just create it */
8950 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8952 if (*needed > *out_size)
8953 status = WERR_MORE_DATA;
8956 if ( !W_ERROR_IS_OK(status) )
8958 DEBUG(5, ("error: allocating %d\n", *out_size));
8960 /* reply this param doesn't exist */
8964 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8965 status = WERR_NOMEM;
8975 free_a_printer( &printer, 2 );
8980 /********************************************************************
8981 * spoolss_setprinterdataex
8982 ********************************************************************/
8984 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8986 POLICY_HND *handle = &q_u->handle;
8987 uint32 type = q_u->type;
8988 uint8 *data = q_u->data;
8989 uint32 real_len = q_u->real_len;
8991 NT_PRINTER_INFO_LEVEL *printer = NULL;
8993 WERROR status = WERR_OK;
8994 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8999 DEBUG(4,("_spoolss_setprinterdataex\n"));
9001 /* From MSDN documentation of SetPrinterDataEx: pass request to
9002 SetPrinterData if key is "PrinterDriverData" */
9005 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9009 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
9010 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9011 return WERR_INVALID_PARAM;
9014 if ( !get_printer_snum(p,handle, &snum) )
9018 * Access check : NT returns "access denied" if you make a
9019 * SetPrinterData call without the necessary privildge.
9020 * we were originally returning OK if nothing changed
9021 * which made Win2k issue **a lot** of SetPrinterData
9022 * when connecting to a printer --jerry
9025 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9027 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9028 return WERR_ACCESS_DENIED;
9031 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9032 if (!W_ERROR_IS_OK(status))
9035 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9036 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9038 /* check for OID in valuename */
9040 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9046 /* save the registry data */
9048 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9050 if ( W_ERROR_IS_OK(status) )
9052 /* save the OID if one was specified */
9054 fstrcat( keyname, "\\" );
9055 fstrcat( keyname, SPOOL_OID_KEY );
9058 * I'm not checking the status here on purpose. Don't know
9059 * if this is right, but I'm returning the status from the
9060 * previous set_printer_dataex() call. I have no idea if
9061 * this is right. --jerry
9064 set_printer_dataex( printer, keyname, valuename,
9065 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9068 status = mod_a_printer(printer, 2);
9071 free_a_printer(&printer, 2);
9077 /********************************************************************
9078 * spoolss_deleteprinterdataex
9079 ********************************************************************/
9081 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9083 POLICY_HND *handle = &q_u->handle;
9084 UNISTR2 *value = &q_u->valuename;
9085 UNISTR2 *key = &q_u->keyname;
9087 NT_PRINTER_INFO_LEVEL *printer = NULL;
9089 WERROR status = WERR_OK;
9090 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9091 pstring valuename, keyname;
9093 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9096 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9100 if (!get_printer_snum(p, handle, &snum))
9103 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9104 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9105 return WERR_ACCESS_DENIED;
9108 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9109 if (!W_ERROR_IS_OK(status))
9112 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9113 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9115 status = delete_printer_dataex( printer, keyname, valuename );
9117 if ( W_ERROR_IS_OK(status) )
9118 mod_a_printer( printer, 2 );
9120 free_a_printer(&printer, 2);
9125 /********************************************************************
9126 * spoolss_enumprinterkey
9127 ********************************************************************/
9130 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9133 fstring *keynames = NULL;
9134 uint16 *enumkeys = NULL;
9137 POLICY_HND *handle = &q_u->handle;
9138 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9139 NT_PRINTER_DATA *data;
9140 NT_PRINTER_INFO_LEVEL *printer = NULL;
9142 WERROR status = WERR_BADFILE;
9145 DEBUG(4,("_spoolss_enumprinterkey\n"));
9148 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9152 if ( !get_printer_snum(p,handle, &snum) )
9155 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9156 if (!W_ERROR_IS_OK(status))
9159 /* get the list of subkey names */
9161 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9162 data = &printer->info_2->data;
9164 num_keys = get_printer_subkeys( data, key, &keynames );
9166 if ( num_keys == -1 ) {
9167 status = WERR_BADFILE;
9171 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9173 r_u->needed = printerkey_len*2;
9175 if ( q_u->size < r_u->needed ) {
9176 status = WERR_MORE_DATA;
9180 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9181 status = WERR_NOMEM;
9187 if ( q_u->size < r_u->needed )
9188 status = WERR_MORE_DATA;
9191 free_a_printer( &printer, 2 );
9192 SAFE_FREE( keynames );
9197 /********************************************************************
9198 * spoolss_deleteprinterkey
9199 ********************************************************************/
9201 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9203 POLICY_HND *handle = &q_u->handle;
9204 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9206 NT_PRINTER_INFO_LEVEL *printer = NULL;
9210 DEBUG(5,("spoolss_deleteprinterkey\n"));
9213 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9217 /* if keyname == NULL, return error */
9219 if ( !q_u->keyname.buffer )
9220 return WERR_INVALID_PARAM;
9222 if (!get_printer_snum(p, handle, &snum))
9225 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9226 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9227 return WERR_ACCESS_DENIED;
9230 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9231 if (!W_ERROR_IS_OK(status))
9234 /* delete the key and all subneys */
9236 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9238 status = delete_all_printer_data( printer->info_2, key );
9240 if ( W_ERROR_IS_OK(status) )
9241 status = mod_a_printer(printer, 2);
9243 free_a_printer( &printer, 2 );
9249 /********************************************************************
9250 * spoolss_enumprinterdataex
9251 ********************************************************************/
9253 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9255 POLICY_HND *handle = &q_u->handle;
9256 uint32 in_size = q_u->size;
9259 NT_PRINTER_INFO_LEVEL *printer = NULL;
9260 PRINTER_ENUM_VALUES *enum_values = NULL;
9261 NT_PRINTER_DATA *p_data;
9263 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9268 REGISTRY_VALUE *val;
9273 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9276 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9281 * first check for a keyname of NULL or "". Win2k seems to send
9282 * this a lot and we should send back WERR_INVALID_PARAM
9283 * no need to spend time looking up the printer in this case.
9287 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9288 if ( !strlen(key) ) {
9289 result = WERR_INVALID_PARAM;
9293 /* get the printer off of disk */
9295 if (!get_printer_snum(p,handle, &snum))
9298 ZERO_STRUCT(printer);
9299 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9300 if (!W_ERROR_IS_OK(result))
9303 /* now look for a match on the key name */
9305 p_data = &printer->info_2->data;
9307 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9308 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9310 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9311 result = WERR_INVALID_PARAM;
9318 /* allocate the memory for the array of pointers -- if necessary */
9320 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9323 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9325 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9326 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9327 result = WERR_NOMEM;
9331 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9335 * loop through all params and build the array to pass
9336 * back to the client
9339 for ( i=0; i<num_entries; i++ )
9341 /* lookup the registry value */
9343 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9344 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9348 value_name = regval_name( val );
9349 init_unistr( &enum_values[i].valuename, value_name );
9350 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9351 enum_values[i].type = regval_type( val );
9353 data_len = regval_size( val );
9355 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9357 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9359 result = WERR_NOMEM;
9363 enum_values[i].data_len = data_len;
9365 /* keep track of the size of the array in bytes */
9367 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9370 /* housekeeping information in the reply */
9372 r_u->needed = needed;
9373 r_u->returned = num_entries;
9375 if (needed > in_size) {
9376 result = WERR_MORE_DATA;
9380 /* copy data into the reply */
9382 r_u->ctr.size = r_u->needed;
9383 r_u->ctr.size_of_array = r_u->returned;
9384 r_u->ctr.values = enum_values;
9390 free_a_printer(&printer, 2);
9395 /****************************************************************************
9396 ****************************************************************************/
9398 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9400 init_unistr(&info->name, name);
9403 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9404 UNISTR2 *environment,
9411 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9412 WERROR result = WERR_OK;
9414 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9416 if (!get_short_archi(long_archi))
9417 return WERR_INVALID_ENVIRONMENT;
9419 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9422 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9424 fill_printprocessordirectory_1(info, path);
9426 *needed += spoolss_size_printprocessordirectory_info_1(info);
9428 if (*needed > offered) {
9429 result = WERR_INSUFFICIENT_BUFFER;
9433 if (!rpcbuf_alloc_size(buffer, *needed)) {
9434 result = WERR_INSUFFICIENT_BUFFER;
9438 smb_io_printprocessordirectory_1("", buffer, info, 0);
9446 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9448 uint32 level = q_u->level;
9449 RPC_BUFFER *buffer = NULL;
9450 uint32 offered = q_u->offered;
9451 uint32 *needed = &r_u->needed;
9454 /* that's an [in out] buffer */
9456 if ( q_u->buffer ) {
9457 rpcbuf_move(q_u->buffer, &r_u->buffer);
9458 buffer = r_u->buffer;
9461 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9467 result = getprintprocessordirectory_level_1
9468 (&q_u->name, &q_u->environment, buffer, offered, needed);
9471 result = WERR_UNKNOWN_LEVEL;
9479 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9480 SPOOL_R_REPLYOPENPRINTER *r_u)
9482 DEBUG(5,("_spoolss_replyopenprinter\n"));
9484 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9489 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9490 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9492 DEBUG(5,("_spoolss_replycloseprinter\n"));