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-2003,
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 */
52 const char *long_archi;
53 const char *short_archi;
57 static Printer_entry *printers_list;
59 typedef struct _counter_printer_0 {
67 static ubi_dlList counter_list;
69 static struct cli_state notify_cli; /* print notify back-channel */
70 static uint32 smb_connections=0;
73 /* in printing/nt_printing.c */
75 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
77 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
78 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
80 /* translate between internal status numbers and NT status numbers */
81 static int nt_printj_status(int v)
87 return JOB_STATUS_PAUSED;
89 return JOB_STATUS_SPOOLING;
91 return JOB_STATUS_PRINTING;
93 return JOB_STATUS_ERROR;
95 return JOB_STATUS_DELETING;
97 return JOB_STATUS_OFFLINE;
99 return JOB_STATUS_PAPEROUT;
101 return JOB_STATUS_PRINTED;
103 return JOB_STATUS_DELETED;
105 return JOB_STATUS_BLOCKED;
106 case LPQ_USER_INTERVENTION:
107 return JOB_STATUS_USER_INTERVENTION;
112 static int nt_printq_status(int v)
116 return PRINTER_STATUS_PAUSED;
125 /****************************************************************************
126 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
127 ****************************************************************************/
129 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
134 SAFE_FREE((*pp)->ctr.type);
138 /***************************************************************************
139 Disconnect from the client
140 ****************************************************************************/
142 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
147 * Tell the specific printing tdb we no longer want messages for this printer
148 * by deregistering our PID.
151 if (!print_notify_deregister_pid(snum))
152 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
154 /* weird if the test succeds !!! */
155 if (smb_connections==0) {
156 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
160 result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle);
162 if (!W_ERROR_IS_OK(result))
163 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
164 dos_errstr(result)));
166 /* if it's the last connection, deconnect the IPC$ share */
167 if (smb_connections==1) {
168 cli_nt_session_close(¬ify_cli);
169 cli_ulogoff(¬ify_cli);
170 cli_shutdown(¬ify_cli);
171 message_deregister(MSG_PRINTER_NOTIFY2);
173 /* Tell the connections db we're no longer interested in
174 * printer notify messages. */
176 register_message_flags( False, FLAG_MSG_PRINTING );
182 /****************************************************************************
183 Functions to free a printer entry datastruct.
184 ****************************************************************************/
186 static void free_printer_entry(void *ptr)
188 Printer_entry *Printer = (Printer_entry *)ptr;
190 if (Printer->notify.client_connected==True) {
193 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
195 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
196 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
197 snum = print_queue_snum(Printer->dev.handlename);
199 srv_spoolss_replycloseprinter(snum,
200 &Printer->notify.client_hnd);
204 Printer->notify.flags=0;
205 Printer->notify.options=0;
206 Printer->notify.localmachine[0]='\0';
207 Printer->notify.printerlocal=0;
208 free_spool_notify_option(&Printer->notify.option);
209 Printer->notify.option=NULL;
210 Printer->notify.client_connected=False;
212 free_nt_devicemode( &Printer->nt_devmode );
213 free_a_printer( &Printer->printer_info, 2 );
215 talloc_destroy( Printer->ctx );
217 /* Remove from the internal list. */
218 DLIST_REMOVE(printers_list, Printer);
223 /****************************************************************************
224 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
225 ****************************************************************************/
227 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
229 SPOOL_NOTIFY_OPTION *new_sp = NULL;
234 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
241 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
243 if (!new_sp->ctr.type) {
252 /****************************************************************************
253 find printer index by handle
254 ****************************************************************************/
256 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
258 Printer_entry *find_printer = NULL;
260 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
261 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
268 /****************************************************************************
269 find printer index by handle
270 ****************************************************************************/
272 void invalidate_printer_hnd_cache( char *printername )
276 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
278 for ( p=printers_list; p; p=p->next )
280 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
281 && StrCaseCmp(p->dev.handlename, printername)==0)
283 DEBUG(10,("invalidating printer_info cache for handl:\n"));
284 free_a_printer( &p->printer_info, 2 );
285 p->printer_info = NULL;
291 /****************************************************************************
292 Close printer index by handle.
293 ****************************************************************************/
295 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
297 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
300 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
304 close_policy_hnd(p, hnd);
309 /****************************************************************************
310 Delete a printer given a handle.
311 ****************************************************************************/
313 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
315 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
318 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
323 * It turns out that Windows allows delete printer on a handle
324 * opened by an admin user, then used on a pipe handle created
325 * by an anonymous user..... but they're working on security.... riiight !
329 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
330 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
331 return WERR_ACCESS_DENIED;
335 /* Check calling user has permission to delete printer. Note that
336 since we set the snum parameter to -1 only administrators can
337 delete the printer. This stops people with the Full Control
338 permission from deleting the printer. */
340 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
341 DEBUG(3, ("printer delete denied by security descriptor\n"));
342 return WERR_ACCESS_DENIED;
346 if (del_a_printer(Printer->dev.handlename) != 0) {
347 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
351 if (*lp_deleteprinter_cmd()) {
353 char *cmd = lp_deleteprinter_cmd();
358 /* Printer->dev.handlename equals portname equals sharename */
359 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
360 Printer->dev.handlename);
362 DEBUG(10,("Running [%s]\n", command));
363 ret = smbrun(command, NULL);
365 return WERR_BADFID; /* What to return here? */
367 DEBUGADD(10,("returned [%d]\n", ret));
369 /* Send SIGHUP to process group... is there a better way? */
372 /* go ahead and re-read the services immediately */
373 reload_services( False );
375 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
376 return WERR_ACCESS_DENIED;
382 /****************************************************************************
383 Return the snum of a printer corresponding to an handle.
384 ****************************************************************************/
386 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
388 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
391 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
395 switch (Printer->printer_type) {
396 case PRINTER_HANDLE_IS_PRINTER:
397 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
398 *number = print_queue_snum(Printer->dev.handlename);
399 return (*number != -1);
400 case PRINTER_HANDLE_IS_PRINTSERVER:
407 /****************************************************************************
408 Set printer handle type.
409 Check if it's \\server or \\server\printer
410 ****************************************************************************/
412 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
414 DEBUG(3,("Setting printer type=%s\n", handlename));
416 if ( strlen(handlename) < 3 ) {
417 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
421 /* it's a print server */
422 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
423 DEBUGADD(4,("Printer is a print server\n"));
424 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
428 DEBUGADD(4,("Printer is a printer\n"));
429 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
435 /****************************************************************************
436 Set printer handle name.
437 ****************************************************************************/
439 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
442 int n_services=lp_numservices();
447 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
449 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
450 ZERO_STRUCT(Printer->dev.printerservername);
451 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
455 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
458 if (*handlename=='\\') {
459 aprinter=strchr_m(handlename+2, '\\');
466 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
469 * The original code allowed smbd to store a printer name that
470 * was different from the share name. This is not possible
471 * anymore, so I've simplified this loop greatly. Here
472 * we are just verifying that the printer name is a valid
473 * printer service defined in smb.conf
474 * --jerry [Fri Feb 15 11:17:46 CST 2002]
477 for (snum=0; snum<n_services; snum++) {
479 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
482 fstrcpy(sname, lp_servicename(snum));
484 DEBUGADD(5,("share:%s\n",sname));
486 if (! StrCaseCmp(sname, aprinter)) {
495 DEBUGADD(4,("Printer not found\n"));
499 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
501 ZERO_STRUCT(Printer->dev.handlename);
502 fstrcpy(Printer->dev.handlename, sname);
507 /****************************************************************************
508 Find first available printer slot. creates a printer handle for you.
509 ****************************************************************************/
511 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
513 Printer_entry *new_printer;
515 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
517 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
520 ZERO_STRUCTP(new_printer);
522 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
523 SAFE_FREE(new_printer);
527 /* Add to the internal list. */
528 DLIST_ADD(printers_list, new_printer);
530 new_printer->notify.option=NULL;
532 if ( !(new_printer->ctx = talloc_init("Printer Entry [0x%x]", (uint32)hnd)) ) {
533 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
534 close_printer_handle(p, hnd);
538 if (!set_printer_hnd_printertype(new_printer, name)) {
539 close_printer_handle(p, hnd);
543 if (!set_printer_hnd_name(new_printer, name)) {
544 close_printer_handle(p, hnd);
548 new_printer->access_granted = access_granted;
550 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
555 /****************************************************************************
556 Allocate more memory for a BUFFER.
557 ****************************************************************************/
559 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
567 /* damn, I'm doing the reverse operation of prs_grow() :) */
568 if (buffer_size < prs_data_size(ps))
571 extra_space = buffer_size - prs_data_size(ps);
574 * save the offset and move to the end of the buffer
575 * prs_grow() checks the extra_space against the offset
577 old_offset=prs_offset(ps);
578 prs_set_offset(ps, prs_data_size(ps));
580 if (!prs_grow(ps, extra_space))
583 prs_set_offset(ps, old_offset);
585 buffer->string_at_end=prs_data_size(ps);
590 /***************************************************************************
591 check to see if the client motify handle is monitoring the notification
592 given by (notify_type, notify_field).
593 **************************************************************************/
595 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
601 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
604 SPOOL_NOTIFY_OPTION *option = p->notify.option;
608 * Flags should always be zero when the change notify
609 * is registered by the client's spooler. A user Win32 app
610 * might use the flags though instead of the NOTIFY_OPTION_INFO
615 return is_monitoring_event_flags(
616 p->notify.flags, notify_type, notify_field);
618 for (i = 0; i < option->count; i++) {
620 /* Check match for notify_type */
622 if (option->ctr.type[i].type != notify_type)
625 /* Check match for field */
627 for (j = 0; j < option->ctr.type[i].count; j++) {
628 if (option->ctr.type[i].fields[j] == notify_field) {
634 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
635 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
636 p->dev.handlename : p->dev.printerservername,
637 notify_type, notify_field));
642 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
644 static void notify_one_value(struct spoolss_notify_msg *msg,
645 SPOOL_NOTIFY_INFO_DATA *data,
648 data->notify_data.value[0] = msg->notify.value[0];
649 data->notify_data.value[1] = 0;
652 static void notify_string(struct spoolss_notify_msg *msg,
653 SPOOL_NOTIFY_INFO_DATA *data,
658 /* The length of the message includes the trailing \0 */
660 init_unistr2(&unistr, msg->notify.data, msg->len);
662 data->notify_data.data.length = msg->len * 2;
663 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
665 if (!data->notify_data.data.string) {
666 data->notify_data.data.length = 0;
670 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
673 static void notify_system_time(struct spoolss_notify_msg *msg,
674 SPOOL_NOTIFY_INFO_DATA *data,
680 if (msg->len != sizeof(time_t)) {
681 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
686 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
687 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
691 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
692 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
696 if (!spoolss_io_system_time("", &ps, 0, &systime))
699 data->notify_data.data.length = prs_offset(&ps);
700 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
702 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
707 struct notify2_message_table {
709 void (*fn)(struct spoolss_notify_msg *msg,
710 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
713 static struct notify2_message_table printer_notify_table[] = {
714 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
715 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
716 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
717 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
718 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
719 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
720 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
721 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
722 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
723 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
724 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
725 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
726 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
727 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
728 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
729 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
730 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
731 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
732 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
735 static struct notify2_message_table job_notify_table[] = {
736 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
737 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
738 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
739 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
740 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
741 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
742 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
743 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
744 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
745 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
746 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
747 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
748 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
749 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
750 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
751 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
752 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
753 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
754 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
755 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
756 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
757 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
758 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
759 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
763 /***********************************************************************
764 Allocate talloc context for container object
765 **********************************************************************/
767 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
772 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
777 /***********************************************************************
778 release all allocated memory and zero out structure
779 **********************************************************************/
781 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
787 talloc_destroy(ctr->ctx);
794 /***********************************************************************
795 **********************************************************************/
797 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
805 /***********************************************************************
806 **********************************************************************/
808 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
810 if ( !ctr || !ctr->msg_groups )
813 if ( idx >= ctr->num_groups )
816 return &ctr->msg_groups[idx];
820 /***********************************************************************
821 How many groups of change messages do we have ?
822 **********************************************************************/
824 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
829 return ctr->num_groups;
832 /***********************************************************************
833 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
834 **********************************************************************/
836 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
838 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
839 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
840 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
846 /* loop over all groups looking for a matching printer name */
848 for ( i=0; i<ctr->num_groups; i++ ) {
849 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
853 /* add a new group? */
855 if ( i == ctr->num_groups ) {
858 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
859 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
862 ctr->msg_groups = groups;
864 /* clear the new entry and set the printer name */
866 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
867 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
870 /* add the change messages; 'i' is the correct index now regardless */
872 msg_grp = &ctr->msg_groups[i];
876 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
877 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
880 msg_grp->msgs = msg_list;
882 new_slot = msg_grp->num_msgs-1;
883 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
885 /* need to allocate own copy of data */
888 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
890 return ctr->num_groups;
893 /***********************************************************************
894 Send a change notication message on all handles which have a call
896 **********************************************************************/
898 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
901 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
902 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
903 SPOOLSS_NOTIFY_MSG *messages;
904 int sending_msg_count;
907 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
911 messages = msg_group->msgs;
914 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
918 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
920 /* loop over all printers */
922 for (p = printers_list; p; p = p->next) {
923 SPOOL_NOTIFY_INFO_DATA *data;
928 /* Is there notification on this handle? */
930 if ( !p->notify.client_connected )
933 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
935 /* For this printer? Print servers always receive
938 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
939 ( !strequal(msg_group->printername, p->dev.handlename) ) )
942 DEBUG(10,("Our printer\n"));
944 /* allocate the max entries possible */
946 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
951 /* build the array of change notifications */
953 sending_msg_count = 0;
955 for ( i=0; i<msg_group->num_msgs; i++ ) {
956 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
958 /* Are we monitoring this event? */
960 if (!is_monitoring_event(p, msg->type, msg->field))
966 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
967 msg->type, msg->field, p->dev.handlename));
970 * if the is a printer notification handle and not a job notification
971 * type, then set the id to 0. Other wise just use what was specified
974 * When registering change notification on a print server handle
975 * we always need to send back the id (snum) matching the printer
976 * for which the change took place. For change notify registered
977 * on a printer handle, this does not matter and the id should be 0.
982 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
988 /* Convert unix jobid to smb jobid */
990 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
991 id = sysjob_to_jobid(msg->id);
994 DEBUG(3, ("no such unix jobid %d\n", msg->id));
999 construct_info_data( &data[data_len], msg->type, msg->field, id );
1002 case PRINTER_NOTIFY_TYPE:
1003 if ( printer_notify_table[msg->field].fn )
1004 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1007 case JOB_NOTIFY_TYPE:
1008 if ( job_notify_table[msg->field].fn )
1009 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1013 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1020 if ( sending_msg_count ) {
1021 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1022 data_len, data, p->notify.change, 0 );
1027 DEBUG(8,("send_notify2_changes: Exit...\n"));
1031 /***********************************************************************
1032 **********************************************************************/
1034 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1037 uint32 tv_sec, tv_usec;
1040 /* Unpack message */
1042 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1045 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1047 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1050 tdb_unpack((char *)buf + offset, len - offset, "dd",
1051 &msg->notify.value[0], &msg->notify.value[1]);
1053 tdb_unpack((char *)buf + offset, len - offset, "B",
1054 &msg->len, &msg->notify.data);
1056 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1057 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1059 tv->tv_sec = tv_sec;
1060 tv->tv_usec = tv_usec;
1063 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1064 msg->notify.value[1]));
1066 dump_data(3, msg->notify.data, msg->len);
1071 /* ENUMJOB last timestamp list. */
1073 struct ejts_list *next, *prev;
1078 static struct ejts_list *ejts_head;
1080 static struct ejts_list *find_enumjobs_timestamp(const char *printer_name)
1082 struct ejts_list *ejtsl;
1084 for( ejtsl = ejts_head; ejtsl; ejtsl = ejtsl->next)
1085 if (strequal(ejtsl->printer_name, printer_name))
1090 static void set_enumjobs_timestamp(int snum)
1092 const char *printer_name = lp_const_servicename(snum);
1093 struct ejts_list *ejtsl = find_enumjobs_timestamp(printer_name);
1096 ejtsl = (struct ejts_list *)malloc(sizeof(struct ejts_list));
1099 ejtsl->printer_name = strdup(printer_name);
1100 if (!ejtsl->printer_name) {
1104 DLIST_ADD(ejts_head, ejtsl);
1107 gettimeofday(&ejtsl->tv, NULL);
1110 static int timeval_diff(struct timeval *tv1, struct timeval *tv2)
1112 if (tv1->tv_sec > tv2->tv_sec)
1114 if (tv1->tv_sec < tv2->tv_sec)
1116 if (tv1->tv_usec > tv2->tv_usec)
1118 if (tv1->tv_usec < tv2->tv_usec)
1123 /********************************************************************
1124 Receive a notify2 message list
1125 ********************************************************************/
1127 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1129 size_t msg_count, i;
1130 char *buf = (char *)msg;
1133 SPOOLSS_NOTIFY_MSG notify;
1134 SPOOLSS_NOTIFY_MSG_CTR messages;
1138 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1142 msg_count = IVAL(buf, 0);
1145 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1147 if (msg_count == 0) {
1148 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1152 /* initialize the container */
1154 ZERO_STRUCT( messages );
1155 notify_msg_ctr_init( &messages );
1158 * build message groups for each printer identified
1159 * in a change_notify msg. Remember that a PCN message
1160 * includes the handle returned for the srv_spoolss_replyopenprinter()
1161 * call. Therefore messages are grouped according to printer handle.
1164 for ( i=0; i<msg_count; i++ ) {
1165 struct timeval msg_tv;
1167 if (msg_ptr + 4 - buf > len) {
1168 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1172 msg_len = IVAL(msg_ptr,0);
1175 if (msg_ptr + msg_len - buf > len) {
1176 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1180 /* unpack messages */
1182 ZERO_STRUCT( notify );
1183 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1186 /* See if it is still relevent. */
1187 if (notify.type == JOB_NOTIFY_TYPE) {
1188 BOOL status_is_deleting = False;
1190 if (notify.field == JOB_NOTIFY_STATUS && (notify.notify.value[0] & (JOB_STATUS_DELETING|JOB_STATUS_DELETED)))
1191 status_is_deleting = True;
1193 if (!status_is_deleting) {
1194 struct ejts_list *ejtsl = find_enumjobs_timestamp(notify.printer);
1196 if (ejtsl && (timeval_diff(&ejtsl->tv, &msg_tv) > 0)) {
1198 DEBUG(10, ("receive_notify2_message_list: enumjobs ts = %u, %u, msg ts = %u, %u discarding\n",
1199 (unsigned int)ejtsl->tv.tv_sec, (unsigned int)ejtsl->tv.tv_usec,
1200 (unsigned int)msg_tv.tv_sec, (unsigned int)msg_tv.tv_usec ));
1202 /* Message no longer relevent. Ignore it. */
1203 if ( notify.len != 0 )
1204 SAFE_FREE( notify.notify.data );
1209 /* add to correct list in container */
1211 notify_msg_ctr_addmsg( &messages, ¬ify );
1213 /* free memory that might have been allocated by notify2_unpack_msg() */
1215 if ( notify.len != 0 )
1216 SAFE_FREE( notify.notify.data );
1219 /* process each group of messages */
1221 num_groups = notify_msg_ctr_numgroups( &messages );
1222 for ( i=0; i<num_groups; i++ )
1223 send_notify2_changes( &messages, i );
1228 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1230 notify_msg_ctr_destroy( &messages );
1235 /********************************************************************
1236 Send a message to ourself about new driver being installed
1237 so we can upgrade the information for each printer bound to this
1239 ********************************************************************/
1241 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1243 int len = strlen(drivername);
1248 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1251 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1256 /**********************************************************************
1257 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1258 over all printers, upgrading ones as necessary
1259 **********************************************************************/
1261 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1265 int n_services = lp_numservices();
1267 len = MIN(len,sizeof(drivername)-1);
1268 strncpy(drivername, buf, len);
1270 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1272 /* Iterate the printer list */
1274 for (snum=0; snum<n_services; snum++)
1276 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1279 NT_PRINTER_INFO_LEVEL *printer = NULL;
1281 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1282 if (!W_ERROR_IS_OK(result))
1285 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1287 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1289 /* all we care about currently is the change_id */
1291 result = mod_a_printer(*printer, 2);
1292 if (!W_ERROR_IS_OK(result)) {
1293 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1294 dos_errstr(result)));
1298 free_a_printer(&printer, 2);
1305 /********************************************************************
1306 Update the cache for all printq's with a registered client
1308 ********************************************************************/
1310 void update_monitored_printq_cache( void )
1312 Printer_entry *printer = printers_list;
1315 /* loop through all printers and update the cache where
1316 client_connected == True */
1319 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1320 && printer->notify.client_connected )
1322 snum = print_queue_snum(printer->dev.handlename);
1323 print_queue_status( snum, NULL, NULL );
1326 printer = printer->next;
1331 /********************************************************************
1332 Send a message to ourself about new driver being installed
1333 so we can upgrade the information for each printer bound to this
1335 ********************************************************************/
1337 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1339 int len = strlen(drivername);
1344 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1347 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1352 /**********************************************************************
1353 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1354 over all printers, resetting printer data as neessary
1355 **********************************************************************/
1357 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1361 int n_services = lp_numservices();
1363 len = MIN( len, sizeof(drivername)-1 );
1364 strncpy( drivername, buf, len );
1366 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1368 /* Iterate the printer list */
1370 for ( snum=0; snum<n_services; snum++ )
1372 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1375 NT_PRINTER_INFO_LEVEL *printer = NULL;
1377 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1378 if ( !W_ERROR_IS_OK(result) )
1382 * if the printer is bound to the driver,
1383 * then reset to the new driver initdata
1386 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1388 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1390 if ( !set_driver_init(printer, 2) ) {
1391 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1392 printer->info_2->printername, printer->info_2->drivername));
1395 result = mod_a_printer( *printer, 2 );
1396 if ( !W_ERROR_IS_OK(result) ) {
1397 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1398 get_dos_error_msg(result)));
1402 free_a_printer( &printer, 2 );
1411 /********************************************************************
1412 Copy routines used by convert_to_openprinterex()
1413 *******************************************************************/
1415 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1423 DEBUG (8,("dup_devmode\n"));
1425 /* bulk copy first */
1427 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1431 /* dup the pointer members separately */
1433 len = unistrlen(devmode->devicename.buffer);
1435 d->devicename.buffer = talloc(ctx, len*2);
1436 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1441 len = unistrlen(devmode->formname.buffer);
1443 d->devicename.buffer = talloc(ctx, len*2);
1444 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1448 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1453 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1455 if (!new_ctr || !ctr)
1458 DEBUG(8,("copy_devmode_ctr\n"));
1460 new_ctr->size = ctr->size;
1461 new_ctr->devmode_ptr = ctr->devmode_ptr;
1463 if(ctr->devmode_ptr)
1464 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1467 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1469 if (!new_def || !def)
1472 DEBUG(8,("copy_printer_defaults\n"));
1474 new_def->datatype_ptr = def->datatype_ptr;
1476 if (def->datatype_ptr)
1477 copy_unistr2(&new_def->datatype, &def->datatype);
1479 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1481 new_def->access_required = def->access_required;
1484 /********************************************************************
1485 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1486 * SPOOL_Q_OPEN_PRINTER_EX structure
1487 ********************************************************************/
1489 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1491 if (!q_u_ex || !q_u)
1494 DEBUG(8,("convert_to_openprinterex\n"));
1496 q_u_ex->printername_ptr = q_u->printername_ptr;
1498 if (q_u->printername_ptr)
1499 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1501 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1504 /********************************************************************
1505 * spoolss_open_printer
1507 * called from the spoolss dispatcher
1508 ********************************************************************/
1510 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1512 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1513 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1518 ZERO_STRUCT(q_u_ex);
1519 ZERO_STRUCT(r_u_ex);
1521 /* convert the OpenPrinter() call to OpenPrinterEx() */
1523 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1525 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1527 /* convert back to OpenPrinter() */
1529 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1534 /********************************************************************
1535 * spoolss_open_printer
1537 * If the openprinterex rpc call contains a devmode,
1538 * it's a per-user one. This per-user devmode is derivated
1539 * from the global devmode. Openprinterex() contains a per-user
1540 * devmode for when you do EMF printing and spooling.
1541 * In the EMF case, the NT workstation is only doing half the job
1542 * of rendering the page. The other half is done by running the printer
1543 * driver on the server.
1544 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1545 * The EMF file only contains what is to be printed on the page.
1546 * So in order for the server to know how to print, the NT client sends
1547 * a devicemode attached to the openprinterex call.
1548 * But this devicemode is short lived, it's only valid for the current print job.
1550 * If Samba would have supported EMF spooling, this devicemode would
1551 * have been attached to the handle, to sent it to the driver to correctly
1552 * rasterize the EMF file.
1554 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1555 * we just act as a pass-thru between windows and the printer.
1557 * In order to know that Samba supports only RAW spooling, NT has to call
1558 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1559 * and until NT sends a RAW job, we refuse it.
1561 * But to call getprinter() or startdoc(), you first need a valid handle,
1562 * and to get an handle you have to call openprintex(). Hence why you have
1563 * a devicemode in the openprinterex() call.
1566 * Differences between NT4 and NT 2000.
1569 * On NT4, you only have a global devicemode. This global devicemode can be changed
1570 * by the administrator (or by a user with enough privs). Everytime a user
1571 * wants to print, the devicemode is resetted to the default. In Word, everytime
1572 * you print, the printer's characteristics are always reset to the global devicemode.
1576 * In W2K, there is the notion of per-user devicemode. The first time you use
1577 * a printer, a per-user devicemode is build from the global devicemode.
1578 * If you change your per-user devicemode, it is saved in the registry, under the
1579 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1580 * printer preferences available.
1582 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1583 * on the General Tab of the printer properties windows.
1585 * To change the global devicemode: it's the "Printing Defaults..." button
1586 * on the Advanced Tab of the printer properties window.
1589 ********************************************************************/
1591 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1593 UNISTR2 *printername = NULL;
1594 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1595 POLICY_HND *handle = &r_u->handle;
1599 struct current_user user;
1600 Printer_entry *Printer=NULL;
1602 if (q_u->printername_ptr != 0)
1603 printername = &q_u->printername;
1605 if (printername == NULL)
1606 return WERR_INVALID_PRINTER_NAME;
1608 /* some sanity check because you can open a printer or a print server */
1609 /* aka: \\server\printer or \\server */
1610 unistr2_to_ascii(name, printername, sizeof(name)-1);
1612 DEBUGADD(3,("checking name: %s\n",name));
1614 if (!open_printer_hnd(p, handle, name, 0))
1615 return WERR_INVALID_PRINTER_NAME;
1617 Printer=find_printer_index_by_hnd(p, handle);
1619 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1620 Can't find printer handle we created for printer %s\n", name ));
1621 close_printer_handle(p,handle);
1622 return WERR_INVALID_PRINTER_NAME;
1625 get_current_user(&user, p);
1628 * First case: the user is opening the print server:
1630 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1631 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1633 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1634 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1635 * or if the user is listed in the smb.conf printer admin parameter.
1637 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1638 * client view printer folder, but does not show the MSAPW.
1640 * Note: this test needs code to check access rights here too. Jeremy
1641 * could you look at this?
1643 * Second case: the user is opening a printer:
1644 * NT doesn't let us connect to a printer if the connecting user
1645 * doesn't have print permission.
1648 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1650 /* Printserver handles use global struct... */
1654 /* Map standard access rights to object specific access rights */
1656 se_map_standard(&printer_default->access_required,
1657 &printserver_std_mapping);
1659 /* Deny any object specific bits that don't apply to print
1660 servers (i.e printer and job specific bits) */
1662 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1664 if (printer_default->access_required &
1665 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1666 DEBUG(3, ("access DENIED for non-printserver bits"));
1667 close_printer_handle(p, handle);
1668 return WERR_ACCESS_DENIED;
1671 /* Allow admin access */
1673 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1675 if (!lp_ms_add_printer_wizard()) {
1676 close_printer_handle(p, handle);
1677 return WERR_ACCESS_DENIED;
1680 /* if the user is not root and not a printer admin, then fail */
1683 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1685 close_printer_handle(p, handle);
1686 return WERR_ACCESS_DENIED;
1689 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1693 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1696 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1697 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1699 /* We fall through to return WERR_OK */
1704 /* NT doesn't let us connect to a printer if the connecting user
1705 doesn't have print permission. */
1707 if (!get_printer_snum(p, handle, &snum)) {
1708 close_printer_handle(p, handle);
1712 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1714 /* map an empty access mask to the minimum access mask */
1715 if (printer_default->access_required == 0x0)
1716 printer_default->access_required = PRINTER_ACCESS_USE;
1719 * If we are not serving the printer driver for this printer,
1720 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1721 * will keep NT clients happy --jerry
1724 if (lp_use_client_driver(snum)
1725 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1727 printer_default->access_required = PRINTER_ACCESS_USE;
1730 /* check smb.conf parameters and the the sec_desc */
1732 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1733 DEBUG(3, ("access DENIED for printer open\n"));
1734 close_printer_handle(p, handle);
1735 return WERR_ACCESS_DENIED;
1738 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1739 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1740 close_printer_handle(p, handle);
1741 return WERR_ACCESS_DENIED;
1744 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1745 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1747 printer_default->access_required = PRINTER_ACCESS_USE;
1749 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1750 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1754 Printer->access_granted = printer_default->access_required;
1757 * If the client sent a devmode in the OpenPrinter() call, then
1758 * save it here in case we get a job submission on this handle
1761 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1762 && q_u->printer_default.devmode_cont.devmode_ptr )
1764 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1765 &Printer->nt_devmode );
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()) )
1780 /****************************************************************************
1781 ****************************************************************************/
1783 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1784 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1790 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1799 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1800 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1806 printer->info_3=NULL;
1807 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1811 printer->info_6=NULL;
1812 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1822 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1823 NT_DEVICEMODE **pp_nt_devmode)
1825 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1828 * Ensure nt_devmode is a valid pointer
1829 * as we will be overwriting it.
1832 if (nt_devmode == NULL) {
1833 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1834 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1838 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1839 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1841 nt_devmode->specversion=devmode->specversion;
1842 nt_devmode->driverversion=devmode->driverversion;
1843 nt_devmode->size=devmode->size;
1844 nt_devmode->fields=devmode->fields;
1845 nt_devmode->orientation=devmode->orientation;
1846 nt_devmode->papersize=devmode->papersize;
1847 nt_devmode->paperlength=devmode->paperlength;
1848 nt_devmode->paperwidth=devmode->paperwidth;
1849 nt_devmode->scale=devmode->scale;
1850 nt_devmode->copies=devmode->copies;
1851 nt_devmode->defaultsource=devmode->defaultsource;
1852 nt_devmode->printquality=devmode->printquality;
1853 nt_devmode->color=devmode->color;
1854 nt_devmode->duplex=devmode->duplex;
1855 nt_devmode->yresolution=devmode->yresolution;
1856 nt_devmode->ttoption=devmode->ttoption;
1857 nt_devmode->collate=devmode->collate;
1859 nt_devmode->logpixels=devmode->logpixels;
1860 nt_devmode->bitsperpel=devmode->bitsperpel;
1861 nt_devmode->pelswidth=devmode->pelswidth;
1862 nt_devmode->pelsheight=devmode->pelsheight;
1863 nt_devmode->displayflags=devmode->displayflags;
1864 nt_devmode->displayfrequency=devmode->displayfrequency;
1865 nt_devmode->icmmethod=devmode->icmmethod;
1866 nt_devmode->icmintent=devmode->icmintent;
1867 nt_devmode->mediatype=devmode->mediatype;
1868 nt_devmode->dithertype=devmode->dithertype;
1869 nt_devmode->reserved1=devmode->reserved1;
1870 nt_devmode->reserved2=devmode->reserved2;
1871 nt_devmode->panningwidth=devmode->panningwidth;
1872 nt_devmode->panningheight=devmode->panningheight;
1875 * Only change private and driverextra if the incoming devmode
1876 * has a new one. JRA.
1879 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1880 SAFE_FREE(nt_devmode->private);
1881 nt_devmode->driverextra=devmode->driverextra;
1882 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1884 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1887 *pp_nt_devmode = nt_devmode;
1892 /********************************************************************
1893 * _spoolss_enddocprinter_internal.
1894 ********************************************************************/
1896 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1898 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1902 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1906 if (!get_printer_snum(p, handle, &snum))
1909 Printer->document_started=False;
1910 print_job_end(snum, Printer->jobid,True);
1911 /* error codes unhandled so far ... */
1916 /********************************************************************
1917 * api_spoolss_closeprinter
1918 ********************************************************************/
1920 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1922 POLICY_HND *handle = &q_u->handle;
1924 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1926 if (Printer && Printer->document_started)
1927 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1929 if (!close_printer_handle(p, handle))
1932 /* clear the returned printer handle. Observed behavior
1933 from Win2k server. Don't think this really matters.
1934 Previous code just copied the value of the closed
1937 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1942 /********************************************************************
1943 * api_spoolss_deleteprinter
1945 ********************************************************************/
1947 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1949 POLICY_HND *handle = &q_u->handle;
1950 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1953 if (Printer && Printer->document_started)
1954 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1956 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1958 result = delete_printer_handle(p, handle);
1960 update_c_setprinter(False);
1965 /*******************************************************************
1966 * static function to lookup the version id corresponding to an
1967 * long architecture string
1968 ******************************************************************/
1970 static int get_version_id (char * arch)
1973 struct table_node archi_table[]= {
1975 {"Windows 4.0", "WIN40", 0 },
1976 {"Windows NT x86", "W32X86", 2 },
1977 {"Windows NT R4000", "W32MIPS", 2 },
1978 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1979 {"Windows NT PowerPC", "W32PPC", 2 },
1983 for (i=0; archi_table[i].long_archi != NULL; i++)
1985 if (strcmp(arch, archi_table[i].long_archi) == 0)
1986 return (archi_table[i].version);
1992 /********************************************************************
1993 * _spoolss_deleteprinterdriver
1994 ********************************************************************/
1996 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2000 NT_PRINTER_DRIVER_INFO_LEVEL info;
2001 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2003 struct current_user user;
2005 WERROR status_win2k = WERR_ACCESS_DENIED;
2007 get_current_user(&user, p);
2009 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2010 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2012 /* check that we have a valid driver name first */
2014 if ((version=get_version_id(arch)) == -1)
2015 return WERR_INVALID_ENVIRONMENT;
2018 ZERO_STRUCT(info_win2k);
2020 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2022 /* try for Win2k driver if "Windows NT x86" */
2024 if ( version == 2 ) {
2026 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2027 status = WERR_UNKNOWN_PRINTER_DRIVER;
2031 /* otherwise it was a failure */
2033 status = WERR_UNKNOWN_PRINTER_DRIVER;
2039 if (printer_driver_in_use(info.info_3)) {
2040 status = WERR_PRINTER_DRIVER_IN_USE;
2046 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2048 /* if we get to here, we now have 2 driver info structures to remove */
2049 /* remove the Win2k driver first*/
2051 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2052 free_a_printer_driver( info_win2k, 3 );
2054 /* this should not have failed---if it did, report to client */
2055 if ( !W_ERROR_IS_OK(status_win2k) )
2060 status = delete_printer_driver(info.info_3, &user, version, False);
2062 /* if at least one of the deletes succeeded return OK */
2064 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2068 free_a_printer_driver( info, 3 );
2073 /********************************************************************
2074 * spoolss_deleteprinterdriverex
2075 ********************************************************************/
2077 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2081 NT_PRINTER_DRIVER_INFO_LEVEL info;
2082 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2084 uint32 flags = q_u->delete_flags;
2086 struct current_user user;
2088 WERROR status_win2k = WERR_ACCESS_DENIED;
2090 get_current_user(&user, p);
2092 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2093 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2095 /* check that we have a valid driver name first */
2096 if ((version=get_version_id(arch)) == -1) {
2097 /* this is what NT returns */
2098 return WERR_INVALID_ENVIRONMENT;
2101 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2102 version = q_u->version;
2105 ZERO_STRUCT(info_win2k);
2107 status = get_a_printer_driver(&info, 3, driver, arch, version);
2109 if ( !W_ERROR_IS_OK(status) )
2112 * if the client asked for a specific version,
2113 * or this is something other than Windows NT x86,
2117 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2120 /* try for Win2k driver if "Windows NT x86" */
2123 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2124 status = WERR_UNKNOWN_PRINTER_DRIVER;
2129 if ( printer_driver_in_use(info.info_3) ) {
2130 status = WERR_PRINTER_DRIVER_IN_USE;
2135 * we have a couple of cases to consider.
2136 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2137 * then the delete should fail if **any** files overlap with
2139 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2140 * non-overlapping files
2141 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2142 * is set, the do not delete any files
2143 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2146 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2148 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2150 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2151 /* no idea of the correct error here */
2152 status = WERR_ACCESS_DENIED;
2157 /* also check for W32X86/3 if necessary; maybe we already have? */
2159 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2160 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2163 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2164 /* no idea of the correct error here */
2165 free_a_printer_driver( info_win2k, 3 );
2166 status = WERR_ACCESS_DENIED;
2170 /* if we get to here, we now have 2 driver info structures to remove */
2171 /* remove the Win2k driver first*/
2173 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2174 free_a_printer_driver( info_win2k, 3 );
2176 /* this should not have failed---if it did, report to client */
2178 if ( !W_ERROR_IS_OK(status_win2k) )
2183 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2185 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2188 free_a_printer_driver( info, 3 );
2194 /****************************************************************************
2195 Internal routine for retreiving printerdata
2196 ***************************************************************************/
2198 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2199 const char *key, const char *value, uint32 *type, uint8 **data,
2200 uint32 *needed, uint32 in_size )
2202 REGISTRY_VALUE *val;
2205 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2206 return WERR_BADFILE;
2208 *type = regval_type( val );
2210 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2212 size = regval_size( val );
2214 /* copy the min(in_size, len) */
2217 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2219 /* special case for 0 length values */
2221 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2225 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2234 DEBUG(5,("get_printer_dataex: copy done\n"));
2239 /****************************************************************************
2240 Internal routine for removing printerdata
2241 ***************************************************************************/
2243 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2245 return delete_printer_data( printer->info_2, key, value );
2248 /****************************************************************************
2249 Internal routine for storing printerdata
2250 ***************************************************************************/
2252 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2253 uint32 type, uint8 *data, int real_len )
2255 delete_printer_data( printer->info_2, key, value );
2257 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2260 /********************************************************************
2261 GetPrinterData on a printer server Handle.
2262 ********************************************************************/
2264 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2268 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2270 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2272 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2278 if (!StrCaseCmp(value, "BeepEnabled")) {
2280 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2282 SIVAL(*data, 0, 0x00);
2287 if (!StrCaseCmp(value, "EventLog")) {
2289 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2291 /* formally was 0x1b */
2292 SIVAL(*data, 0, 0x0);
2297 if (!StrCaseCmp(value, "NetPopup")) {
2299 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2301 SIVAL(*data, 0, 0x00);
2306 if (!StrCaseCmp(value, "MajorVersion")) {
2308 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2311 /* Windows NT 4.0 seems to not allow uploading of drivers
2312 to a server that reports 0x3 as the MajorVersion.
2313 need to investigate more how Win2k gets around this .
2316 if ( RA_WINNT == get_remote_arch() )
2325 if (!StrCaseCmp(value, "MinorVersion")) {
2327 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2336 * uint32 size = 0x114
2338 * uint32 minor = [0|1]
2339 * uint32 build = [2195|2600]
2340 * extra unicode string = e.g. "Service Pack 3"
2342 if (!StrCaseCmp(value, "OSVersion")) {
2344 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2352 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2355 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2357 *needed = 2*(strlen(string)+1);
2358 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2360 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2362 /* it's done by hand ready to go on the wire */
2363 for (i=0; i<strlen(string); i++) {
2364 (*data)[2*i]=string[i];
2365 (*data)[2*i+1]='\0';
2370 if (!StrCaseCmp(value, "Architecture")) {
2371 pstring string="Windows NT x86";
2373 *needed = 2*(strlen(string)+1);
2374 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2376 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2377 for (i=0; i<strlen(string); i++) {
2378 (*data)[2*i]=string[i];
2379 (*data)[2*i+1]='\0';
2384 if (!StrCaseCmp(value, "DsPresent")) {
2386 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2388 SIVAL(*data, 0, 0x01);
2393 if (!StrCaseCmp(value, "DNSMachineName")) {
2396 if (!get_myfullname(hostname))
2397 return WERR_BADFILE;
2399 *needed = 2*(strlen(hostname)+1);
2400 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2402 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2403 for (i=0; i<strlen(hostname); i++) {
2404 (*data)[2*i]=hostname[i];
2405 (*data)[2*i+1]='\0';
2411 return WERR_BADFILE;
2414 /********************************************************************
2415 * spoolss_getprinterdata
2416 ********************************************************************/
2418 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2420 POLICY_HND *handle = &q_u->handle;
2421 UNISTR2 *valuename = &q_u->valuename;
2422 uint32 in_size = q_u->size;
2423 uint32 *type = &r_u->type;
2424 uint32 *out_size = &r_u->size;
2425 uint8 **data = &r_u->data;
2426 uint32 *needed = &r_u->needed;
2429 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2430 NT_PRINTER_INFO_LEVEL *printer = NULL;
2434 * Reminder: when it's a string, the length is in BYTES
2435 * even if UNICODE is negociated.
2440 *out_size = in_size;
2442 /* in case of problem, return some default values */
2447 DEBUG(4,("_spoolss_getprinterdata\n"));
2450 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2451 status = WERR_BADFID;
2455 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2457 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2458 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2461 if ( !get_printer_snum(p,handle, &snum) ) {
2462 status = WERR_BADFID;
2466 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2467 if ( !W_ERROR_IS_OK(status) )
2470 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2472 if ( strequal(value, "ChangeId") ) {
2474 *needed = sizeof(uint32);
2475 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2476 status = WERR_NOMEM;
2479 SIVAL( *data, 0, printer->info_2->changeid );
2483 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2486 if (*needed > *out_size)
2487 status = WERR_MORE_DATA;
2490 if ( !W_ERROR_IS_OK(status) )
2492 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2494 /* reply this param doesn't exist */
2497 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2499 free_a_printer( &printer, 2 );
2508 /* cleanup & exit */
2511 free_a_printer( &printer, 2 );
2516 /*********************************************************
2517 Connect to the client machine.
2518 **********************************************************/
2520 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2521 struct in_addr *client_ip, const char *remote_machine)
2523 ZERO_STRUCTP(the_cli);
2525 if(cli_initialise(the_cli) == NULL) {
2526 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2530 if ( is_zero_ip(*client_ip) ) {
2531 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2532 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2533 cli_shutdown(the_cli);
2537 if (ismyip(the_cli->dest_ip)) {
2538 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2539 cli_shutdown(the_cli);
2544 the_cli->dest_ip.s_addr = client_ip->s_addr;
2545 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2546 inet_ntoa(*client_ip) ));
2549 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2550 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) ));
2551 cli_shutdown(the_cli);
2555 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2556 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2558 cli_shutdown(the_cli);
2562 the_cli->protocol = PROTOCOL_NT1;
2564 if (!cli_negprot(the_cli)) {
2565 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2566 cli_shutdown(the_cli);
2570 if (the_cli->protocol != PROTOCOL_NT1) {
2571 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2572 cli_shutdown(the_cli);
2577 * Do an anonymous session setup.
2580 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2581 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2582 cli_shutdown(the_cli);
2586 if (!(the_cli->sec_mode & 1)) {
2587 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2588 cli_shutdown(the_cli);
2592 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2593 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) ));
2594 cli_shutdown(the_cli);
2599 * Ok - we have an anonymous connection to the IPC$ share.
2600 * Now start the NT Domain stuff :-).
2603 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2604 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)));
2605 cli_nt_session_close(the_cli);
2606 cli_ulogoff(the_cli);
2607 cli_shutdown(the_cli);
2614 /***************************************************************************
2615 Connect to the client.
2616 ****************************************************************************/
2618 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2619 uint32 localprinter, uint32 type,
2620 POLICY_HND *handle, struct in_addr *client_ip)
2625 * If it's the first connection, contact the client
2626 * and connect to the IPC$ share anonymously
2628 if (smb_connections==0) {
2629 fstring unix_printer;
2631 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2633 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2636 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2637 /* Tell the connections db we're now interested in printer
2638 * notify messages. */
2639 register_message_flags( True, FLAG_MSG_PRINTING );
2643 * Tell the specific printing tdb we want messages for this printer
2644 * by registering our PID.
2647 if (!print_notify_register_pid(snum))
2648 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2652 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2655 if (!W_ERROR_IS_OK(result))
2656 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2657 dos_errstr(result)));
2659 return (W_ERROR_IS_OK(result));
2662 /********************************************************************
2664 * ReplyFindFirstPrinterChangeNotifyEx
2666 * before replying OK: status=0 a rpc call is made to the workstation
2667 * asking ReplyOpenPrinter
2669 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2670 * called from api_spoolss_rffpcnex
2671 ********************************************************************/
2673 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2675 POLICY_HND *handle = &q_u->handle;
2676 uint32 flags = q_u->flags;
2677 uint32 options = q_u->options;
2678 UNISTR2 *localmachine = &q_u->localmachine;
2679 uint32 printerlocal = q_u->printerlocal;
2681 SPOOL_NOTIFY_OPTION *option = q_u->option;
2682 struct in_addr client_ip;
2684 /* store the notify value in the printer struct */
2686 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2689 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2693 Printer->notify.flags=flags;
2694 Printer->notify.options=options;
2695 Printer->notify.printerlocal=printerlocal;
2697 if (Printer->notify.option)
2698 free_spool_notify_option(&Printer->notify.option);
2700 Printer->notify.option=dup_spool_notify_option(option);
2702 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2703 sizeof(Printer->notify.localmachine)-1);
2705 /* Connect to the client machine and send a ReplyOpenPrinter */
2707 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2709 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2710 !get_printer_snum(p, handle, &snum) )
2713 client_ip.s_addr = inet_addr(p->conn->client_address);
2715 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2716 Printer->notify.printerlocal, 1,
2717 &Printer->notify.client_hnd, &client_ip))
2718 return WERR_SERVER_UNAVAILABLE;
2720 Printer->notify.client_connected=True;
2725 /*******************************************************************
2726 * fill a notify_info_data with the servername
2727 ********************************************************************/
2729 void spoolss_notify_server_name(int snum,
2730 SPOOL_NOTIFY_INFO_DATA *data,
2731 print_queue_struct *queue,
2732 NT_PRINTER_INFO_LEVEL *printer,
2733 TALLOC_CTX *mem_ctx)
2735 pstring temp_name, temp;
2738 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2740 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2742 data->notify_data.data.length = len;
2743 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2745 if (!data->notify_data.data.string) {
2746 data->notify_data.data.length = 0;
2750 memcpy(data->notify_data.data.string, temp, len);
2753 /*******************************************************************
2754 * fill a notify_info_data with the printername (not including the servername).
2755 ********************************************************************/
2757 void spoolss_notify_printer_name(int snum,
2758 SPOOL_NOTIFY_INFO_DATA *data,
2759 print_queue_struct *queue,
2760 NT_PRINTER_INFO_LEVEL *printer,
2761 TALLOC_CTX *mem_ctx)
2766 /* the notify name should not contain the \\server\ part */
2767 char *p = strrchr(printer->info_2->printername, '\\');
2770 p = printer->info_2->printername;
2775 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2777 data->notify_data.data.length = len;
2778 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2780 if (!data->notify_data.data.string) {
2781 data->notify_data.data.length = 0;
2785 memcpy(data->notify_data.data.string, temp, len);
2788 /*******************************************************************
2789 * fill a notify_info_data with the servicename
2790 ********************************************************************/
2792 void spoolss_notify_share_name(int snum,
2793 SPOOL_NOTIFY_INFO_DATA *data,
2794 print_queue_struct *queue,
2795 NT_PRINTER_INFO_LEVEL *printer,
2796 TALLOC_CTX *mem_ctx)
2801 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2803 data->notify_data.data.length = len;
2804 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2806 if (!data->notify_data.data.string) {
2807 data->notify_data.data.length = 0;
2811 memcpy(data->notify_data.data.string, temp, len);
2814 /*******************************************************************
2815 * fill a notify_info_data with the port name
2816 ********************************************************************/
2818 void spoolss_notify_port_name(int snum,
2819 SPOOL_NOTIFY_INFO_DATA *data,
2820 print_queue_struct *queue,
2821 NT_PRINTER_INFO_LEVEL *printer,
2822 TALLOC_CTX *mem_ctx)
2827 /* even if it's strange, that's consistant in all the code */
2829 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2831 data->notify_data.data.length = len;
2832 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2834 if (!data->notify_data.data.string) {
2835 data->notify_data.data.length = 0;
2839 memcpy(data->notify_data.data.string, temp, len);
2842 /*******************************************************************
2843 * fill a notify_info_data with the printername
2844 * but it doesn't exist, have to see what to do
2845 ********************************************************************/
2847 void spoolss_notify_driver_name(int snum,
2848 SPOOL_NOTIFY_INFO_DATA *data,
2849 print_queue_struct *queue,
2850 NT_PRINTER_INFO_LEVEL *printer,
2851 TALLOC_CTX *mem_ctx)
2856 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2858 data->notify_data.data.length = len;
2859 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2861 if (!data->notify_data.data.string) {
2862 data->notify_data.data.length = 0;
2866 memcpy(data->notify_data.data.string, temp, len);
2869 /*******************************************************************
2870 * fill a notify_info_data with the comment
2871 ********************************************************************/
2873 void spoolss_notify_comment(int snum,
2874 SPOOL_NOTIFY_INFO_DATA *data,
2875 print_queue_struct *queue,
2876 NT_PRINTER_INFO_LEVEL *printer,
2877 TALLOC_CTX *mem_ctx)
2882 if (*printer->info_2->comment == '\0')
2883 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2885 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2887 data->notify_data.data.length = len;
2888 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2890 if (!data->notify_data.data.string) {
2891 data->notify_data.data.length = 0;
2895 memcpy(data->notify_data.data.string, temp, len);
2898 /*******************************************************************
2899 * fill a notify_info_data with the comment
2900 * location = "Room 1, floor 2, building 3"
2901 ********************************************************************/
2903 void spoolss_notify_location(int snum,
2904 SPOOL_NOTIFY_INFO_DATA *data,
2905 print_queue_struct *queue,
2906 NT_PRINTER_INFO_LEVEL *printer,
2907 TALLOC_CTX *mem_ctx)
2912 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2914 data->notify_data.data.length = len;
2915 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2917 if (!data->notify_data.data.string) {
2918 data->notify_data.data.length = 0;
2922 memcpy(data->notify_data.data.string, temp, len);
2925 /*******************************************************************
2926 * fill a notify_info_data with the device mode
2927 * jfm:xxxx don't to it for know but that's a real problem !!!
2928 ********************************************************************/
2930 static void spoolss_notify_devmode(int snum,
2931 SPOOL_NOTIFY_INFO_DATA *data,
2932 print_queue_struct *queue,
2933 NT_PRINTER_INFO_LEVEL *printer,
2934 TALLOC_CTX *mem_ctx)
2938 /*******************************************************************
2939 * fill a notify_info_data with the separator file name
2940 ********************************************************************/
2942 void spoolss_notify_sepfile(int snum,
2943 SPOOL_NOTIFY_INFO_DATA *data,
2944 print_queue_struct *queue,
2945 NT_PRINTER_INFO_LEVEL *printer,
2946 TALLOC_CTX *mem_ctx)
2951 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2953 data->notify_data.data.length = len;
2954 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2956 if (!data->notify_data.data.string) {
2957 data->notify_data.data.length = 0;
2961 memcpy(data->notify_data.data.string, temp, len);
2964 /*******************************************************************
2965 * fill a notify_info_data with the print processor
2966 * jfm:xxxx return always winprint to indicate we don't do anything to it
2967 ********************************************************************/
2969 void spoolss_notify_print_processor(int snum,
2970 SPOOL_NOTIFY_INFO_DATA *data,
2971 print_queue_struct *queue,
2972 NT_PRINTER_INFO_LEVEL *printer,
2973 TALLOC_CTX *mem_ctx)
2978 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2980 data->notify_data.data.length = len;
2981 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2983 if (!data->notify_data.data.string) {
2984 data->notify_data.data.length = 0;
2988 memcpy(data->notify_data.data.string, temp, len);
2991 /*******************************************************************
2992 * fill a notify_info_data with the print processor options
2993 * jfm:xxxx send an empty string
2994 ********************************************************************/
2996 void spoolss_notify_parameters(int snum,
2997 SPOOL_NOTIFY_INFO_DATA *data,
2998 print_queue_struct *queue,
2999 NT_PRINTER_INFO_LEVEL *printer,
3000 TALLOC_CTX *mem_ctx)
3005 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3007 data->notify_data.data.length = len;
3008 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3010 if (!data->notify_data.data.string) {
3011 data->notify_data.data.length = 0;
3015 memcpy(data->notify_data.data.string, temp, len);
3018 /*******************************************************************
3019 * fill a notify_info_data with the data type
3020 * jfm:xxxx always send RAW as data type
3021 ********************************************************************/
3023 void spoolss_notify_datatype(int snum,
3024 SPOOL_NOTIFY_INFO_DATA *data,
3025 print_queue_struct *queue,
3026 NT_PRINTER_INFO_LEVEL *printer,
3027 TALLOC_CTX *mem_ctx)
3032 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3034 data->notify_data.data.length = len;
3035 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3037 if (!data->notify_data.data.string) {
3038 data->notify_data.data.length = 0;
3042 memcpy(data->notify_data.data.string, temp, len);
3045 /*******************************************************************
3046 * fill a notify_info_data with the security descriptor
3047 * jfm:xxxx send an null pointer to say no security desc
3048 * have to implement security before !
3049 ********************************************************************/
3051 static void spoolss_notify_security_desc(int snum,
3052 SPOOL_NOTIFY_INFO_DATA *data,
3053 print_queue_struct *queue,
3054 NT_PRINTER_INFO_LEVEL *printer,
3055 TALLOC_CTX *mem_ctx)
3057 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3058 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3061 /*******************************************************************
3062 * fill a notify_info_data with the attributes
3063 * jfm:xxxx a samba printer is always shared
3064 ********************************************************************/
3066 void spoolss_notify_attributes(int snum,
3067 SPOOL_NOTIFY_INFO_DATA *data,
3068 print_queue_struct *queue,
3069 NT_PRINTER_INFO_LEVEL *printer,
3070 TALLOC_CTX *mem_ctx)
3072 data->notify_data.value[0] = printer->info_2->attributes;
3073 data->notify_data.value[1] = 0;
3076 /*******************************************************************
3077 * fill a notify_info_data with the priority
3078 ********************************************************************/
3080 static void spoolss_notify_priority(int snum,
3081 SPOOL_NOTIFY_INFO_DATA *data,
3082 print_queue_struct *queue,
3083 NT_PRINTER_INFO_LEVEL *printer,
3084 TALLOC_CTX *mem_ctx)
3086 data->notify_data.value[0] = printer->info_2->priority;
3087 data->notify_data.value[1] = 0;
3090 /*******************************************************************
3091 * fill a notify_info_data with the default priority
3092 ********************************************************************/
3094 static void spoolss_notify_default_priority(int snum,
3095 SPOOL_NOTIFY_INFO_DATA *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 data->notify_data.value[0] = printer->info_2->default_priority;
3101 data->notify_data.value[1] = 0;
3104 /*******************************************************************
3105 * fill a notify_info_data with the start time
3106 ********************************************************************/
3108 static void spoolss_notify_start_time(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 data->notify_data.value[0] = printer->info_2->starttime;
3115 data->notify_data.value[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the until time
3120 ********************************************************************/
3122 static void spoolss_notify_until_time(int snum,
3123 SPOOL_NOTIFY_INFO_DATA *data,
3124 print_queue_struct *queue,
3125 NT_PRINTER_INFO_LEVEL *printer,
3126 TALLOC_CTX *mem_ctx)
3128 data->notify_data.value[0] = printer->info_2->untiltime;
3129 data->notify_data.value[1] = 0;
3132 /*******************************************************************
3133 * fill a notify_info_data with the status
3134 ********************************************************************/
3136 static void spoolss_notify_status(int snum,
3137 SPOOL_NOTIFY_INFO_DATA *data,
3138 print_queue_struct *queue,
3139 NT_PRINTER_INFO_LEVEL *printer,
3140 TALLOC_CTX *mem_ctx)
3142 print_status_struct status;
3144 print_queue_length(snum, &status);
3145 data->notify_data.value[0]=(uint32) status.status;
3146 data->notify_data.value[1] = 0;
3149 /*******************************************************************
3150 * fill a notify_info_data with the number of jobs queued
3151 ********************************************************************/
3153 void spoolss_notify_cjobs(int snum,
3154 SPOOL_NOTIFY_INFO_DATA *data,
3155 print_queue_struct *queue,
3156 NT_PRINTER_INFO_LEVEL *printer,
3157 TALLOC_CTX *mem_ctx)
3159 data->notify_data.value[0] = print_queue_length(snum, NULL);
3160 data->notify_data.value[1] = 0;
3163 /*******************************************************************
3164 * fill a notify_info_data with the average ppm
3165 ********************************************************************/
3167 static void spoolss_notify_average_ppm(int snum,
3168 SPOOL_NOTIFY_INFO_DATA *data,
3169 print_queue_struct *queue,
3170 NT_PRINTER_INFO_LEVEL *printer,
3171 TALLOC_CTX *mem_ctx)
3173 /* always respond 8 pages per minutes */
3174 /* a little hard ! */
3175 data->notify_data.value[0] = printer->info_2->averageppm;
3176 data->notify_data.value[1] = 0;
3179 /*******************************************************************
3180 * fill a notify_info_data with username
3181 ********************************************************************/
3183 static void spoolss_notify_username(int snum,
3184 SPOOL_NOTIFY_INFO_DATA *data,
3185 print_queue_struct *queue,
3186 NT_PRINTER_INFO_LEVEL *printer,
3187 TALLOC_CTX *mem_ctx)
3192 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3194 data->notify_data.data.length = len;
3195 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3197 if (!data->notify_data.data.string) {
3198 data->notify_data.data.length = 0;
3202 memcpy(data->notify_data.data.string, temp, len);
3205 /*******************************************************************
3206 * fill a notify_info_data with job status
3207 ********************************************************************/
3209 static void spoolss_notify_job_status(int snum,
3210 SPOOL_NOTIFY_INFO_DATA *data,
3211 print_queue_struct *queue,
3212 NT_PRINTER_INFO_LEVEL *printer,
3213 TALLOC_CTX *mem_ctx)
3215 data->notify_data.value[0]=nt_printj_status(queue->status);
3216 data->notify_data.value[1] = 0;
3219 /*******************************************************************
3220 * fill a notify_info_data with job name
3221 ********************************************************************/
3223 static void spoolss_notify_job_name(int snum,
3224 SPOOL_NOTIFY_INFO_DATA *data,
3225 print_queue_struct *queue,
3226 NT_PRINTER_INFO_LEVEL *printer,
3227 TALLOC_CTX *mem_ctx)
3232 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3234 data->notify_data.data.length = len;
3235 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3237 if (!data->notify_data.data.string) {
3238 data->notify_data.data.length = 0;
3242 memcpy(data->notify_data.data.string, temp, len);
3245 /*******************************************************************
3246 * fill a notify_info_data with job status
3247 ********************************************************************/
3249 static void spoolss_notify_job_status_string(int snum,
3250 SPOOL_NOTIFY_INFO_DATA *data,
3251 print_queue_struct *queue,
3252 NT_PRINTER_INFO_LEVEL *printer,
3253 TALLOC_CTX *mem_ctx)
3256 * Now we're returning job status codes we just return a "" here. JRA.
3263 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3266 switch (queue->status) {
3271 p = ""; /* NT provides the paused string */
3280 #endif /* NO LONGER NEEDED. */
3282 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3284 data->notify_data.data.length = len;
3285 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3287 if (!data->notify_data.data.string) {
3288 data->notify_data.data.length = 0;
3292 memcpy(data->notify_data.data.string, temp, len);
3295 /*******************************************************************
3296 * fill a notify_info_data with job time
3297 ********************************************************************/
3299 static void spoolss_notify_job_time(int snum,
3300 SPOOL_NOTIFY_INFO_DATA *data,
3301 print_queue_struct *queue,
3302 NT_PRINTER_INFO_LEVEL *printer,
3303 TALLOC_CTX *mem_ctx)
3305 data->notify_data.value[0]=0x0;
3306 data->notify_data.value[1]=0;
3309 /*******************************************************************
3310 * fill a notify_info_data with job size
3311 ********************************************************************/
3313 static void spoolss_notify_job_size(int snum,
3314 SPOOL_NOTIFY_INFO_DATA *data,
3315 print_queue_struct *queue,
3316 NT_PRINTER_INFO_LEVEL *printer,
3317 TALLOC_CTX *mem_ctx)
3319 data->notify_data.value[0]=queue->size;
3320 data->notify_data.value[1]=0;
3323 /*******************************************************************
3324 * fill a notify_info_data with page info
3325 ********************************************************************/
3326 static void spoolss_notify_total_pages(int snum,
3327 SPOOL_NOTIFY_INFO_DATA *data,
3328 print_queue_struct *queue,
3329 NT_PRINTER_INFO_LEVEL *printer,
3330 TALLOC_CTX *mem_ctx)
3332 data->notify_data.value[0]=queue->page_count;
3333 data->notify_data.value[1]=0;
3336 /*******************************************************************
3337 * fill a notify_info_data with pages printed info.
3338 ********************************************************************/
3339 static void spoolss_notify_pages_printed(int snum,
3340 SPOOL_NOTIFY_INFO_DATA *data,
3341 print_queue_struct *queue,
3342 NT_PRINTER_INFO_LEVEL *printer,
3343 TALLOC_CTX *mem_ctx)
3345 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3346 data->notify_data.value[1]=0;
3349 /*******************************************************************
3350 Fill a notify_info_data with job position.
3351 ********************************************************************/
3353 static void spoolss_notify_job_position(int snum,
3354 SPOOL_NOTIFY_INFO_DATA *data,
3355 print_queue_struct *queue,
3356 NT_PRINTER_INFO_LEVEL *printer,
3357 TALLOC_CTX *mem_ctx)
3359 data->notify_data.value[0]=queue->job;
3360 data->notify_data.value[1]=0;
3363 /*******************************************************************
3364 Fill a notify_info_data with submitted time.
3365 ********************************************************************/
3367 static void spoolss_notify_submitted_time(int snum,
3368 SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer,
3371 TALLOC_CTX *mem_ctx)
3378 t=gmtime(&queue->time);
3380 len = sizeof(SYSTEMTIME);
3382 data->notify_data.data.length = len;
3383 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3385 if (!data->notify_data.data.string) {
3386 data->notify_data.data.length = 0;
3390 make_systemtime(&st, t);
3393 * Systemtime must be linearized as a set of UINT16's.
3394 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3397 p = (char *)data->notify_data.data.string;
3398 SSVAL(p, 0, st.year);
3399 SSVAL(p, 2, st.month);
3400 SSVAL(p, 4, st.dayofweek);
3401 SSVAL(p, 6, st.day);
3402 SSVAL(p, 8, st.hour);
3403 SSVAL(p, 10, st.minute);
3404 SSVAL(p, 12, st.second);
3405 SSVAL(p, 14, st.milliseconds);
3408 struct s_notify_info_data_table
3414 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3415 print_queue_struct *queue,
3416 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3419 /* A table describing the various print notification constants and
3420 whether the notification data is a pointer to a variable sized
3421 buffer, a one value uint32 or a two value uint32. */
3423 static const struct s_notify_info_data_table notify_info_data_table[] =
3425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3452 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3453 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3454 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3455 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3456 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3457 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3458 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3463 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3476 /*******************************************************************
3477 Return the size of info_data structure.
3478 ********************************************************************/
3480 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3484 for (i = 0; i < sizeof(notify_info_data_table); i++)
3486 if ( (notify_info_data_table[i].type == type)
3487 && (notify_info_data_table[i].field == field) )
3489 switch(notify_info_data_table[i].size)
3491 case NOTIFY_ONE_VALUE:
3492 case NOTIFY_TWO_VALUE:
3497 /* The only pointer notify data I have seen on
3498 the wire is the submitted time and this has
3499 the notify size set to 4. -tpot */
3501 case NOTIFY_POINTER:
3504 case NOTIFY_SECDESC:
3510 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3515 /*******************************************************************
3516 Return the type of notify_info_data.
3517 ********************************************************************/
3519 static int type_of_notify_info_data(uint16 type, uint16 field)
3523 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3524 if (notify_info_data_table[i].type == type &&
3525 notify_info_data_table[i].field == field)
3526 return notify_info_data_table[i].size;
3532 /****************************************************************************
3533 ****************************************************************************/
3535 static int search_notify(uint16 type, uint16 field, int *value)
3539 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3540 if (notify_info_data_table[i].type == type &&
3541 notify_info_data_table[i].field == field &&
3542 notify_info_data_table[i].fn != NULL) {
3551 /****************************************************************************
3552 ****************************************************************************/
3554 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3556 info_data->type = type;
3557 info_data->field = field;
3558 info_data->reserved = 0;
3560 info_data->size = size_of_notify_info_data(type, field);
3561 info_data->enc_type = type_of_notify_info_data(type, field);
3568 /*******************************************************************
3570 * fill a notify_info struct with info asked
3572 ********************************************************************/
3574 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3575 snum, SPOOL_NOTIFY_OPTION_TYPE
3576 *option_type, uint32 id,
3577 TALLOC_CTX *mem_ctx)
3583 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3584 NT_PRINTER_INFO_LEVEL *printer = NULL;
3585 print_queue_struct *queue=NULL;
3587 type=option_type->type;
3589 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3590 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3591 option_type->count, lp_servicename(snum)));
3593 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3596 for(field_num=0; field_num<option_type->count; field_num++) {
3597 field = option_type->fields[field_num];
3599 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3601 if (!search_notify(type, field, &j) )
3604 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3605 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3610 current_data = &info->data[info->count];
3612 construct_info_data(current_data, type, field, id);
3614 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3615 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3617 notify_info_data_table[j].fn(snum, current_data, queue,
3623 free_a_printer(&printer, 2);
3627 /*******************************************************************
3629 * fill a notify_info struct with info asked
3631 ********************************************************************/
3633 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3634 SPOOL_NOTIFY_INFO *info,
3635 NT_PRINTER_INFO_LEVEL *printer,
3636 int snum, SPOOL_NOTIFY_OPTION_TYPE
3637 *option_type, uint32 id,
3638 TALLOC_CTX *mem_ctx)
3644 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3646 DEBUG(4,("construct_notify_jobs_info\n"));
3648 type = option_type->type;
3650 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3651 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3652 option_type->count));
3654 for(field_num=0; field_num<option_type->count; field_num++) {
3655 field = option_type->fields[field_num];
3657 if (!search_notify(type, field, &j) )
3660 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3661 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3664 else info->data = tid;
3666 current_data=&(info->data[info->count]);
3668 construct_info_data(current_data, type, field, id);
3669 notify_info_data_table[j].fn(snum, current_data, queue,
3678 * JFM: The enumeration is not that simple, it's even non obvious.
3680 * let's take an example: I want to monitor the PRINTER SERVER for
3681 * the printer's name and the number of jobs currently queued.
3682 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3683 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3685 * I have 3 printers on the back of my server.
3687 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3690 * 1 printer 1 name 1
3691 * 2 printer 1 cjob 1
3692 * 3 printer 2 name 2
3693 * 4 printer 2 cjob 2
3694 * 5 printer 3 name 3
3695 * 6 printer 3 name 3
3697 * that's the print server case, the printer case is even worse.
3700 /*******************************************************************
3702 * enumerate all printers on the printserver
3703 * fill a notify_info struct with info asked
3705 ********************************************************************/
3707 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3708 SPOOL_NOTIFY_INFO *info,
3709 TALLOC_CTX *mem_ctx)
3712 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3713 int n_services=lp_numservices();
3716 SPOOL_NOTIFY_OPTION *option;
3717 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3719 DEBUG(4,("printserver_notify_info\n"));
3724 option=Printer->notify.option;
3730 for (i=0; i<option->count; i++) {
3731 option_type=&(option->ctr.type[i]);
3733 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3736 for (snum=0; snum<n_services; snum++)
3738 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3739 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3745 * Debugging information, don't delete.
3748 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3749 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3750 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3752 for (i=0; i<info->count; i++) {
3753 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3754 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3755 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3762 /*******************************************************************
3764 * fill a notify_info struct with info asked
3766 ********************************************************************/
3768 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3769 TALLOC_CTX *mem_ctx)
3772 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3775 SPOOL_NOTIFY_OPTION *option;
3776 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3778 print_queue_struct *queue=NULL;
3779 print_status_struct status;
3781 DEBUG(4,("printer_notify_info\n"));
3786 option=Printer->notify.option;
3792 get_printer_snum(p, hnd, &snum);
3794 for (i=0; i<option->count; i++) {
3795 option_type=&option->ctr.type[i];
3797 switch ( option_type->type ) {
3798 case PRINTER_NOTIFY_TYPE:
3799 if(construct_notify_printer_info(Printer, info, snum,
3805 case JOB_NOTIFY_TYPE: {
3806 NT_PRINTER_INFO_LEVEL *printer = NULL;
3808 count = print_queue_status(snum, &queue, &status);
3810 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3813 for (j=0; j<count; j++) {
3814 construct_notify_jobs_info(&queue[j], info,
3821 free_a_printer(&printer, 2);
3831 * Debugging information, don't delete.
3834 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3835 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3836 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3838 for (i=0; i<info->count; i++) {
3839 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3840 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3841 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3847 /********************************************************************
3849 ********************************************************************/
3851 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3853 POLICY_HND *handle = &q_u->handle;
3854 SPOOL_NOTIFY_INFO *info = &r_u->info;
3856 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3857 WERROR result = WERR_BADFID;
3859 /* we always have a NOTIFY_INFO struct */
3863 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3864 OUR_HANDLE(handle)));
3868 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3871 * We are now using the change value, and
3872 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3873 * I don't have a global notification system, I'm sending back all the
3874 * informations even when _NOTHING_ has changed.
3877 /* We need to keep track of the change value to send back in
3878 RRPCN replies otherwise our updates are ignored. */
3880 Printer->notify.fnpcn = True;
3882 if (Printer->notify.client_connected) {
3883 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3884 Printer->notify.change = q_u->change;
3887 /* just ignore the SPOOL_NOTIFY_OPTION */
3889 switch (Printer->printer_type) {
3890 case PRINTER_HANDLE_IS_PRINTSERVER:
3891 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3894 case PRINTER_HANDLE_IS_PRINTER:
3895 result = printer_notify_info(p, handle, info, p->mem_ctx);
3899 Printer->notify.fnpcn = False;
3905 /********************************************************************
3906 * construct_printer_info_0
3907 * fill a printer_info_0 struct
3908 ********************************************************************/
3910 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3914 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3915 counter_printer_0 *session_counter;
3916 uint32 global_counter;
3919 print_status_struct status;
3921 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3924 count = print_queue_length(snum, &status);
3926 /* check if we already have a counter for this printer */
3927 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3929 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3930 if (session_counter->snum == snum)
3934 /* it's the first time, add it to the list */
3935 if (session_counter==NULL) {
3936 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3937 free_a_printer(&ntprinter, 2);
3940 ZERO_STRUCTP(session_counter);
3941 session_counter->snum=snum;
3942 session_counter->counter=0;
3943 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3947 session_counter->counter++;
3950 * the global_counter should be stored in a TDB as it's common to all the clients
3951 * and should be zeroed on samba startup
3953 global_counter=session_counter->counter;
3955 pstrcpy(chaine,ntprinter->info_2->printername);
3957 init_unistr(&printer->printername, chaine);
3959 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3960 init_unistr(&printer->servername, chaine);
3962 printer->cjobs = count;
3963 printer->total_jobs = 0;
3964 printer->total_bytes = 0;
3966 setuptime = (time_t)ntprinter->info_2->setuptime;
3967 t=gmtime(&setuptime);
3969 printer->year = t->tm_year+1900;
3970 printer->month = t->tm_mon+1;
3971 printer->dayofweek = t->tm_wday;
3972 printer->day = t->tm_mday;
3973 printer->hour = t->tm_hour;
3974 printer->minute = t->tm_min;
3975 printer->second = t->tm_sec;
3976 printer->milliseconds = 0;
3978 printer->global_counter = global_counter;
3979 printer->total_pages = 0;
3981 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3982 printer->major_version = 0x0005; /* NT 5 */
3983 printer->build_version = 0x0893; /* build 2195 */
3985 printer->unknown7 = 0x1;
3986 printer->unknown8 = 0x0;
3987 printer->unknown9 = 0x0;
3988 printer->session_counter = session_counter->counter;
3989 printer->unknown11 = 0x0;
3990 printer->printer_errors = 0x0; /* number of print failure */
3991 printer->unknown13 = 0x0;
3992 printer->unknown14 = 0x1;
3993 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3994 printer->unknown16 = 0x0;
3995 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3996 printer->unknown18 = 0x0;
3997 printer->status = nt_printq_status(status.status);
3998 printer->unknown20 = 0x0;
3999 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4000 printer->unknown22 = 0x0;
4001 printer->unknown23 = 0x6; /* 6 ???*/
4002 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4003 printer->unknown25 = 0;
4004 printer->unknown26 = 0;
4005 printer->unknown27 = 0;
4006 printer->unknown28 = 0;
4007 printer->unknown29 = 0;
4009 free_a_printer(&ntprinter,2);
4013 /********************************************************************
4014 * construct_printer_info_1
4015 * fill a printer_info_1 struct
4016 ********************************************************************/
4017 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4021 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4023 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4026 printer->flags=flags;
4028 if (*ntprinter->info_2->comment == '\0') {
4029 init_unistr(&printer->comment, lp_comment(snum));
4030 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4031 ntprinter->info_2->drivername, lp_comment(snum));
4034 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4035 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4036 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4039 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4041 init_unistr(&printer->description, chaine);
4042 init_unistr(&printer->name, chaine2);
4044 free_a_printer(&ntprinter,2);
4049 /****************************************************************************
4050 Free a DEVMODE struct.
4051 ****************************************************************************/
4053 static void free_dev_mode(DEVICEMODE *dev)
4058 SAFE_FREE(dev->private);
4063 /****************************************************************************
4064 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4065 should be valid upon entry
4066 ****************************************************************************/
4068 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4070 if ( !devmode || !ntdevmode )
4073 init_unistr(&devmode->devicename, ntdevmode->devicename);
4075 init_unistr(&devmode->formname, ntdevmode->formname);
4077 devmode->specversion = ntdevmode->specversion;
4078 devmode->driverversion = ntdevmode->driverversion;
4079 devmode->size = ntdevmode->size;
4080 devmode->driverextra = ntdevmode->driverextra;
4081 devmode->fields = ntdevmode->fields;
4083 devmode->orientation = ntdevmode->orientation;
4084 devmode->papersize = ntdevmode->papersize;
4085 devmode->paperlength = ntdevmode->paperlength;
4086 devmode->paperwidth = ntdevmode->paperwidth;
4087 devmode->scale = ntdevmode->scale;
4088 devmode->copies = ntdevmode->copies;
4089 devmode->defaultsource = ntdevmode->defaultsource;
4090 devmode->printquality = ntdevmode->printquality;
4091 devmode->color = ntdevmode->color;
4092 devmode->duplex = ntdevmode->duplex;
4093 devmode->yresolution = ntdevmode->yresolution;
4094 devmode->ttoption = ntdevmode->ttoption;
4095 devmode->collate = ntdevmode->collate;
4096 devmode->icmmethod = ntdevmode->icmmethod;
4097 devmode->icmintent = ntdevmode->icmintent;
4098 devmode->mediatype = ntdevmode->mediatype;
4099 devmode->dithertype = ntdevmode->dithertype;
4101 if (ntdevmode->private != NULL) {
4102 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4109 /****************************************************************************
4110 Create a DEVMODE struct. Returns malloced memory.
4111 ****************************************************************************/
4113 DEVICEMODE *construct_dev_mode(int snum)
4115 NT_PRINTER_INFO_LEVEL *printer = NULL;
4116 DEVICEMODE *devmode = NULL;
4118 DEBUG(7,("construct_dev_mode\n"));
4120 DEBUGADD(8,("getting printer characteristics\n"));
4122 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4125 if ( !printer->info_2->devmode ) {
4126 DEBUG(5, ("BONG! There was no device mode!\n"));
4130 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4131 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4135 ZERO_STRUCTP(devmode);
4137 DEBUGADD(8,("loading DEVICEMODE\n"));
4139 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4140 free_dev_mode( devmode );
4145 free_a_printer(&printer,2);
4150 /********************************************************************
4151 * construct_printer_info_2
4152 * fill a printer_info_2 struct
4153 ********************************************************************/
4155 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4158 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4160 print_status_struct status;
4162 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4165 count = print_queue_length(snum, &status);
4167 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4168 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4169 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4170 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4171 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4173 if (*ntprinter->info_2->comment == '\0')
4174 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4176 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4178 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4179 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4180 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4181 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4182 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4184 printer->attributes = ntprinter->info_2->attributes;
4186 printer->priority = ntprinter->info_2->priority; /* priority */
4187 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4188 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4189 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4190 printer->status = nt_printq_status(status.status); /* status */
4191 printer->cjobs = count; /* jobs */
4192 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4194 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4195 DEBUG(8, ("Returning NULL Devicemode!\n"));
4198 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4199 /* steal the printer info sec_desc structure. [badly done]. */
4200 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4201 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4202 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4203 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4206 printer->secdesc = NULL;
4209 free_a_printer(&ntprinter, 2);
4213 /********************************************************************
4214 * construct_printer_info_3
4215 * fill a printer_info_3 struct
4216 ********************************************************************/
4218 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4220 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4221 PRINTER_INFO_3 *printer = NULL;
4223 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4227 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4228 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4232 ZERO_STRUCTP(printer);
4234 printer->flags = 4; /* These are the components of the SD we are returning. */
4235 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4236 /* steal the printer info sec_desc structure. [badly done]. */
4237 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4241 * Set the flags for the components we are returning.
4244 if (printer->secdesc->owner_sid)
4245 printer->flags |= OWNER_SECURITY_INFORMATION;
4247 if (printer->secdesc->grp_sid)
4248 printer->flags |= GROUP_SECURITY_INFORMATION;
4250 if (printer->secdesc->dacl)
4251 printer->flags |= DACL_SECURITY_INFORMATION;
4253 if (printer->secdesc->sacl)
4254 printer->flags |= SACL_SECURITY_INFORMATION;
4257 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4258 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4259 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4262 free_a_printer(&ntprinter, 2);
4264 *pp_printer = printer;
4268 /********************************************************************
4269 * construct_printer_info_4
4270 * fill a printer_info_4 struct
4271 ********************************************************************/
4273 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4275 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4277 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4280 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4281 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4282 printer->attributes = ntprinter->info_2->attributes;
4284 free_a_printer(&ntprinter, 2);
4288 /********************************************************************
4289 * construct_printer_info_5
4290 * fill a printer_info_5 struct
4291 ********************************************************************/
4293 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4295 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4297 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4300 init_unistr(&printer->printername, ntprinter->info_2->printername);
4301 init_unistr(&printer->portname, ntprinter->info_2->portname);
4302 printer->attributes = ntprinter->info_2->attributes;
4304 /* these two are not used by NT+ according to MSDN */
4306 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4307 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4309 free_a_printer(&ntprinter, 2);
4314 /********************************************************************
4315 * construct_printer_info_7
4316 * fill a printer_info_7 struct
4317 ********************************************************************/
4319 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4321 char *guid_str = NULL;
4324 if (is_printer_published(print_hnd, snum, &guid)) {
4325 asprintf(&guid_str, "{%s}", uuid_string_static(guid));
4327 init_unistr(&printer->guid, guid_str);
4328 printer->action = SPOOL_DS_PUBLISH;
4330 init_unistr(&printer->guid, "");
4331 printer->action = SPOOL_DS_UNPUBLISH;
4337 /********************************************************************
4338 Spoolss_enumprinters.
4339 ********************************************************************/
4341 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4345 int n_services=lp_numservices();
4346 PRINTER_INFO_1 *tp, *printers=NULL;
4347 PRINTER_INFO_1 current_prt;
4349 DEBUG(4,("enum_all_printers_info_1\n"));
4351 for (snum=0; snum<n_services; snum++) {
4352 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4353 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4355 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4356 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4357 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4358 SAFE_FREE(printers);
4363 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4365 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4371 /* check the required size. */
4372 for (i=0; i<*returned; i++)
4373 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4375 if (!alloc_buffer_size(buffer, *needed))
4376 return WERR_INSUFFICIENT_BUFFER;
4378 /* fill the buffer with the structures */
4379 for (i=0; i<*returned; i++)
4380 smb_io_printer_info_1("", buffer, &printers[i], 0);
4383 SAFE_FREE(printers);
4385 if (*needed > offered) {
4387 return WERR_INSUFFICIENT_BUFFER;
4393 /********************************************************************
4394 enum_all_printers_info_1_local.
4395 *********************************************************************/
4397 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4399 DEBUG(4,("enum_all_printers_info_1_local\n"));
4401 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4404 /********************************************************************
4405 enum_all_printers_info_1_name.
4406 *********************************************************************/
4408 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4412 DEBUG(4,("enum_all_printers_info_1_name\n"));
4414 if ((name[0] == '\\') && (name[1] == '\\'))
4417 if (is_myname_or_ipaddr(s)) {
4418 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4421 return WERR_INVALID_NAME;
4424 /********************************************************************
4425 enum_all_printers_info_1_remote.
4426 *********************************************************************/
4428 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4430 PRINTER_INFO_1 *printer;
4431 fstring printername;
4434 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4436 /* JFM: currently it's more a place holder than anything else.
4437 * In the spooler world there is a notion of server registration.
4438 * the print servers are registring (sp ?) on the PDC (in the same domain)
4440 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4443 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4448 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4449 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4450 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4452 init_unistr(&printer->description, desc);
4453 init_unistr(&printer->name, printername);
4454 init_unistr(&printer->comment, comment);
4455 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4457 /* check the required size. */
4458 *needed += spoolss_size_printer_info_1(printer);
4460 if (!alloc_buffer_size(buffer, *needed)) {
4462 return WERR_INSUFFICIENT_BUFFER;
4465 /* fill the buffer with the structures */
4466 smb_io_printer_info_1("", buffer, printer, 0);
4471 if (*needed > offered) {
4473 return WERR_INSUFFICIENT_BUFFER;
4479 /********************************************************************
4480 enum_all_printers_info_1_network.
4481 *********************************************************************/
4483 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4487 DEBUG(4,("enum_all_printers_info_1_network\n"));
4489 /* If we respond to a enum_printers level 1 on our name with flags
4490 set to PRINTER_ENUM_REMOTE with a list of printers then these
4491 printers incorrectly appear in the APW browse list.
4492 Specifically the printers for the server appear at the workgroup
4493 level where all the other servers in the domain are
4494 listed. Windows responds to this call with a
4495 WERR_CAN_NOT_COMPLETE so we should do the same. */
4497 if (name[0] == '\\' && name[1] == '\\')
4500 if (is_myname_or_ipaddr(s))
4501 return WERR_CAN_NOT_COMPLETE;
4503 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4506 /********************************************************************
4507 * api_spoolss_enumprinters
4509 * called from api_spoolss_enumprinters (see this to understand)
4510 ********************************************************************/
4512 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4516 int n_services=lp_numservices();
4517 PRINTER_INFO_2 *tp, *printers=NULL;
4518 PRINTER_INFO_2 current_prt;
4520 for (snum=0; snum<n_services; snum++) {
4521 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4522 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4524 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4525 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4526 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4527 SAFE_FREE(printers);
4532 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4533 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4539 /* check the required size. */
4540 for (i=0; i<*returned; i++)
4541 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4543 if (!alloc_buffer_size(buffer, *needed)) {
4544 for (i=0; i<*returned; i++) {
4545 free_devmode(printers[i].devmode);
4547 SAFE_FREE(printers);
4548 return WERR_INSUFFICIENT_BUFFER;
4551 /* fill the buffer with the structures */
4552 for (i=0; i<*returned; i++)
4553 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4556 for (i=0; i<*returned; i++) {
4557 free_devmode(printers[i].devmode);
4559 SAFE_FREE(printers);
4561 if (*needed > offered) {
4563 return WERR_INSUFFICIENT_BUFFER;
4569 /********************************************************************
4570 * handle enumeration of printers at level 1
4571 ********************************************************************/
4573 static WERROR enumprinters_level1( uint32 flags, fstring name,
4574 NEW_BUFFER *buffer, uint32 offered,
4575 uint32 *needed, uint32 *returned)
4577 /* Not all the flags are equals */
4579 if (flags & PRINTER_ENUM_LOCAL)
4580 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4582 if (flags & PRINTER_ENUM_NAME)
4583 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4585 if (flags & PRINTER_ENUM_REMOTE)
4586 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4588 if (flags & PRINTER_ENUM_NETWORK)
4589 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4591 return WERR_OK; /* NT4sp5 does that */
4594 /********************************************************************
4595 * handle enumeration of printers at level 2
4596 ********************************************************************/
4598 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4599 NEW_BUFFER *buffer, uint32 offered,
4600 uint32 *needed, uint32 *returned)
4602 char *s = servername;
4604 if (flags & PRINTER_ENUM_LOCAL) {
4605 return enum_all_printers_info_2(buffer, offered, needed, returned);
4608 if (flags & PRINTER_ENUM_NAME) {
4609 if ((servername[0] == '\\') && (servername[1] == '\\'))
4611 if (is_myname_or_ipaddr(s))
4612 return enum_all_printers_info_2(buffer, offered, needed, returned);
4614 return WERR_INVALID_NAME;
4617 if (flags & PRINTER_ENUM_REMOTE)
4618 return WERR_UNKNOWN_LEVEL;
4623 /********************************************************************
4624 * handle enumeration of printers at level 5
4625 ********************************************************************/
4627 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4628 NEW_BUFFER *buffer, uint32 offered,
4629 uint32 *needed, uint32 *returned)
4631 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4635 /********************************************************************
4636 * api_spoolss_enumprinters
4638 * called from api_spoolss_enumprinters (see this to understand)
4639 ********************************************************************/
4641 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4643 uint32 flags = q_u->flags;
4644 UNISTR2 *servername = &q_u->servername;
4645 uint32 level = q_u->level;
4646 NEW_BUFFER *buffer = NULL;
4647 uint32 offered = q_u->offered;
4648 uint32 *needed = &r_u->needed;
4649 uint32 *returned = &r_u->returned;
4653 /* that's an [in out] buffer */
4654 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4655 buffer = r_u->buffer;
4657 DEBUG(4,("_spoolss_enumprinters\n"));
4664 * flags==PRINTER_ENUM_NAME
4665 * if name=="" then enumerates all printers
4666 * if name!="" then enumerate the printer
4667 * flags==PRINTER_ENUM_REMOTE
4668 * name is NULL, enumerate printers
4669 * Level 2: name!="" enumerates printers, name can't be NULL
4670 * Level 3: doesn't exist
4671 * Level 4: does a local registry lookup
4672 * Level 5: same as Level 2
4675 unistr2_to_ascii(name, servername, sizeof(name)-1);
4680 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4682 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4684 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4689 return WERR_UNKNOWN_LEVEL;
4692 /****************************************************************************
4693 ****************************************************************************/
4695 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4697 PRINTER_INFO_0 *printer=NULL;
4699 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4702 construct_printer_info_0(print_hnd, printer, snum);
4704 /* check the required size. */
4705 *needed += spoolss_size_printer_info_0(printer);
4707 if (!alloc_buffer_size(buffer, *needed)) {
4709 return WERR_INSUFFICIENT_BUFFER;
4712 /* fill the buffer with the structures */
4713 smb_io_printer_info_0("", buffer, printer, 0);
4718 if (*needed > offered) {
4719 return WERR_INSUFFICIENT_BUFFER;
4725 /****************************************************************************
4726 ****************************************************************************/
4728 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4730 PRINTER_INFO_1 *printer=NULL;
4732 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4735 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4737 /* check the required size. */
4738 *needed += spoolss_size_printer_info_1(printer);
4740 if (!alloc_buffer_size(buffer, *needed)) {
4742 return WERR_INSUFFICIENT_BUFFER;
4745 /* fill the buffer with the structures */
4746 smb_io_printer_info_1("", buffer, printer, 0);
4751 if (*needed > offered) {
4752 return WERR_INSUFFICIENT_BUFFER;
4758 /****************************************************************************
4759 ****************************************************************************/
4761 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4763 PRINTER_INFO_2 *printer=NULL;
4765 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4768 construct_printer_info_2(print_hnd, printer, snum);
4770 /* check the required size. */
4771 *needed += spoolss_size_printer_info_2(printer);
4773 if (!alloc_buffer_size(buffer, *needed)) {
4774 free_printer_info_2(printer);
4775 return WERR_INSUFFICIENT_BUFFER;
4778 /* fill the buffer with the structures */
4779 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4780 free_printer_info_2(printer);
4785 free_printer_info_2(printer);
4787 if (*needed > offered) {
4788 return WERR_INSUFFICIENT_BUFFER;
4794 /****************************************************************************
4795 ****************************************************************************/
4797 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4799 PRINTER_INFO_3 *printer=NULL;
4801 if (!construct_printer_info_3(print_hnd, &printer, snum))
4804 /* check the required size. */
4805 *needed += spoolss_size_printer_info_3(printer);
4807 if (!alloc_buffer_size(buffer, *needed)) {
4808 free_printer_info_3(printer);
4809 return WERR_INSUFFICIENT_BUFFER;
4812 /* fill the buffer with the structures */
4813 smb_io_printer_info_3("", buffer, printer, 0);
4816 free_printer_info_3(printer);
4818 if (*needed > offered) {
4819 return WERR_INSUFFICIENT_BUFFER;
4825 /****************************************************************************
4826 ****************************************************************************/
4828 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4830 PRINTER_INFO_4 *printer=NULL;
4832 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4835 if (!construct_printer_info_4(print_hnd, printer, snum))
4838 /* check the required size. */
4839 *needed += spoolss_size_printer_info_4(printer);
4841 if (!alloc_buffer_size(buffer, *needed)) {
4842 free_printer_info_4(printer);
4843 return WERR_INSUFFICIENT_BUFFER;
4846 /* fill the buffer with the structures */
4847 smb_io_printer_info_4("", buffer, printer, 0);
4850 free_printer_info_4(printer);
4852 if (*needed > offered) {
4853 return WERR_INSUFFICIENT_BUFFER;
4859 /****************************************************************************
4860 ****************************************************************************/
4862 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4864 PRINTER_INFO_5 *printer=NULL;
4866 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4869 if (!construct_printer_info_5(print_hnd, printer, snum))
4872 /* check the required size. */
4873 *needed += spoolss_size_printer_info_5(printer);
4875 if (!alloc_buffer_size(buffer, *needed)) {
4876 free_printer_info_5(printer);
4877 return WERR_INSUFFICIENT_BUFFER;
4880 /* fill the buffer with the structures */
4881 smb_io_printer_info_5("", buffer, printer, 0);
4884 free_printer_info_5(printer);
4886 if (*needed > offered) {
4887 return WERR_INSUFFICIENT_BUFFER;
4893 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4895 PRINTER_INFO_7 *printer=NULL;
4897 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4900 if (!construct_printer_info_7(print_hnd, printer, snum))
4903 /* check the required size. */
4904 *needed += spoolss_size_printer_info_7(printer);
4906 if (!alloc_buffer_size(buffer, *needed)) {
4907 free_printer_info_7(printer);
4908 return WERR_INSUFFICIENT_BUFFER;
4911 /* fill the buffer with the structures */
4912 smb_io_printer_info_7("", buffer, printer, 0);
4915 free_printer_info_7(printer);
4917 if (*needed > offered) {
4918 return WERR_INSUFFICIENT_BUFFER;
4924 /****************************************************************************
4925 ****************************************************************************/
4927 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4929 POLICY_HND *handle = &q_u->handle;
4930 uint32 level = q_u->level;
4931 NEW_BUFFER *buffer = NULL;
4932 uint32 offered = q_u->offered;
4933 uint32 *needed = &r_u->needed;
4934 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4938 /* that's an [in out] buffer */
4939 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4940 buffer = r_u->buffer;
4944 if (!get_printer_snum(p, handle, &snum))
4949 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4951 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4953 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4955 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4957 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4959 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4961 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4963 return WERR_UNKNOWN_LEVEL;
4966 /********************************************************************
4967 * fill a DRIVER_INFO_1 struct
4968 ********************************************************************/
4970 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4972 init_unistr( &info->name, driver.info_3->name);
4975 /********************************************************************
4976 * construct_printer_driver_info_1
4977 ********************************************************************/
4979 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4981 NT_PRINTER_INFO_LEVEL *printer = NULL;
4982 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4984 ZERO_STRUCT(driver);
4986 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4987 return WERR_INVALID_PRINTER_NAME;
4989 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4990 return WERR_UNKNOWN_PRINTER_DRIVER;
4992 fill_printer_driver_info_1(info, driver, servername, architecture);
4994 free_a_printer(&printer,2);
4999 /********************************************************************
5000 * construct_printer_driver_info_2
5001 * fill a printer_info_2 struct
5002 ********************************************************************/
5004 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5008 info->version=driver.info_3->cversion;
5010 init_unistr( &info->name, driver.info_3->name );
5011 init_unistr( &info->architecture, driver.info_3->environment );
5014 if (strlen(driver.info_3->driverpath)) {
5015 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5016 init_unistr( &info->driverpath, temp );
5018 init_unistr( &info->driverpath, "" );
5020 if (strlen(driver.info_3->datafile)) {
5021 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5022 init_unistr( &info->datafile, temp );
5024 init_unistr( &info->datafile, "" );
5026 if (strlen(driver.info_3->configfile)) {
5027 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5028 init_unistr( &info->configfile, temp );
5030 init_unistr( &info->configfile, "" );
5033 /********************************************************************
5034 * construct_printer_driver_info_2
5035 * fill a printer_info_2 struct
5036 ********************************************************************/
5038 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5040 NT_PRINTER_INFO_LEVEL *printer = NULL;
5041 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5043 ZERO_STRUCT(printer);
5044 ZERO_STRUCT(driver);
5046 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5047 return WERR_INVALID_PRINTER_NAME;
5049 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5050 return WERR_UNKNOWN_PRINTER_DRIVER;
5052 fill_printer_driver_info_2(info, driver, servername);
5054 free_a_printer(&printer,2);
5059 /********************************************************************
5060 * copy a strings array and convert to UNICODE
5062 * convert an array of ascii string to a UNICODE string
5063 ********************************************************************/
5065 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5073 DEBUG(6,("init_unistr_array\n"));
5084 v = ""; /* hack to handle null lists */
5087 /* hack to allow this to be used in places other than when generating
5088 the list of dependent files */
5091 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5095 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
5097 /* add one extra unit16 for the second terminating NULL */
5099 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5100 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5108 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5113 /* special case for ""; we need to add both NULL's here */
5115 (*uni_array)[j++]=0x0000;
5116 (*uni_array)[j]=0x0000;
5119 DEBUGADD(6,("last one:done\n"));
5121 /* return size of array in uint16's */
5126 /********************************************************************
5127 * construct_printer_info_3
5128 * fill a printer_info_3 struct
5129 ********************************************************************/
5131 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5137 info->version=driver.info_3->cversion;
5139 init_unistr( &info->name, driver.info_3->name );
5140 init_unistr( &info->architecture, driver.info_3->environment );
5142 if (strlen(driver.info_3->driverpath)) {
5143 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5144 init_unistr( &info->driverpath, temp );
5146 init_unistr( &info->driverpath, "" );
5148 if (strlen(driver.info_3->datafile)) {
5149 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5150 init_unistr( &info->datafile, temp );
5152 init_unistr( &info->datafile, "" );
5154 if (strlen(driver.info_3->configfile)) {
5155 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5156 init_unistr( &info->configfile, temp );
5158 init_unistr( &info->configfile, "" );
5160 if (strlen(driver.info_3->helpfile)) {
5161 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5162 init_unistr( &info->helpfile, temp );
5164 init_unistr( &info->helpfile, "" );
5166 init_unistr( &info->monitorname, driver.info_3->monitorname );
5167 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5169 info->dependentfiles=NULL;
5170 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5173 /********************************************************************
5174 * construct_printer_info_3
5175 * fill a printer_info_3 struct
5176 ********************************************************************/
5178 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5180 NT_PRINTER_INFO_LEVEL *printer = NULL;
5181 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5183 ZERO_STRUCT(driver);
5185 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5186 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5187 if (!W_ERROR_IS_OK(status))
5188 return WERR_INVALID_PRINTER_NAME;
5190 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5191 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5196 * I put this code in during testing. Helpful when commenting out the
5197 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5198 * as win2k always queries the driver using an infor level of 6.
5199 * I've left it in (but ifdef'd out) because I'll probably
5200 * use it in experimentation again in the future. --jerry 22/01/2002
5203 if (!W_ERROR_IS_OK(status)) {
5205 * Is this a W2k client ?
5208 /* Yes - try again with a WinNT driver. */
5210 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5211 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5215 if (!W_ERROR_IS_OK(status)) {
5216 free_a_printer(&printer,2);
5217 return WERR_UNKNOWN_PRINTER_DRIVER;
5225 fill_printer_driver_info_3(info, driver, servername);
5227 free_a_printer(&printer,2);
5232 /********************************************************************
5233 * construct_printer_info_6
5234 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5235 ********************************************************************/
5237 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5243 memset(&nullstr, '\0', sizeof(fstring));
5245 info->version=driver.info_3->cversion;
5247 init_unistr( &info->name, driver.info_3->name );
5248 init_unistr( &info->architecture, driver.info_3->environment );
5250 if (strlen(driver.info_3->driverpath)) {
5251 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5252 init_unistr( &info->driverpath, temp );
5254 init_unistr( &info->driverpath, "" );
5256 if (strlen(driver.info_3->datafile)) {
5257 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5258 init_unistr( &info->datafile, temp );
5260 init_unistr( &info->datafile, "" );
5262 if (strlen(driver.info_3->configfile)) {
5263 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5264 init_unistr( &info->configfile, temp );
5266 init_unistr( &info->configfile, "" );
5268 if (strlen(driver.info_3->helpfile)) {
5269 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5270 init_unistr( &info->helpfile, temp );
5272 init_unistr( &info->helpfile, "" );
5274 init_unistr( &info->monitorname, driver.info_3->monitorname );
5275 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5277 info->dependentfiles = NULL;
5278 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5280 info->previousdrivernames=NULL;
5281 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5283 info->driver_date.low=0;
5284 info->driver_date.high=0;
5287 info->driver_version_low=0;
5288 info->driver_version_high=0;
5290 init_unistr( &info->mfgname, "");
5291 init_unistr( &info->oem_url, "");
5292 init_unistr( &info->hardware_id, "");
5293 init_unistr( &info->provider, "");
5296 /********************************************************************
5297 * construct_printer_info_6
5298 * fill a printer_info_6 struct
5299 ********************************************************************/
5301 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5302 fstring servername, fstring architecture, uint32 version)
5304 NT_PRINTER_INFO_LEVEL *printer = NULL;
5305 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5308 ZERO_STRUCT(driver);
5310 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5312 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5314 if (!W_ERROR_IS_OK(status))
5315 return WERR_INVALID_PRINTER_NAME;
5317 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5319 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5321 if (!W_ERROR_IS_OK(status))
5324 * Is this a W2k client ?
5328 free_a_printer(&printer,2);
5329 return WERR_UNKNOWN_PRINTER_DRIVER;
5332 /* Yes - try again with a WinNT driver. */
5334 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5335 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5336 if (!W_ERROR_IS_OK(status)) {
5337 free_a_printer(&printer,2);
5338 return WERR_UNKNOWN_PRINTER_DRIVER;
5342 fill_printer_driver_info_6(info, driver, servername);
5344 free_a_printer(&printer,2);
5345 free_a_printer_driver(driver, 3);
5350 /****************************************************************************
5351 ****************************************************************************/
5353 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5355 SAFE_FREE(info->dependentfiles);
5358 /****************************************************************************
5359 ****************************************************************************/
5361 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5363 SAFE_FREE(info->dependentfiles);
5367 /****************************************************************************
5368 ****************************************************************************/
5370 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5372 DRIVER_INFO_1 *info=NULL;
5375 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5378 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5379 if (!W_ERROR_IS_OK(status)) {
5384 /* check the required size. */
5385 *needed += spoolss_size_printer_driver_info_1(info);
5387 if (!alloc_buffer_size(buffer, *needed)) {
5389 return WERR_INSUFFICIENT_BUFFER;
5392 /* fill the buffer with the structures */
5393 smb_io_printer_driver_info_1("", buffer, info, 0);
5398 if (*needed > offered)
5399 return WERR_INSUFFICIENT_BUFFER;
5404 /****************************************************************************
5405 ****************************************************************************/
5407 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5409 DRIVER_INFO_2 *info=NULL;
5412 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5415 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5416 if (!W_ERROR_IS_OK(status)) {
5421 /* check the required size. */
5422 *needed += spoolss_size_printer_driver_info_2(info);
5424 if (!alloc_buffer_size(buffer, *needed)) {
5426 return WERR_INSUFFICIENT_BUFFER;
5429 /* fill the buffer with the structures */
5430 smb_io_printer_driver_info_2("", buffer, info, 0);
5435 if (*needed > offered)
5436 return WERR_INSUFFICIENT_BUFFER;
5441 /****************************************************************************
5442 ****************************************************************************/
5444 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5451 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5452 if (!W_ERROR_IS_OK(status)) {
5456 /* check the required size. */
5457 *needed += spoolss_size_printer_driver_info_3(&info);
5459 if (!alloc_buffer_size(buffer, *needed)) {
5460 free_printer_driver_info_3(&info);
5461 return WERR_INSUFFICIENT_BUFFER;
5464 /* fill the buffer with the structures */
5465 smb_io_printer_driver_info_3("", buffer, &info, 0);
5467 free_printer_driver_info_3(&info);
5469 if (*needed > offered)
5470 return WERR_INSUFFICIENT_BUFFER;
5475 /****************************************************************************
5476 ****************************************************************************/
5478 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5485 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5486 if (!W_ERROR_IS_OK(status)) {
5490 /* check the required size. */
5491 *needed += spoolss_size_printer_driver_info_6(&info);
5493 if (!alloc_buffer_size(buffer, *needed)) {
5494 free_printer_driver_info_6(&info);
5495 return WERR_INSUFFICIENT_BUFFER;
5498 /* fill the buffer with the structures */
5499 smb_io_printer_driver_info_6("", buffer, &info, 0);
5501 free_printer_driver_info_6(&info);
5503 if (*needed > offered)
5504 return WERR_INSUFFICIENT_BUFFER;
5509 /****************************************************************************
5510 ****************************************************************************/
5512 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5514 POLICY_HND *handle = &q_u->handle;
5515 UNISTR2 *uni_arch = &q_u->architecture;
5516 uint32 level = q_u->level;
5517 uint32 clientmajorversion = q_u->clientmajorversion;
5518 NEW_BUFFER *buffer = NULL;
5519 uint32 offered = q_u->offered;
5520 uint32 *needed = &r_u->needed;
5521 uint32 *servermajorversion = &r_u->servermajorversion;
5522 uint32 *serverminorversion = &r_u->serverminorversion;
5525 fstring architecture;
5528 /* that's an [in out] buffer */
5529 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5530 buffer = r_u->buffer;
5532 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5535 *servermajorversion = 0;
5536 *serverminorversion = 0;
5538 fstrcpy(servername, get_called_name());
5539 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5541 if (!get_printer_snum(p, handle, &snum))
5546 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5548 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5550 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5552 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5555 return WERR_UNKNOWN_LEVEL;
5558 /****************************************************************************
5559 ****************************************************************************/
5561 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5563 POLICY_HND *handle = &q_u->handle;
5565 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5568 DEBUG(3,("Error in startpageprinter printer handle\n"));
5572 Printer->page_started=True;
5576 /****************************************************************************
5577 ****************************************************************************/
5579 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5581 POLICY_HND *handle = &q_u->handle;
5584 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5587 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5591 if (!get_printer_snum(p, handle, &snum))
5594 Printer->page_started=False;
5595 print_job_endpage(snum, Printer->jobid);
5600 /********************************************************************
5601 * api_spoolss_getprinter
5602 * called from the spoolss dispatcher
5604 ********************************************************************/
5606 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5608 POLICY_HND *handle = &q_u->handle;
5609 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5610 uint32 *jobid = &r_u->jobid;
5612 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5616 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5617 struct current_user user;
5620 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5624 get_current_user(&user, p);
5627 * a nice thing with NT is it doesn't listen to what you tell it.
5628 * when asked to send _only_ RAW datas, it tries to send datas
5631 * So I add checks like in NT Server ...
5634 if (info_1->p_datatype != 0) {
5635 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5636 if (strcmp(datatype, "RAW") != 0) {
5638 return WERR_INVALID_DATATYPE;
5642 /* get the share number of the printer */
5643 if (!get_printer_snum(p, handle, &snum)) {
5647 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5649 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5651 /* An error occured in print_job_start() so return an appropriate
5654 if (Printer->jobid == -1) {
5655 return map_werror_from_unix(errno);
5658 Printer->document_started=True;
5659 (*jobid) = Printer->jobid;
5664 /********************************************************************
5665 * api_spoolss_getprinter
5666 * called from the spoolss dispatcher
5668 ********************************************************************/
5670 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5672 POLICY_HND *handle = &q_u->handle;
5674 return _spoolss_enddocprinter_internal(p, handle);
5677 /****************************************************************************
5678 ****************************************************************************/
5680 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5682 POLICY_HND *handle = &q_u->handle;
5683 uint32 buffer_size = q_u->buffer_size;
5684 uint8 *buffer = q_u->buffer;
5685 uint32 *buffer_written = &q_u->buffer_size2;
5687 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5690 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5691 r_u->buffer_written = q_u->buffer_size2;
5695 if (!get_printer_snum(p, handle, &snum))
5698 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5699 if (*buffer_written == -1) {
5700 r_u->buffer_written = 0;
5701 if (errno == ENOSPC)
5702 return WERR_NO_SPOOL_SPACE;
5704 return WERR_ACCESS_DENIED;
5707 r_u->buffer_written = q_u->buffer_size2;
5712 /********************************************************************
5713 * api_spoolss_getprinter
5714 * called from the spoolss dispatcher
5716 ********************************************************************/
5718 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5721 struct current_user user;
5723 WERROR errcode = WERR_BADFUNC;
5724 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5726 get_current_user(&user, p);
5729 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5733 if (!get_printer_snum(p, handle, &snum))
5737 case PRINTER_CONTROL_PAUSE:
5738 if (print_queue_pause(&user, snum, &errcode)) {
5742 case PRINTER_CONTROL_RESUME:
5743 case PRINTER_CONTROL_UNPAUSE:
5744 if (print_queue_resume(&user, snum, &errcode)) {
5748 case PRINTER_CONTROL_PURGE:
5749 if (print_queue_purge(&user, snum, &errcode)) {
5754 return WERR_UNKNOWN_LEVEL;
5760 /********************************************************************
5761 * api_spoolss_abortprinter
5762 * From MSDN: "Deletes printer's spool file if printer is configured
5764 ********************************************************************/
5766 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5768 POLICY_HND *handle = &q_u->handle;
5769 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5771 struct current_user user;
5772 WERROR errcode = WERR_OK;
5775 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5779 if (!get_printer_snum(p, handle, &snum))
5782 get_current_user( &user, p );
5784 print_job_delete( &user, snum, Printer->jobid, &errcode );
5789 /********************************************************************
5790 * called by spoolss_api_setprinter
5791 * when updating a printer description
5792 ********************************************************************/
5794 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5795 const SPOOL_PRINTER_INFO_LEVEL *info,
5796 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5798 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5799 struct current_user user;
5803 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5805 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5806 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5807 OUR_HANDLE(handle)));
5809 result = WERR_BADFID;
5813 /* NT seems to like setting the security descriptor even though
5814 nothing may have actually changed. This causes annoying
5815 dialog boxes when the user doesn't have permission to change
5816 the security descriptor. */
5818 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5820 if (DEBUGLEVEL >= 10) {
5824 the_acl = old_secdesc_ctr->sec->dacl;
5825 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5826 PRINTERNAME(snum), the_acl->num_aces));
5828 for (i = 0; i < the_acl->num_aces; i++) {
5831 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5833 DEBUG(10, ("%s 0x%08x\n", sid_str,
5834 the_acl->ace[i].info.mask));
5837 the_acl = secdesc_ctr->sec->dacl;
5840 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5841 PRINTERNAME(snum), the_acl->num_aces));
5843 for (i = 0; i < the_acl->num_aces; i++) {
5846 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5848 DEBUG(10, ("%s 0x%08x\n", sid_str,
5849 the_acl->ace[i].info.mask));
5852 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5856 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5858 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5863 /* Work out which user is performing the operation */
5865 get_current_user(&user, p);
5867 /* Check the user has permissions to change the security
5868 descriptor. By experimentation with two NT machines, the user
5869 requires Full Access to the printer to change security
5872 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5873 result = WERR_ACCESS_DENIED;
5877 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5884 /********************************************************************
5885 Do Samba sanity checks on a printer info struct.
5886 this has changed purpose: it now "canonicalises" printer
5887 info from a client rather than just checking it is correct
5888 ********************************************************************/
5890 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5892 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5893 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5895 /* we force some elements to "correct" values */
5896 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5897 fstrcpy(info->sharename, lp_servicename(snum));
5898 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5899 get_called_name(), info->sharename);
5900 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5906 /****************************************************************************
5907 ****************************************************************************/
5909 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5911 extern userdom_struct current_user_info;
5912 char *cmd = lp_addprinter_cmd();
5918 fstring remote_machine = "%m";
5920 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5922 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5923 cmd, printer->info_2->printername, printer->info_2->sharename,
5924 printer->info_2->portname, printer->info_2->drivername,
5925 printer->info_2->location, printer->info_2->comment, remote_machine);
5927 DEBUG(10,("Running [%s]\n", command));
5928 ret = smbrun(command, &fd);
5929 DEBUGADD(10,("returned [%d]\n", ret));
5938 /* Get lines and convert them back to dos-codepage */
5939 qlines = fd_lines_load(fd, &numlines);
5940 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5944 /* Set the portname to what the script says the portname should be. */
5945 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5946 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5948 /* Send SIGHUP to process group... is there a better way? */
5951 /* reload our services immediately */
5952 reload_services( False );
5955 file_lines_free(qlines);
5959 /********************************************************************
5960 * Called by spoolss_api_setprinter
5961 * when updating a printer description.
5962 ********************************************************************/
5964 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5965 const SPOOL_PRINTER_INFO_LEVEL *info,
5966 DEVICEMODE *devmode)
5969 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5970 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5975 DEBUG(8,("update_printer\n"));
5980 result = WERR_BADFID;
5984 if (!get_printer_snum(p, handle, &snum)) {
5985 result = WERR_BADFID;
5989 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5990 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5991 result = WERR_BADFID;
5995 DEBUGADD(8,("Converting info_2 struct\n"));
5998 * convert_printer_info converts the incoming
5999 * info from the client and overwrites the info
6000 * just read from the tdb in the pointer 'printer'.
6003 if (!convert_printer_info(info, printer, level)) {
6004 result = WERR_NOMEM;
6009 /* we have a valid devmode
6010 convert it and link it*/
6012 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6013 if (!convert_devicemode(printer->info_2->printername, devmode,
6014 &printer->info_2->devmode)) {
6015 result = WERR_NOMEM;
6020 /* Do sanity check on the requested changes for Samba */
6022 if (!check_printer_ok(printer->info_2, snum)) {
6023 result = WERR_INVALID_PARAM;
6027 /* FIXME!!! If the driver has changed we really should verify that
6028 it is installed before doing much else --jerry */
6030 /* Check calling user has permission to update printer description */
6032 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6033 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6034 result = WERR_ACCESS_DENIED;
6038 /* Call addprinter hook */
6039 /* Check changes to see if this is really needed */
6041 if ( *lp_addprinter_cmd()
6042 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6043 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6044 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6045 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6047 if ( !add_printer_hook(printer) ) {
6048 result = WERR_ACCESS_DENIED;
6053 * make sure we actually reload the services after
6054 * this as smb.conf could have a new section in it
6055 * .... shouldn't .... but could
6057 reload_services(False);
6061 * When a *new* driver is bound to a printer, the drivername is used to
6062 * lookup previously saved driver initialization info, which is then
6063 * bound to the printer, simulating what happens in the Windows arch.
6065 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6067 if (!set_driver_init(printer, 2))
6069 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6070 printer->info_2->drivername));
6073 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6074 printer->info_2->drivername));
6076 notify_printer_driver(snum, printer->info_2->drivername);
6080 * flag which changes actually occured. This is a small subset of
6081 * all the possible changes. We also have to update things in the
6085 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6086 init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 );
6087 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6088 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6090 notify_printer_comment(snum, printer->info_2->comment);
6093 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6094 init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 );
6095 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6096 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6097 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6098 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6100 notify_printer_sharename(snum, printer->info_2->sharename);
6103 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6104 init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 );
6105 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6106 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6108 notify_printer_port(snum, printer->info_2->portname);
6111 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6112 init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 );
6113 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6114 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6116 notify_printer_location(snum, printer->info_2->location);
6119 /* here we need to update some more DsSpooler keys */
6120 /* uNCName, serverName, shortServerName */
6122 init_unistr2( &buffer, global_myname(), strlen(global_myname())+1 );
6123 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6124 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6125 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6126 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6128 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6129 global_myname(), printer->info_2->sharename );
6130 init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 );
6131 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6132 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6134 /* Update printer info */
6135 result = mod_a_printer(*printer, 2);
6138 free_a_printer(&printer, 2);
6139 free_a_printer(&old_printer, 2);
6145 /****************************************************************************
6146 ****************************************************************************/
6147 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6148 const SPOOL_PRINTER_INFO_LEVEL *info)
6151 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6153 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6156 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6163 if (!get_printer_snum(p, handle, &snum))
6166 nt_printer_publish(Printer, snum, info7->action);
6170 return WERR_UNKNOWN_LEVEL;
6173 /****************************************************************************
6174 ****************************************************************************/
6176 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6178 POLICY_HND *handle = &q_u->handle;
6179 uint32 level = q_u->level;
6180 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6181 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6182 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6183 uint32 command = q_u->command;
6185 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6188 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6192 /* check the level */
6195 return control_printer(handle, command, p);
6197 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6199 return update_printer_sec(handle, level, info, p,
6202 return publish_or_unpublish_printer(p, handle, info);
6204 return WERR_UNKNOWN_LEVEL;
6208 /****************************************************************************
6209 ****************************************************************************/
6211 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6213 POLICY_HND *handle = &q_u->handle;
6214 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6217 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6221 if (Printer->notify.client_connected==True) {
6224 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6226 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6227 !get_printer_snum(p, handle, &snum) )
6230 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6233 Printer->notify.flags=0;
6234 Printer->notify.options=0;
6235 Printer->notify.localmachine[0]='\0';
6236 Printer->notify.printerlocal=0;
6237 if (Printer->notify.option)
6238 free_spool_notify_option(&Printer->notify.option);
6239 Printer->notify.client_connected=False;
6244 /****************************************************************************
6245 ****************************************************************************/
6247 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6249 /* that's an [in out] buffer (despite appearences to the contrary) */
6250 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6253 return WERR_INVALID_PARAM; /* this is what a NT server
6254 returns for AddJob. AddJob
6255 must fail on non-local
6259 /****************************************************************************
6260 ****************************************************************************/
6262 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6263 int position, int snum)
6269 t=gmtime(&queue->time);
6270 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6272 job_info->jobid=queue->job;
6273 init_unistr(&job_info->printername, lp_servicename(snum));
6274 init_unistr(&job_info->machinename, temp_name);
6275 init_unistr(&job_info->username, queue->fs_user);
6276 init_unistr(&job_info->document, queue->fs_file);
6277 init_unistr(&job_info->datatype, "RAW");
6278 init_unistr(&job_info->text_status, "");
6279 job_info->status=nt_printj_status(queue->status);
6280 job_info->priority=queue->priority;
6281 job_info->position=position;
6282 job_info->totalpages=queue->page_count;
6283 job_info->pagesprinted=0;
6285 make_systemtime(&job_info->submitted, t);
6288 /****************************************************************************
6289 ****************************************************************************/
6291 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6292 int position, int snum,
6293 NT_PRINTER_INFO_LEVEL *ntprinter,
6294 DEVICEMODE *devmode)
6299 t=gmtime(&queue->time);
6300 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6302 job_info->jobid=queue->job;
6304 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6306 init_unistr(&job_info->machinename, temp_name);
6307 init_unistr(&job_info->username, queue->fs_user);
6308 init_unistr(&job_info->document, queue->fs_file);
6309 init_unistr(&job_info->notifyname, queue->fs_user);
6310 init_unistr(&job_info->datatype, "RAW");
6311 init_unistr(&job_info->printprocessor, "winprint");
6312 init_unistr(&job_info->parameters, "");
6313 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6314 init_unistr(&job_info->text_status, "");
6316 /* and here the security descriptor */
6318 job_info->status=nt_printj_status(queue->status);
6319 job_info->priority=queue->priority;
6320 job_info->position=position;
6321 job_info->starttime=0;
6322 job_info->untiltime=0;
6323 job_info->totalpages=queue->page_count;
6324 job_info->size=queue->size;
6325 make_systemtime(&(job_info->submitted), t);
6326 job_info->timeelapsed=0;
6327 job_info->pagesprinted=0;
6329 job_info->devmode = devmode;
6334 /****************************************************************************
6335 Enumjobs at level 1.
6336 ****************************************************************************/
6338 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6339 NEW_BUFFER *buffer, uint32 offered,
6340 uint32 *needed, uint32 *returned)
6345 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6352 for (i=0; i<*returned; i++)
6353 fill_job_info_1(&info[i], &queue[i], i, snum);
6357 /* check the required size. */
6358 for (i=0; i<*returned; i++)
6359 (*needed) += spoolss_size_job_info_1(&info[i]);
6361 if (!alloc_buffer_size(buffer, *needed)) {
6363 return WERR_INSUFFICIENT_BUFFER;
6366 /* fill the buffer with the structures */
6367 for (i=0; i<*returned; i++)
6368 smb_io_job_info_1("", buffer, &info[i], 0);
6373 if (*needed > offered) {
6375 return WERR_INSUFFICIENT_BUFFER;
6381 /****************************************************************************
6382 Enumjobs at level 2.
6383 ****************************************************************************/
6385 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6386 NEW_BUFFER *buffer, uint32 offered,
6387 uint32 *needed, uint32 *returned)
6389 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6390 JOB_INFO_2 *info = NULL;
6393 DEVICEMODE *devmode = NULL;
6395 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6398 result = WERR_NOMEM;
6402 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6403 if (!W_ERROR_IS_OK(result)) {
6408 /* this should not be a failure condition if the devmode is NULL */
6410 devmode = construct_dev_mode(snum);
6412 for (i=0; i<*returned; i++)
6413 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6416 free_a_printer(&ntprinter, 2);
6419 /* check the required size. */
6420 for (i=0; i<*returned; i++)
6421 (*needed) += spoolss_size_job_info_2(&info[i]);
6423 if (*needed > offered) {
6425 result = WERR_INSUFFICIENT_BUFFER;
6429 if (!alloc_buffer_size(buffer, *needed)) {
6431 result = WERR_INSUFFICIENT_BUFFER;
6435 /* fill the buffer with the structures */
6436 for (i=0; i<*returned; i++)
6437 smb_io_job_info_2("", buffer, &info[i], 0);
6442 free_a_printer(&ntprinter, 2);
6443 free_devmode(devmode);
6451 /****************************************************************************
6453 ****************************************************************************/
6455 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6457 POLICY_HND *handle = &q_u->handle;
6458 uint32 level = q_u->level;
6459 NEW_BUFFER *buffer = NULL;
6460 uint32 offered = q_u->offered;
6461 uint32 *needed = &r_u->needed;
6462 uint32 *returned = &r_u->returned;
6466 print_status_struct prt_status;
6467 print_queue_struct *queue=NULL;
6469 /* that's an [in out] buffer */
6470 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6471 buffer = r_u->buffer;
6473 DEBUG(4,("_spoolss_enumjobs\n"));
6478 if (!get_printer_snum(p, handle, &snum))
6481 *returned = print_queue_status(snum, &queue, &prt_status);
6482 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6484 if (*returned == 0) {
6485 set_enumjobs_timestamp(snum);
6492 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6493 set_enumjobs_timestamp(snum);
6496 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6497 set_enumjobs_timestamp(snum);
6502 return WERR_UNKNOWN_LEVEL;
6506 /****************************************************************************
6507 ****************************************************************************/
6509 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6514 /****************************************************************************
6515 ****************************************************************************/
6517 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6519 POLICY_HND *handle = &q_u->handle;
6520 uint32 jobid = q_u->jobid;
6521 uint32 command = q_u->command;
6523 struct current_user user;
6525 WERROR errcode = WERR_BADFUNC;
6527 if (!get_printer_snum(p, handle, &snum)) {
6531 if (!print_job_exists(snum, jobid)) {
6532 return WERR_INVALID_PRINTER_NAME;
6535 get_current_user(&user, p);
6538 case JOB_CONTROL_CANCEL:
6539 case JOB_CONTROL_DELETE:
6540 if (print_job_delete(&user, snum, jobid, &errcode)) {
6544 case JOB_CONTROL_PAUSE:
6545 if (print_job_pause(&user, snum, jobid, &errcode)) {
6549 case JOB_CONTROL_RESTART:
6550 case JOB_CONTROL_RESUME:
6551 if (print_job_resume(&user, snum, jobid, &errcode)) {
6556 return WERR_UNKNOWN_LEVEL;
6562 /****************************************************************************
6563 Enumerates all printer drivers at level 1.
6564 ****************************************************************************/
6566 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6571 fstring *list = NULL;
6573 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6574 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6578 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6580 ndrivers=get_ntdrivers(&list, architecture, version);
6581 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6587 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6588 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6589 SAFE_FREE(driver_info_1);
6593 else driver_info_1 = tdi1;
6596 for (i=0; i<ndrivers; i++) {
6598 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6599 ZERO_STRUCT(driver);
6600 status = get_a_printer_driver(&driver, 3, list[i],
6601 architecture, version);
6602 if (!W_ERROR_IS_OK(status)) {
6606 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6607 free_a_printer_driver(driver, 3);
6610 *returned+=ndrivers;
6614 /* check the required size. */
6615 for (i=0; i<*returned; i++) {
6616 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6617 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6620 if (!alloc_buffer_size(buffer, *needed)) {
6621 SAFE_FREE(driver_info_1);
6622 return WERR_INSUFFICIENT_BUFFER;
6625 /* fill the buffer with the driver structures */
6626 for (i=0; i<*returned; i++) {
6627 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6628 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6631 SAFE_FREE(driver_info_1);
6633 if (*needed > offered) {
6635 return WERR_INSUFFICIENT_BUFFER;
6641 /****************************************************************************
6642 Enumerates all printer drivers at level 2.
6643 ****************************************************************************/
6645 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6650 fstring *list = NULL;
6652 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6653 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6657 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6659 ndrivers=get_ntdrivers(&list, architecture, version);
6660 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6666 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6667 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6668 SAFE_FREE(driver_info_2);
6672 else driver_info_2 = tdi2;
6675 for (i=0; i<ndrivers; i++) {
6678 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6679 ZERO_STRUCT(driver);
6680 status = get_a_printer_driver(&driver, 3, list[i],
6681 architecture, version);
6682 if (!W_ERROR_IS_OK(status)) {
6686 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6687 free_a_printer_driver(driver, 3);
6690 *returned+=ndrivers;
6694 /* check the required size. */
6695 for (i=0; i<*returned; i++) {
6696 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6697 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6700 if (!alloc_buffer_size(buffer, *needed)) {
6701 SAFE_FREE(driver_info_2);
6702 return WERR_INSUFFICIENT_BUFFER;
6705 /* fill the buffer with the form structures */
6706 for (i=0; i<*returned; i++) {
6707 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6708 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6711 SAFE_FREE(driver_info_2);
6713 if (*needed > offered) {
6715 return WERR_INSUFFICIENT_BUFFER;
6721 /****************************************************************************
6722 Enumerates all printer drivers at level 3.
6723 ****************************************************************************/
6725 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6730 fstring *list = NULL;
6732 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6733 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6737 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6739 ndrivers=get_ntdrivers(&list, architecture, version);
6740 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6746 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6747 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6748 SAFE_FREE(driver_info_3);
6752 else driver_info_3 = tdi3;
6755 for (i=0; i<ndrivers; i++) {
6758 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6759 ZERO_STRUCT(driver);
6760 status = get_a_printer_driver(&driver, 3, list[i],
6761 architecture, version);
6762 if (!W_ERROR_IS_OK(status)) {
6766 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6767 free_a_printer_driver(driver, 3);
6770 *returned+=ndrivers;
6774 /* check the required size. */
6775 for (i=0; i<*returned; i++) {
6776 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6777 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6780 if (!alloc_buffer_size(buffer, *needed)) {
6781 SAFE_FREE(driver_info_3);
6782 return WERR_INSUFFICIENT_BUFFER;
6785 /* fill the buffer with the driver structures */
6786 for (i=0; i<*returned; i++) {
6787 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6788 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6791 for (i=0; i<*returned; i++)
6792 SAFE_FREE(driver_info_3[i].dependentfiles);
6794 SAFE_FREE(driver_info_3);
6796 if (*needed > offered) {
6798 return WERR_INSUFFICIENT_BUFFER;
6804 /****************************************************************************
6805 Enumerates all printer drivers.
6806 ****************************************************************************/
6808 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6810 UNISTR2 *environment = &q_u->environment;
6811 uint32 level = q_u->level;
6812 NEW_BUFFER *buffer = NULL;
6813 uint32 offered = q_u->offered;
6814 uint32 *needed = &r_u->needed;
6815 uint32 *returned = &r_u->returned;
6817 fstring *list = NULL;
6819 fstring architecture;
6821 /* that's an [in out] buffer */
6822 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6823 buffer = r_u->buffer;
6825 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6826 fstrcpy(servername, get_called_name());
6830 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6834 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6836 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6838 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6842 return WERR_UNKNOWN_LEVEL;
6846 /****************************************************************************
6847 ****************************************************************************/
6849 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6851 form->flag=list->flag;
6852 init_unistr(&form->name, list->name);
6853 form->width=list->width;
6854 form->length=list->length;
6855 form->left=list->left;
6856 form->top=list->top;
6857 form->right=list->right;
6858 form->bottom=list->bottom;
6861 /****************************************************************************
6862 ****************************************************************************/
6864 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6866 uint32 level = q_u->level;
6867 NEW_BUFFER *buffer = NULL;
6868 uint32 offered = q_u->offered;
6869 uint32 *needed = &r_u->needed;
6870 uint32 *numofforms = &r_u->numofforms;
6871 uint32 numbuiltinforms;
6873 nt_forms_struct *list=NULL;
6874 nt_forms_struct *builtinlist=NULL;
6879 /* that's an [in out] buffer */
6880 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6881 buffer = r_u->buffer;
6883 DEBUG(4,("_spoolss_enumforms\n"));
6884 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6885 DEBUGADD(5,("Info level [%d]\n", level));
6887 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6888 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6889 *numofforms = get_ntforms(&list);
6890 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6891 *numofforms += numbuiltinforms;
6893 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6897 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6902 /* construct the list of form structures */
6903 for (i=0; i<numbuiltinforms; i++) {
6904 DEBUGADD(6,("Filling form number [%d]\n",i));
6905 fill_form_1(&forms_1[i], &builtinlist[i]);
6908 SAFE_FREE(builtinlist);
6910 for (; i<*numofforms; i++) {
6911 DEBUGADD(6,("Filling form number [%d]\n",i));
6912 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6917 /* check the required size. */
6918 for (i=0; i<numbuiltinforms; i++) {
6919 DEBUGADD(6,("adding form [%d]'s size\n",i));
6920 buffer_size += spoolss_size_form_1(&forms_1[i]);
6922 for (; i<*numofforms; i++) {
6923 DEBUGADD(6,("adding form [%d]'s size\n",i));
6924 buffer_size += spoolss_size_form_1(&forms_1[i]);
6927 *needed=buffer_size;
6929 if (!alloc_buffer_size(buffer, buffer_size)){
6931 return WERR_INSUFFICIENT_BUFFER;
6934 /* fill the buffer with the form structures */
6935 for (i=0; i<numbuiltinforms; i++) {
6936 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6937 smb_io_form_1("", buffer, &forms_1[i], 0);
6939 for (; i<*numofforms; i++) {
6940 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6941 smb_io_form_1("", buffer, &forms_1[i], 0);
6946 if (*needed > offered) {
6948 return WERR_INSUFFICIENT_BUFFER;
6955 SAFE_FREE(builtinlist);
6956 return WERR_UNKNOWN_LEVEL;
6961 /****************************************************************************
6962 ****************************************************************************/
6964 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6966 uint32 level = q_u->level;
6967 UNISTR2 *uni_formname = &q_u->formname;
6968 NEW_BUFFER *buffer = NULL;
6969 uint32 offered = q_u->offered;
6970 uint32 *needed = &r_u->needed;
6972 nt_forms_struct *list=NULL;
6973 nt_forms_struct builtin_form;
6978 int numofforms=0, i=0;
6980 /* that's an [in out] buffer */
6981 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6982 buffer = r_u->buffer;
6984 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6986 DEBUG(4,("_spoolss_getform\n"));
6987 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6988 DEBUGADD(5,("Info level [%d]\n", level));
6990 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6991 if (!foundBuiltin) {
6992 numofforms = get_ntforms(&list);
6993 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6995 if (numofforms == 0)
7002 fill_form_1(&form_1, &builtin_form);
7005 /* Check if the requested name is in the list of form structures */
7006 for (i=0; i<numofforms; i++) {
7008 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7010 if (strequal(form_name, list[i].name)) {
7011 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7012 fill_form_1(&form_1, &list[i]);
7018 if (i == numofforms) {
7022 /* check the required size. */
7024 *needed=spoolss_size_form_1(&form_1);
7026 if (!alloc_buffer_size(buffer, buffer_size)){
7027 return WERR_INSUFFICIENT_BUFFER;
7030 if (*needed > offered) {
7031 return WERR_INSUFFICIENT_BUFFER;
7034 /* fill the buffer with the form structures */
7035 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7036 smb_io_form_1("", buffer, &form_1, 0);
7042 return WERR_UNKNOWN_LEVEL;
7046 /****************************************************************************
7047 ****************************************************************************/
7049 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7051 init_unistr(&port->port_name, name);
7054 /****************************************************************************
7055 ****************************************************************************/
7057 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7059 init_unistr(&port->port_name, name);
7060 init_unistr(&port->monitor_name, "Local Monitor");
7061 init_unistr(&port->description, "Local Port");
7062 #define PORT_TYPE_WRITE 1
7063 port->port_type=PORT_TYPE_WRITE;
7067 /****************************************************************************
7069 ****************************************************************************/
7071 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7073 PORT_INFO_1 *ports=NULL;
7076 if (*lp_enumports_cmd()) {
7077 char *cmd = lp_enumports_cmd();
7084 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7086 DEBUG(10,("Running [%s]\n", command));
7087 ret = smbrun(command, &fd);
7088 DEBUG(10,("Returned [%d]\n", ret));
7092 /* Is this the best error to return here? */
7093 return WERR_ACCESS_DENIED;
7097 qlines = fd_lines_load(fd, &numlines);
7098 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7102 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7103 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7104 dos_errstr(WERR_NOMEM)));
7105 file_lines_free(qlines);
7109 for (i=0; i<numlines; i++) {
7110 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7111 fill_port_1(&ports[i], qlines[i]);
7114 file_lines_free(qlines);
7117 *returned = numlines;
7120 *returned = 1; /* Sole Samba port returned. */
7122 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7125 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7127 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7130 /* check the required size. */
7131 for (i=0; i<*returned; i++) {
7132 DEBUGADD(6,("adding port [%d]'s size\n", i));
7133 *needed += spoolss_size_port_info_1(&ports[i]);
7136 if (!alloc_buffer_size(buffer, *needed)) {
7138 return WERR_INSUFFICIENT_BUFFER;
7141 /* fill the buffer with the ports structures */
7142 for (i=0; i<*returned; i++) {
7143 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7144 smb_io_port_1("", buffer, &ports[i], 0);
7149 if (*needed > offered) {
7151 return WERR_INSUFFICIENT_BUFFER;
7157 /****************************************************************************
7159 ****************************************************************************/
7161 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7163 PORT_INFO_2 *ports=NULL;
7166 if (*lp_enumports_cmd()) {
7167 char *cmd = lp_enumports_cmd();
7176 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7177 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7179 path = lp_lockdir();
7181 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7182 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7185 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7186 ret = smbrun(command, &fd);
7187 DEBUGADD(10,("returned [%d]\n", ret));
7191 /* Is this the best error to return here? */
7192 return WERR_ACCESS_DENIED;
7196 qlines = fd_lines_load(fd, &numlines);
7197 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7201 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7202 file_lines_free(qlines);
7206 for (i=0; i<numlines; i++) {
7207 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7208 fill_port_2(&(ports[i]), qlines[i]);
7211 file_lines_free(qlines);
7214 *returned = numlines;
7220 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7223 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7225 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7228 /* check the required size. */
7229 for (i=0; i<*returned; i++) {
7230 DEBUGADD(6,("adding port [%d]'s size\n", i));
7231 *needed += spoolss_size_port_info_2(&ports[i]);
7234 if (!alloc_buffer_size(buffer, *needed)) {
7236 return WERR_INSUFFICIENT_BUFFER;
7239 /* fill the buffer with the ports structures */
7240 for (i=0; i<*returned; i++) {
7241 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7242 smb_io_port_2("", buffer, &ports[i], 0);
7247 if (*needed > offered) {
7249 return WERR_INSUFFICIENT_BUFFER;
7255 /****************************************************************************
7257 ****************************************************************************/
7259 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7261 uint32 level = q_u->level;
7262 NEW_BUFFER *buffer = NULL;
7263 uint32 offered = q_u->offered;
7264 uint32 *needed = &r_u->needed;
7265 uint32 *returned = &r_u->returned;
7267 /* that's an [in out] buffer */
7268 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7269 buffer = r_u->buffer;
7271 DEBUG(4,("_spoolss_enumports\n"));
7278 return enumports_level_1(buffer, offered, needed, returned);
7280 return enumports_level_2(buffer, offered, needed, returned);
7282 return WERR_UNKNOWN_LEVEL;
7286 /****************************************************************************
7287 ****************************************************************************/
7289 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7290 const SPOOL_PRINTER_INFO_LEVEL *info,
7291 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7292 uint32 user_switch, const SPOOL_USER_CTR *user,
7295 NT_PRINTER_INFO_LEVEL *printer = NULL;
7298 WERROR err = WERR_OK;
7300 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7301 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7305 ZERO_STRUCTP(printer);
7307 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7308 if (!convert_printer_info(info, printer, 2)) {
7309 free_a_printer(&printer, 2);
7313 /* check to see if the printer already exists */
7315 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7316 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7317 printer->info_2->sharename));
7318 free_a_printer(&printer, 2);
7319 return WERR_PRINTER_ALREADY_EXISTS;
7322 /* FIXME!!! smbd should check to see if the driver is installed before
7323 trying to add a printer like this --jerry */
7325 if (*lp_addprinter_cmd() ) {
7326 if ( !add_printer_hook(printer) ) {
7327 free_a_printer(&printer,2);
7328 return WERR_ACCESS_DENIED;
7332 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7333 printer->info_2->sharename);
7336 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7337 free_a_printer(&printer,2);
7338 return WERR_ACCESS_DENIED;
7341 /* you must be a printer admin to add a new printer */
7342 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7343 free_a_printer(&printer,2);
7344 return WERR_ACCESS_DENIED;
7348 * Do sanity check on the requested changes for Samba.
7351 if (!check_printer_ok(printer->info_2, snum)) {
7352 free_a_printer(&printer,2);
7353 return WERR_INVALID_PARAM;
7357 * When a printer is created, the drivername bound to the printer is used
7358 * to lookup previously saved driver initialization info, which is then
7359 * bound to the new printer, simulating what happens in the Windows arch.
7364 set_driver_init(printer, 2);
7368 /* A valid devmode was included, convert and link it
7370 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7372 if (!convert_devicemode(printer->info_2->printername, devmode,
7373 &printer->info_2->devmode))
7377 /* write the ASCII on disk */
7378 err = mod_a_printer(*printer, 2);
7379 if (!W_ERROR_IS_OK(err)) {
7380 free_a_printer(&printer,2);
7384 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7385 /* Handle open failed - remove addition. */
7386 del_a_printer(printer->info_2->sharename);
7387 free_a_printer(&printer,2);
7388 return WERR_ACCESS_DENIED;
7391 update_c_setprinter(False);
7392 free_a_printer(&printer,2);
7397 /****************************************************************************
7398 ****************************************************************************/
7400 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7402 UNISTR2 *uni_srv_name = &q_u->server_name;
7403 uint32 level = q_u->level;
7404 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7405 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7406 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7407 uint32 user_switch = q_u->user_switch;
7408 SPOOL_USER_CTR *user = &q_u->user_ctr;
7409 POLICY_HND *handle = &r_u->handle;
7413 /* we don't handle yet */
7414 /* but I know what to do ... */
7415 return WERR_UNKNOWN_LEVEL;
7417 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7419 user_switch, user, handle);
7421 return WERR_UNKNOWN_LEVEL;
7425 /****************************************************************************
7426 ****************************************************************************/
7428 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7430 uint32 level = q_u->level;
7431 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7432 WERROR err = WERR_OK;
7433 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7434 struct current_user user;
7435 fstring driver_name;
7438 ZERO_STRUCT(driver);
7440 get_current_user(&user, p);
7442 if (!convert_printer_driver_info(info, &driver, level)) {
7447 DEBUG(5,("Cleaning driver's information\n"));
7448 err = clean_up_driver_struct(driver, level, &user);
7449 if (!W_ERROR_IS_OK(err))
7452 DEBUG(5,("Moving driver to final destination\n"));
7453 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7454 if (W_ERROR_IS_OK(err))
7455 err = WERR_ACCESS_DENIED;
7459 if (add_a_printer_driver(driver, level)!=0) {
7460 err = WERR_ACCESS_DENIED;
7464 /* BEGIN_ADMIN_LOG */
7467 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7468 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7469 fstrcpy(driver_name, driver.info_3->name);
7472 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7473 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7474 fstrcpy(driver_name, driver.info_6->name);
7480 * I think this is where he DrvUpgradePrinter() hook would be
7481 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7482 * server. Right now, we just need to send ourselves a message
7483 * to update each printer bound to this driver. --jerry
7486 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7487 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7492 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7493 * decide if the driver init data should be deleted. The rules are:
7494 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7495 * 2) delete init data only if there is no 2k/Xp driver
7496 * 3) always delete init data
7497 * The generalized rule is always use init data from the highest order driver.
7498 * It is necessary to follow the driver install by an initialization step to
7499 * finish off this process.
7502 version = driver.info_3->cversion;
7503 else if (level == 6)
7504 version = driver.info_6->version;
7509 * 9x printer driver - never delete init data
7512 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7517 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7518 * there is no 2k/Xp driver init data for this driver name.
7522 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7524 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7526 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7528 if (!del_driver_init(driver_name))
7529 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7532 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7534 free_a_printer_driver(driver1,3);
7535 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7542 * 2k or Xp printer driver - always delete init data
7545 if (!del_driver_init(driver_name))
7546 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7550 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7556 free_a_printer_driver(driver, level);
7560 /********************************************************************
7561 * spoolss_addprinterdriverex
7562 ********************************************************************/
7564 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7566 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7567 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7570 * we only support the semantics of AddPrinterDriver()
7571 * i.e. only copy files that are newer than existing ones
7574 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7575 return WERR_ACCESS_DENIED;
7577 ZERO_STRUCT(q_u_local);
7578 ZERO_STRUCT(r_u_local);
7580 /* just pass the information off to _spoolss_addprinterdriver() */
7581 q_u_local.server_name_ptr = q_u->server_name_ptr;
7582 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7583 q_u_local.level = q_u->level;
7584 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7586 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7589 /****************************************************************************
7590 ****************************************************************************/
7592 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7594 init_unistr(&info->name, name);
7597 /****************************************************************************
7598 ****************************************************************************/
7600 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7604 const char *short_archi;
7605 DRIVER_DIRECTORY_1 *info=NULL;
7607 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7609 if (!(short_archi = get_short_archi(long_archi)))
7610 return WERR_INVALID_ENVIRONMENT;
7612 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7615 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7617 DEBUG(4,("printer driver directory: [%s]\n", path));
7619 fill_driverdir_1(info, path);
7621 *needed += spoolss_size_driverdir_info_1(info);
7623 if (!alloc_buffer_size(buffer, *needed)) {
7625 return WERR_INSUFFICIENT_BUFFER;
7628 smb_io_driverdir_1("", buffer, info, 0);
7632 if (*needed > offered)
7633 return WERR_INSUFFICIENT_BUFFER;
7638 /****************************************************************************
7639 ****************************************************************************/
7641 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7643 UNISTR2 *name = &q_u->name;
7644 UNISTR2 *uni_environment = &q_u->environment;
7645 uint32 level = q_u->level;
7646 NEW_BUFFER *buffer = NULL;
7647 uint32 offered = q_u->offered;
7648 uint32 *needed = &r_u->needed;
7650 /* that's an [in out] buffer */
7651 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7652 buffer = r_u->buffer;
7654 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7660 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7662 return WERR_UNKNOWN_LEVEL;
7666 /****************************************************************************
7667 ****************************************************************************/
7669 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7671 POLICY_HND *handle = &q_u->handle;
7672 uint32 idx = q_u->index;
7673 uint32 in_value_len = q_u->valuesize;
7674 uint32 in_data_len = q_u->datasize;
7675 uint32 *out_max_value_len = &r_u->valuesize;
7676 uint16 **out_value = &r_u->value;
7677 uint32 *out_value_len = &r_u->realvaluesize;
7678 uint32 *out_type = &r_u->type;
7679 uint32 *out_max_data_len = &r_u->datasize;
7680 uint8 **data_out = &r_u->data;
7681 uint32 *out_data_len = &r_u->realdatasize;
7683 NT_PRINTER_INFO_LEVEL *printer = NULL;
7686 uint32 biggest_valuesize;
7687 uint32 biggest_datasize;
7689 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7692 REGISTRY_VALUE *val = NULL;
7693 NT_PRINTER_DATA *p_data;
7694 int i, key_index, num_values;
7697 ZERO_STRUCT( printer );
7701 *out_max_data_len = 0;
7705 DEBUG(5,("spoolss_enumprinterdata\n"));
7708 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7712 if (!get_printer_snum(p,handle, &snum))
7715 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7716 if (!W_ERROR_IS_OK(result))
7719 p_data = &printer->info_2->data;
7720 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7725 * The NT machine wants to know the biggest size of value and data
7727 * cf: MSDN EnumPrinterData remark section
7730 if ( !in_value_len && !in_data_len && (key_index != -1) )
7732 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7735 biggest_valuesize = 0;
7736 biggest_datasize = 0;
7738 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7740 for ( i=0; i<num_values; i++ )
7742 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7744 name_length = strlen(val->valuename);
7745 if ( strlen(val->valuename) > biggest_valuesize )
7746 biggest_valuesize = name_length;
7748 if ( val->size > biggest_datasize )
7749 biggest_datasize = val->size;
7751 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7755 /* the value is an UNICODE string but real_value_size is the length
7756 in bytes including the trailing 0 */
7758 *out_value_len = 2 * (1+biggest_valuesize);
7759 *out_data_len = biggest_datasize;
7761 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7767 * the value len is wrong in NT sp3
7768 * that's the number of bytes not the number of unicode chars
7771 if ( key_index != -1 )
7772 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7777 /* out_value should default to "" or else NT4 has
7778 problems unmarshalling the response */
7780 *out_max_value_len=(in_value_len/sizeof(uint16));
7782 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7784 result = WERR_NOMEM;
7788 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7790 /* the data is counted in bytes */
7792 *out_max_data_len = in_data_len;
7793 *out_data_len = in_data_len;
7795 /* only allocate when given a non-zero data_len */
7797 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7799 result = WERR_NOMEM;
7803 result = WERR_NO_MORE_ITEMS;
7809 * - counted in bytes in the request
7810 * - counted in UNICODE chars in the max reply
7811 * - counted in bytes in the real size
7813 * take a pause *before* coding not *during* coding
7817 *out_max_value_len=(in_value_len/sizeof(uint16));
7818 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7820 result = WERR_NOMEM;
7824 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7828 *out_type = regval_type( val );
7830 /* data - counted in bytes */
7832 *out_max_data_len = in_data_len;
7833 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7835 result = WERR_NOMEM;
7838 data_len = (size_t)regval_size(val);
7839 memcpy( *data_out, regval_data_p(val), data_len );
7840 *out_data_len = data_len;
7844 free_a_printer(&printer, 2);
7848 /****************************************************************************
7849 ****************************************************************************/
7851 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7853 POLICY_HND *handle = &q_u->handle;
7854 UNISTR2 *value = &q_u->value;
7855 uint32 type = q_u->type;
7856 uint8 *data = q_u->data;
7857 uint32 real_len = q_u->real_len;
7859 NT_PRINTER_INFO_LEVEL *printer = NULL;
7861 WERROR status = WERR_OK;
7862 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7865 DEBUG(5,("spoolss_setprinterdata\n"));
7868 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7872 if (!get_printer_snum(p,handle, &snum))
7876 * Access check : NT returns "access denied" if you make a
7877 * SetPrinterData call without the necessary privildge.
7878 * we were originally returning OK if nothing changed
7879 * which made Win2k issue **a lot** of SetPrinterData
7880 * when connecting to a printer --jerry
7883 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7885 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7886 status = WERR_ACCESS_DENIED;
7890 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7891 if (!W_ERROR_IS_OK(status))
7894 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7897 * When client side code sets a magic printer data key, detect it and save
7898 * the current printer data and the magic key's data (its the DEVMODE) for
7899 * future printer/driver initializations.
7901 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7903 /* Set devmode and printer initialization info */
7904 status = save_driver_init( printer, 2, data, real_len );
7906 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7910 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7911 type, data, real_len );
7912 if ( W_ERROR_IS_OK(status) )
7913 status = mod_a_printer(*printer, 2);
7917 free_a_printer(&printer, 2);
7922 /****************************************************************************
7923 ****************************************************************************/
7925 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7927 POLICY_HND *handle = &q_u->handle;
7928 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7931 DEBUG(5,("_spoolss_resetprinter\n"));
7934 * All we do is to check to see if the handle and queue is valid.
7935 * This call really doesn't mean anything to us because we only
7936 * support RAW printing. --jerry
7940 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7944 if (!get_printer_snum(p,handle, &snum))
7948 /* blindly return success */
7953 /****************************************************************************
7954 ****************************************************************************/
7956 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7958 POLICY_HND *handle = &q_u->handle;
7959 UNISTR2 *value = &q_u->valuename;
7961 NT_PRINTER_INFO_LEVEL *printer = NULL;
7963 WERROR status = WERR_OK;
7964 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7967 DEBUG(5,("spoolss_deleteprinterdata\n"));
7970 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7974 if (!get_printer_snum(p, handle, &snum))
7977 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7978 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7979 return WERR_ACCESS_DENIED;
7982 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7983 if (!W_ERROR_IS_OK(status))
7986 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7988 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7990 free_a_printer(&printer, 2);
7995 /****************************************************************************
7996 ****************************************************************************/
7998 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8000 POLICY_HND *handle = &q_u->handle;
8001 FORM *form = &q_u->form;
8002 nt_forms_struct tmpForm;
8004 WERROR status = WERR_OK;
8005 NT_PRINTER_INFO_LEVEL *printer = NULL;
8008 nt_forms_struct *list=NULL;
8009 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8011 DEBUG(5,("spoolss_addform\n"));
8014 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8019 /* forms can be added on printer of on the print server handle */
8021 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8023 if (!get_printer_snum(p,handle, &snum))
8026 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8027 if (!W_ERROR_IS_OK(status))
8031 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8032 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8033 status = WERR_ACCESS_DENIED;
8037 /* can't add if builtin */
8039 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8040 status = WERR_ALREADY_EXISTS;
8044 count = get_ntforms(&list);
8046 if(!add_a_form(&list, form, &count)) {
8047 status = WERR_NOMEM;
8051 write_ntforms(&list, count);
8054 * ChangeID must always be set if this is a printer
8057 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8058 status = mod_a_printer(*printer, 2);
8062 free_a_printer(&printer, 2);
8068 /****************************************************************************
8069 ****************************************************************************/
8071 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8073 POLICY_HND *handle = &q_u->handle;
8074 UNISTR2 *form_name = &q_u->name;
8075 nt_forms_struct tmpForm;
8077 nt_forms_struct *list=NULL;
8078 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8080 WERROR status = WERR_OK;
8081 NT_PRINTER_INFO_LEVEL *printer = NULL;
8083 DEBUG(5,("spoolss_deleteform\n"));
8086 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8090 /* forms can be deleted on printer of on the print server handle */
8092 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8094 if (!get_printer_snum(p,handle, &snum))
8097 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8098 if (!W_ERROR_IS_OK(status))
8102 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8103 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8104 status = WERR_ACCESS_DENIED;
8108 /* can't delete if builtin */
8110 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8111 status = WERR_INVALID_PARAM;
8115 count = get_ntforms(&list);
8117 if ( !delete_a_form(&list, form_name, &count, &status ))
8121 * ChangeID must always be set if this is a printer
8124 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8125 status = mod_a_printer(*printer, 2);
8129 free_a_printer(&printer, 2);
8135 /****************************************************************************
8136 ****************************************************************************/
8138 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8140 POLICY_HND *handle = &q_u->handle;
8141 FORM *form = &q_u->form;
8142 nt_forms_struct tmpForm;
8144 WERROR status = WERR_OK;
8145 NT_PRINTER_INFO_LEVEL *printer = NULL;
8148 nt_forms_struct *list=NULL;
8149 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8151 DEBUG(5,("spoolss_setform\n"));
8154 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8158 /* forms can be modified on printer of on the print server handle */
8160 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8162 if (!get_printer_snum(p,handle, &snum))
8165 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8166 if (!W_ERROR_IS_OK(status))
8170 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8171 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8172 status = WERR_ACCESS_DENIED;
8176 /* can't set if builtin */
8177 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8178 status = WERR_INVALID_PARAM;
8182 count = get_ntforms(&list);
8183 update_a_form(&list, form, count);
8184 write_ntforms(&list, count);
8187 * ChangeID must always be set if this is a printer
8190 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8191 status = mod_a_printer(*printer, 2);
8196 free_a_printer(&printer, 2);
8202 /****************************************************************************
8203 enumprintprocessors level 1.
8204 ****************************************************************************/
8206 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8208 PRINTPROCESSOR_1 *info_1=NULL;
8210 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8215 init_unistr(&info_1->name, "winprint");
8217 *needed += spoolss_size_printprocessor_info_1(info_1);
8219 if (!alloc_buffer_size(buffer, *needed))
8220 return WERR_INSUFFICIENT_BUFFER;
8222 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8226 if (*needed > offered) {
8228 return WERR_INSUFFICIENT_BUFFER;
8234 /****************************************************************************
8235 ****************************************************************************/
8237 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8239 uint32 level = q_u->level;
8240 NEW_BUFFER *buffer = NULL;
8241 uint32 offered = q_u->offered;
8242 uint32 *needed = &r_u->needed;
8243 uint32 *returned = &r_u->returned;
8245 /* that's an [in out] buffer */
8246 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8247 buffer = r_u->buffer;
8249 DEBUG(5,("spoolss_enumprintprocessors\n"));
8252 * Enumerate the print processors ...
8254 * Just reply with "winprint", to keep NT happy
8255 * and I can use my nice printer checker.
8263 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8265 return WERR_UNKNOWN_LEVEL;
8269 /****************************************************************************
8270 enumprintprocdatatypes level 1.
8271 ****************************************************************************/
8273 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8275 PRINTPROCDATATYPE_1 *info_1=NULL;
8277 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8282 init_unistr(&info_1->name, "RAW");
8284 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8286 if (!alloc_buffer_size(buffer, *needed))
8287 return WERR_INSUFFICIENT_BUFFER;
8289 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8293 if (*needed > offered) {
8295 return WERR_INSUFFICIENT_BUFFER;
8301 /****************************************************************************
8302 ****************************************************************************/
8304 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8306 uint32 level = q_u->level;
8307 NEW_BUFFER *buffer = NULL;
8308 uint32 offered = q_u->offered;
8309 uint32 *needed = &r_u->needed;
8310 uint32 *returned = &r_u->returned;
8312 /* that's an [in out] buffer */
8313 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8314 buffer = r_u->buffer;
8316 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8323 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8325 return WERR_UNKNOWN_LEVEL;
8329 /****************************************************************************
8330 enumprintmonitors level 1.
8331 ****************************************************************************/
8333 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8335 PRINTMONITOR_1 *info_1=NULL;
8337 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8342 init_unistr(&info_1->name, "Local Port");
8344 *needed += spoolss_size_printmonitor_info_1(info_1);
8346 if (!alloc_buffer_size(buffer, *needed))
8347 return WERR_INSUFFICIENT_BUFFER;
8349 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8353 if (*needed > offered) {
8355 return WERR_INSUFFICIENT_BUFFER;
8361 /****************************************************************************
8362 enumprintmonitors level 2.
8363 ****************************************************************************/
8365 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8367 PRINTMONITOR_2 *info_2=NULL;
8369 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8374 init_unistr(&info_2->name, "Local Port");
8375 init_unistr(&info_2->environment, "Windows NT X86");
8376 init_unistr(&info_2->dll_name, "localmon.dll");
8378 *needed += spoolss_size_printmonitor_info_2(info_2);
8380 if (!alloc_buffer_size(buffer, *needed))
8381 return WERR_INSUFFICIENT_BUFFER;
8383 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8387 if (*needed > offered) {
8389 return WERR_INSUFFICIENT_BUFFER;
8395 /****************************************************************************
8396 ****************************************************************************/
8398 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8400 uint32 level = q_u->level;
8401 NEW_BUFFER *buffer = NULL;
8402 uint32 offered = q_u->offered;
8403 uint32 *needed = &r_u->needed;
8404 uint32 *returned = &r_u->returned;
8406 /* that's an [in out] buffer */
8407 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8408 buffer = r_u->buffer;
8410 DEBUG(5,("spoolss_enumprintmonitors\n"));
8413 * Enumerate the print monitors ...
8415 * Just reply with "Local Port", to keep NT happy
8416 * and I can use my nice printer checker.
8424 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8426 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8428 return WERR_UNKNOWN_LEVEL;
8432 /****************************************************************************
8433 ****************************************************************************/
8435 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8439 JOB_INFO_1 *info_1=NULL;
8441 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8443 if (info_1 == NULL) {
8447 for (i=0; i<count && found==False; i++) {
8448 if ((*queue)[i].job==(int)jobid)
8454 /* NT treats not found as bad param... yet another bad choice */
8455 return WERR_INVALID_PARAM;
8458 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8460 *needed += spoolss_size_job_info_1(info_1);
8462 if (!alloc_buffer_size(buffer, *needed)) {
8464 return WERR_INSUFFICIENT_BUFFER;
8467 smb_io_job_info_1("", buffer, info_1, 0);
8471 if (*needed > offered)
8472 return WERR_INSUFFICIENT_BUFFER;
8477 /****************************************************************************
8478 ****************************************************************************/
8480 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8485 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8487 DEVICEMODE *devmode = NULL;
8488 NT_DEVICEMODE *nt_devmode = NULL;
8490 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8492 ZERO_STRUCTP(info_2);
8494 if (info_2 == NULL) {
8499 for ( i=0; i<count && found==False; i++ )
8501 if ((*queue)[i].job == (int)jobid)
8507 /* NT treats not found as bad param... yet another bad
8509 ret = WERR_INVALID_PARAM;
8513 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8514 if (!W_ERROR_IS_OK(ret))
8518 * if the print job does not have a DEVMODE associated with it,
8519 * just use the one for the printer. A NULL devicemode is not
8520 * a failure condition
8523 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8524 devmode = construct_dev_mode(snum);
8526 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8527 ZERO_STRUCTP( devmode );
8528 convert_nt_devicemode( devmode, nt_devmode );
8532 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8534 *needed += spoolss_size_job_info_2(info_2);
8536 if (!alloc_buffer_size(buffer, *needed)) {
8537 ret = WERR_INSUFFICIENT_BUFFER;
8541 smb_io_job_info_2("", buffer, info_2, 0);
8543 if (*needed > offered) {
8544 ret = WERR_INSUFFICIENT_BUFFER;
8551 /* Cleanup allocated memory */
8553 free_job_info_2(info_2); /* Also frees devmode */
8555 free_a_printer(&ntprinter, 2);
8560 /****************************************************************************
8561 ****************************************************************************/
8563 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8565 POLICY_HND *handle = &q_u->handle;
8566 uint32 jobid = q_u->jobid;
8567 uint32 level = q_u->level;
8568 NEW_BUFFER *buffer = NULL;
8569 uint32 offered = q_u->offered;
8570 uint32 *needed = &r_u->needed;
8571 WERROR wstatus = WERR_OK;
8575 print_queue_struct *queue = NULL;
8576 print_status_struct prt_status;
8578 /* that's an [in out] buffer */
8579 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8580 buffer = r_u->buffer;
8582 DEBUG(5,("spoolss_getjob\n"));
8586 if (!get_printer_snum(p, handle, &snum))
8589 count = print_queue_status(snum, &queue, &prt_status);
8591 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8592 count, prt_status.status, prt_status.message));
8596 wstatus = getjob_level_1(&queue, count, snum, jobid,
8597 buffer, offered, needed);
8600 wstatus = getjob_level_2(&queue, count, snum, jobid,
8601 buffer, offered, needed);
8604 wstatus = WERR_UNKNOWN_LEVEL;
8612 /********************************************************************
8613 spoolss_getprinterdataex
8615 From MSDN documentation of GetPrinterDataEx: pass request
8616 to GetPrinterData if key is "PrinterDriverData".
8617 ********************************************************************/
8619 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8621 POLICY_HND *handle = &q_u->handle;
8622 uint32 in_size = q_u->size;
8623 uint32 *type = &r_u->type;
8624 uint32 *out_size = &r_u->size;
8625 uint8 **data = &r_u->data;
8626 uint32 *needed = &r_u->needed;
8627 fstring keyname, valuename;
8629 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8631 NT_PRINTER_INFO_LEVEL *printer = NULL;
8633 WERROR status = WERR_OK;
8635 DEBUG(4,("_spoolss_getprinterdataex\n"));
8637 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8638 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8640 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8641 keyname, valuename));
8643 /* in case of problem, return some default values */
8647 *out_size = in_size;
8650 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8651 status = WERR_BADFID;
8655 /* Is the handle to a printer or to the server? */
8657 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8658 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8659 status = WERR_INVALID_PARAM;
8663 if ( !get_printer_snum(p,handle, &snum) )
8666 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8667 if ( !W_ERROR_IS_OK(status) )
8670 /* check to see if the keyname is valid */
8671 if ( !strlen(keyname) ) {
8672 status = WERR_INVALID_PARAM;
8676 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8677 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8678 free_a_printer( &printer, 2 );
8679 status = WERR_BADFILE;
8683 /* When given a new keyname, we should just create it */
8685 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8687 if (*needed > *out_size)
8688 status = WERR_MORE_DATA;
8691 if ( !W_ERROR_IS_OK(status) )
8693 DEBUG(5, ("error: allocating %d\n", *out_size));
8695 /* reply this param doesn't exist */
8699 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8700 status = WERR_NOMEM;
8710 free_a_printer( &printer, 2 );
8715 /********************************************************************
8716 * spoolss_setprinterdataex
8717 ********************************************************************/
8719 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8721 POLICY_HND *handle = &q_u->handle;
8722 uint32 type = q_u->type;
8723 uint8 *data = q_u->data;
8724 uint32 real_len = q_u->real_len;
8726 NT_PRINTER_INFO_LEVEL *printer = NULL;
8728 WERROR status = WERR_OK;
8729 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8734 DEBUG(4,("_spoolss_setprinterdataex\n"));
8736 /* From MSDN documentation of SetPrinterDataEx: pass request to
8737 SetPrinterData if key is "PrinterDriverData" */
8740 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8744 if ( !get_printer_snum(p,handle, &snum) )
8748 * Access check : NT returns "access denied" if you make a
8749 * SetPrinterData call without the necessary privildge.
8750 * we were originally returning OK if nothing changed
8751 * which made Win2k issue **a lot** of SetPrinterData
8752 * when connecting to a printer --jerry
8755 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8757 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8758 return WERR_ACCESS_DENIED;
8761 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8762 if (!W_ERROR_IS_OK(status))
8765 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8766 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8768 /* check for OID in valuename */
8770 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8776 /* save the registry data */
8778 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8780 if ( W_ERROR_IS_OK(status) )
8782 /* save the OID if one was specified */
8784 fstrcat( keyname, "\\" );
8785 fstrcat( keyname, SPOOL_OID_KEY );
8788 * I'm not checking the status here on purpose. Don't know
8789 * if this is right, but I'm returning the status from the
8790 * previous set_printer_dataex() call. I have no idea if
8791 * this is right. --jerry
8794 set_printer_dataex( printer, keyname, valuename,
8795 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8798 status = mod_a_printer(*printer, 2);
8801 free_a_printer(&printer, 2);
8807 /********************************************************************
8808 * spoolss_deleteprinterdataex
8809 ********************************************************************/
8811 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8813 POLICY_HND *handle = &q_u->handle;
8814 UNISTR2 *value = &q_u->valuename;
8815 UNISTR2 *key = &q_u->keyname;
8817 NT_PRINTER_INFO_LEVEL *printer = NULL;
8819 WERROR status = WERR_OK;
8820 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8821 pstring valuename, keyname;
8823 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8826 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8830 if (!get_printer_snum(p, handle, &snum))
8833 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8834 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8835 return WERR_ACCESS_DENIED;
8838 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8839 if (!W_ERROR_IS_OK(status))
8842 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8843 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8845 status = delete_printer_dataex( printer, keyname, valuename );
8847 free_a_printer(&printer, 2);
8852 /********************************************************************
8853 * spoolss_enumprinterkey
8854 ********************************************************************/
8857 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8860 fstring *keynames = NULL;
8861 uint16 *enumkeys = NULL;
8864 POLICY_HND *handle = &q_u->handle;
8865 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8866 NT_PRINTER_DATA *data;
8867 NT_PRINTER_INFO_LEVEL *printer = NULL;
8869 WERROR status = WERR_BADFILE;
8872 DEBUG(4,("_spoolss_enumprinterkey\n"));
8875 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8879 if ( !get_printer_snum(p,handle, &snum) )
8882 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8883 if (!W_ERROR_IS_OK(status))
8886 /* get the list of subkey names */
8888 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8889 data = &printer->info_2->data;
8891 num_keys = get_printer_subkeys( data, key, &keynames );
8893 if ( num_keys == -1 ) {
8894 status = WERR_BADFILE;
8898 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8900 r_u->needed = printerkey_len*2;
8902 if ( q_u->size < r_u->needed ) {
8903 status = WERR_MORE_DATA;
8907 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8908 status = WERR_NOMEM;
8914 if ( q_u->size < r_u->needed )
8915 status = WERR_MORE_DATA;
8918 free_a_printer( &printer, 2 );
8919 SAFE_FREE( keynames );
8924 /********************************************************************
8925 * spoolss_deleteprinterkey
8926 ********************************************************************/
8928 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8930 POLICY_HND *handle = &q_u->handle;
8931 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8933 NT_PRINTER_INFO_LEVEL *printer = NULL;
8937 DEBUG(5,("spoolss_deleteprinterkey\n"));
8940 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8944 /* if keyname == NULL, return error */
8946 if ( !q_u->keyname.buffer )
8947 return WERR_INVALID_PARAM;
8949 if (!get_printer_snum(p, handle, &snum))
8952 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8953 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8954 return WERR_ACCESS_DENIED;
8957 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8958 if (!W_ERROR_IS_OK(status))
8961 /* delete the key and all subneys */
8963 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8965 status = delete_all_printer_data( printer->info_2, key );
8967 if ( W_ERROR_IS_OK(status) )
8968 status = mod_a_printer(*printer, 2);
8970 free_a_printer( &printer, 2 );
8976 /********************************************************************
8977 * spoolss_enumprinterdataex
8978 ********************************************************************/
8980 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8982 POLICY_HND *handle = &q_u->handle;
8983 uint32 in_size = q_u->size;
8986 NT_PRINTER_INFO_LEVEL *printer = NULL;
8987 PRINTER_ENUM_VALUES *enum_values = NULL;
8988 NT_PRINTER_DATA *p_data;
8990 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8995 REGISTRY_VALUE *val;
9000 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9003 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9008 * first check for a keyname of NULL or "". Win2k seems to send
9009 * this a lot and we should send back WERR_INVALID_PARAM
9010 * no need to spend time looking up the printer in this case.
9014 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9015 if ( !strlen(key) ) {
9016 result = WERR_INVALID_PARAM;
9020 /* get the printer off of disk */
9022 if (!get_printer_snum(p,handle, &snum))
9025 ZERO_STRUCT(printer);
9026 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9027 if (!W_ERROR_IS_OK(result))
9030 /* now look for a match on the key name */
9032 p_data = &printer->info_2->data;
9034 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9035 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9037 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9038 result = WERR_INVALID_PARAM;
9045 /* allocate the memory for the array of pointers -- if necessary */
9047 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9050 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9052 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
9053 num_entries*sizeof(PRINTER_ENUM_VALUES)));
9054 result = WERR_NOMEM;
9058 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9062 * loop through all params and build the array to pass
9063 * back to the client
9066 for ( i=0; i<num_entries; i++ )
9068 /* lookup the registry value */
9070 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9071 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9075 value_name = regval_name( val );
9076 init_unistr( &enum_values[i].valuename, value_name );
9077 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9078 enum_values[i].type = regval_type( val );
9080 data_len = regval_size( val );
9082 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9084 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9086 result = WERR_NOMEM;
9090 enum_values[i].data_len = data_len;
9092 /* keep track of the size of the array in bytes */
9094 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9097 /* housekeeping information in the reply */
9099 r_u->needed = needed;
9100 r_u->returned = num_entries;
9102 if (needed > in_size) {
9103 result = WERR_MORE_DATA;
9107 /* copy data into the reply */
9109 r_u->ctr.size = r_u->needed;
9110 r_u->ctr.size_of_array = r_u->returned;
9111 r_u->ctr.values = enum_values;
9117 free_a_printer(&printer, 2);
9122 /****************************************************************************
9123 ****************************************************************************/
9125 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9127 init_unistr(&info->name, name);
9130 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9131 UNISTR2 *environment,
9138 const char *short_archi;
9139 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9141 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9143 if (!(short_archi = get_short_archi(long_archi)))
9144 return WERR_INVALID_ENVIRONMENT;
9146 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9149 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9151 fill_printprocessordirectory_1(info, path);
9153 *needed += spoolss_size_printprocessordirectory_info_1(info);
9155 if (!alloc_buffer_size(buffer, *needed)) {
9157 return WERR_INSUFFICIENT_BUFFER;
9160 smb_io_printprocessordirectory_1("", buffer, info, 0);
9164 if (*needed > offered)
9165 return WERR_INSUFFICIENT_BUFFER;
9170 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9172 uint32 level = q_u->level;
9173 NEW_BUFFER *buffer = NULL;
9174 uint32 offered = q_u->offered;
9175 uint32 *needed = &r_u->needed;
9178 /* that's an [in out] buffer */
9179 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9180 buffer = r_u->buffer;
9182 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9188 result = getprintprocessordirectory_level_1
9189 (&q_u->name, &q_u->environment, buffer, offered, needed);
9192 result = WERR_UNKNOWN_LEVEL;
9200 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9201 SPOOL_R_REPLYOPENPRINTER *r_u)
9203 DEBUG(5,("_spoolss_replyopenprinter\n"));
9205 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9210 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9211 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9213 DEBUG(5,("_spoolss_replycloseprinter\n"));