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 neessary
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 cahce 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)
2315 if (!StrCaseCmp(value, "MinorVersion")) {
2317 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2326 * uint32 size = 0x114
2328 * uint32 minor = [0|1]
2329 * uint32 build = [2195|2600]
2330 * extra unicode string = e.g. "Service Pack 3"
2332 if (!StrCaseCmp(value, "OSVersion")) {
2334 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2342 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2345 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2347 *needed = 2*(strlen(string)+1);
2348 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2350 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2352 /* it's done by hand ready to go on the wire */
2353 for (i=0; i<strlen(string); i++) {
2354 (*data)[2*i]=string[i];
2355 (*data)[2*i+1]='\0';
2360 if (!StrCaseCmp(value, "Architecture")) {
2361 pstring string="Windows NT x86";
2363 *needed = 2*(strlen(string)+1);
2364 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2366 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2367 for (i=0; i<strlen(string); i++) {
2368 (*data)[2*i]=string[i];
2369 (*data)[2*i+1]='\0';
2374 if (!StrCaseCmp(value, "DsPresent")) {
2376 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2378 SIVAL(*data, 0, 0x01);
2383 if (!StrCaseCmp(value, "DNSMachineName")) {
2386 if (!get_myfullname(hostname))
2387 return WERR_BADFILE;
2389 *needed = 2*(strlen(hostname)+1);
2390 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2392 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2393 for (i=0; i<strlen(hostname); i++) {
2394 (*data)[2*i]=hostname[i];
2395 (*data)[2*i+1]='\0';
2401 return WERR_BADFILE;
2404 /********************************************************************
2405 * spoolss_getprinterdata
2406 ********************************************************************/
2408 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2410 POLICY_HND *handle = &q_u->handle;
2411 UNISTR2 *valuename = &q_u->valuename;
2412 uint32 in_size = q_u->size;
2413 uint32 *type = &r_u->type;
2414 uint32 *out_size = &r_u->size;
2415 uint8 **data = &r_u->data;
2416 uint32 *needed = &r_u->needed;
2419 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2420 NT_PRINTER_INFO_LEVEL *printer = NULL;
2424 * Reminder: when it's a string, the length is in BYTES
2425 * even if UNICODE is negociated.
2430 *out_size = in_size;
2432 /* in case of problem, return some default values */
2437 DEBUG(4,("_spoolss_getprinterdata\n"));
2440 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2441 status = WERR_BADFID;
2445 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2447 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2448 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2451 if ( !get_printer_snum(p,handle, &snum) ) {
2452 status = WERR_BADFID;
2456 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2457 if ( !W_ERROR_IS_OK(status) )
2460 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2462 if ( strequal(value, "ChangeId") ) {
2464 *needed = sizeof(uint32);
2465 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2466 status = WERR_NOMEM;
2469 SIVAL( *data, 0, printer->info_2->changeid );
2473 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2476 if (*needed > *out_size)
2477 status = WERR_MORE_DATA;
2480 if ( !W_ERROR_IS_OK(status) )
2482 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2484 /* reply this param doesn't exist */
2487 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2489 free_a_printer( &printer, 2 );
2498 /* cleanup & exit */
2501 free_a_printer( &printer, 2 );
2506 /*********************************************************
2507 Connect to the client machine.
2508 **********************************************************/
2510 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2511 struct in_addr *client_ip, const char *remote_machine)
2513 ZERO_STRUCTP(the_cli);
2515 if(cli_initialise(the_cli) == NULL) {
2516 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2520 if ( is_zero_ip(*client_ip) ) {
2521 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2522 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2523 cli_shutdown(the_cli);
2527 if (ismyip(the_cli->dest_ip)) {
2528 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2529 cli_shutdown(the_cli);
2534 the_cli->dest_ip.s_addr = client_ip->s_addr;
2535 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2536 inet_ntoa(*client_ip) ));
2539 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2540 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) ));
2541 cli_shutdown(the_cli);
2545 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2546 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2548 cli_shutdown(the_cli);
2552 the_cli->protocol = PROTOCOL_NT1;
2554 if (!cli_negprot(the_cli)) {
2555 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2556 cli_shutdown(the_cli);
2560 if (the_cli->protocol != PROTOCOL_NT1) {
2561 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2562 cli_shutdown(the_cli);
2567 * Do an anonymous session setup.
2570 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2571 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2572 cli_shutdown(the_cli);
2576 if (!(the_cli->sec_mode & 1)) {
2577 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2578 cli_shutdown(the_cli);
2582 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2583 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) ));
2584 cli_shutdown(the_cli);
2589 * Ok - we have an anonymous connection to the IPC$ share.
2590 * Now start the NT Domain stuff :-).
2593 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2594 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)));
2595 cli_nt_session_close(the_cli);
2596 cli_ulogoff(the_cli);
2597 cli_shutdown(the_cli);
2604 /***************************************************************************
2605 Connect to the client.
2606 ****************************************************************************/
2608 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2609 uint32 localprinter, uint32 type,
2610 POLICY_HND *handle, struct in_addr *client_ip)
2615 * If it's the first connection, contact the client
2616 * and connect to the IPC$ share anonumously
2618 if (smb_connections==0) {
2619 fstring unix_printer;
2621 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2623 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2626 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2627 /* Tell the connections db we're now interested in printer
2628 * notify messages. */
2629 register_message_flags( True, FLAG_MSG_PRINTING );
2633 * Tell the specific printing tdb we want messages for this printer
2634 * by registering our PID.
2637 if (!print_notify_register_pid(snum))
2638 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2642 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2645 if (!W_ERROR_IS_OK(result))
2646 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2647 dos_errstr(result)));
2649 return (W_ERROR_IS_OK(result));
2652 /********************************************************************
2654 * ReplyFindFirstPrinterChangeNotifyEx
2656 * before replying OK: status=0 a rpc call is made to the workstation
2657 * asking ReplyOpenPrinter
2659 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2660 * called from api_spoolss_rffpcnex
2661 ********************************************************************/
2663 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2665 POLICY_HND *handle = &q_u->handle;
2666 uint32 flags = q_u->flags;
2667 uint32 options = q_u->options;
2668 UNISTR2 *localmachine = &q_u->localmachine;
2669 uint32 printerlocal = q_u->printerlocal;
2671 SPOOL_NOTIFY_OPTION *option = q_u->option;
2672 struct in_addr client_ip;
2674 /* store the notify value in the printer struct */
2676 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2679 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2683 Printer->notify.flags=flags;
2684 Printer->notify.options=options;
2685 Printer->notify.printerlocal=printerlocal;
2687 if (Printer->notify.option)
2688 free_spool_notify_option(&Printer->notify.option);
2690 Printer->notify.option=dup_spool_notify_option(option);
2692 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2693 sizeof(Printer->notify.localmachine)-1);
2695 /* Connect to the client machine and send a ReplyOpenPrinter */
2697 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2699 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2700 !get_printer_snum(p, handle, &snum) )
2703 client_ip.s_addr = inet_addr(p->conn->client_address);
2705 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2706 Printer->notify.printerlocal, 1,
2707 &Printer->notify.client_hnd, &client_ip))
2708 return WERR_SERVER_UNAVAILABLE;
2710 Printer->notify.client_connected=True;
2715 /*******************************************************************
2716 * fill a notify_info_data with the servername
2717 ********************************************************************/
2719 void spoolss_notify_server_name(int snum,
2720 SPOOL_NOTIFY_INFO_DATA *data,
2721 print_queue_struct *queue,
2722 NT_PRINTER_INFO_LEVEL *printer,
2723 TALLOC_CTX *mem_ctx)
2725 pstring temp_name, temp;
2728 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2730 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2732 data->notify_data.data.length = len;
2733 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2735 if (!data->notify_data.data.string) {
2736 data->notify_data.data.length = 0;
2740 memcpy(data->notify_data.data.string, temp, len);
2743 /*******************************************************************
2744 * fill a notify_info_data with the printername (not including the servername).
2745 ********************************************************************/
2747 void spoolss_notify_printer_name(int snum,
2748 SPOOL_NOTIFY_INFO_DATA *data,
2749 print_queue_struct *queue,
2750 NT_PRINTER_INFO_LEVEL *printer,
2751 TALLOC_CTX *mem_ctx)
2756 /* the notify name should not contain the \\server\ part */
2757 char *p = strrchr(printer->info_2->printername, '\\');
2760 p = printer->info_2->printername;
2765 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2767 data->notify_data.data.length = len;
2768 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2770 if (!data->notify_data.data.string) {
2771 data->notify_data.data.length = 0;
2775 memcpy(data->notify_data.data.string, temp, len);
2778 /*******************************************************************
2779 * fill a notify_info_data with the servicename
2780 ********************************************************************/
2782 void spoolss_notify_share_name(int snum,
2783 SPOOL_NOTIFY_INFO_DATA *data,
2784 print_queue_struct *queue,
2785 NT_PRINTER_INFO_LEVEL *printer,
2786 TALLOC_CTX *mem_ctx)
2791 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2793 data->notify_data.data.length = len;
2794 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2796 if (!data->notify_data.data.string) {
2797 data->notify_data.data.length = 0;
2801 memcpy(data->notify_data.data.string, temp, len);
2804 /*******************************************************************
2805 * fill a notify_info_data with the port name
2806 ********************************************************************/
2808 void spoolss_notify_port_name(int snum,
2809 SPOOL_NOTIFY_INFO_DATA *data,
2810 print_queue_struct *queue,
2811 NT_PRINTER_INFO_LEVEL *printer,
2812 TALLOC_CTX *mem_ctx)
2817 /* even if it's strange, that's consistant in all the code */
2819 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2821 data->notify_data.data.length = len;
2822 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2824 if (!data->notify_data.data.string) {
2825 data->notify_data.data.length = 0;
2829 memcpy(data->notify_data.data.string, temp, len);
2832 /*******************************************************************
2833 * fill a notify_info_data with the printername
2834 * but it doesn't exist, have to see what to do
2835 ********************************************************************/
2837 void spoolss_notify_driver_name(int snum,
2838 SPOOL_NOTIFY_INFO_DATA *data,
2839 print_queue_struct *queue,
2840 NT_PRINTER_INFO_LEVEL *printer,
2841 TALLOC_CTX *mem_ctx)
2846 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2848 data->notify_data.data.length = len;
2849 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2851 if (!data->notify_data.data.string) {
2852 data->notify_data.data.length = 0;
2856 memcpy(data->notify_data.data.string, temp, len);
2859 /*******************************************************************
2860 * fill a notify_info_data with the comment
2861 ********************************************************************/
2863 void spoolss_notify_comment(int snum,
2864 SPOOL_NOTIFY_INFO_DATA *data,
2865 print_queue_struct *queue,
2866 NT_PRINTER_INFO_LEVEL *printer,
2867 TALLOC_CTX *mem_ctx)
2872 if (*printer->info_2->comment == '\0')
2873 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2875 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2877 data->notify_data.data.length = len;
2878 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2880 if (!data->notify_data.data.string) {
2881 data->notify_data.data.length = 0;
2885 memcpy(data->notify_data.data.string, temp, len);
2888 /*******************************************************************
2889 * fill a notify_info_data with the comment
2890 * location = "Room 1, floor 2, building 3"
2891 ********************************************************************/
2893 void spoolss_notify_location(int snum,
2894 SPOOL_NOTIFY_INFO_DATA *data,
2895 print_queue_struct *queue,
2896 NT_PRINTER_INFO_LEVEL *printer,
2897 TALLOC_CTX *mem_ctx)
2902 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2904 data->notify_data.data.length = len;
2905 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2907 if (!data->notify_data.data.string) {
2908 data->notify_data.data.length = 0;
2912 memcpy(data->notify_data.data.string, temp, len);
2915 /*******************************************************************
2916 * fill a notify_info_data with the device mode
2917 * jfm:xxxx don't to it for know but that's a real problem !!!
2918 ********************************************************************/
2920 static void spoolss_notify_devmode(int snum,
2921 SPOOL_NOTIFY_INFO_DATA *data,
2922 print_queue_struct *queue,
2923 NT_PRINTER_INFO_LEVEL *printer,
2924 TALLOC_CTX *mem_ctx)
2928 /*******************************************************************
2929 * fill a notify_info_data with the separator file name
2930 ********************************************************************/
2932 void spoolss_notify_sepfile(int snum,
2933 SPOOL_NOTIFY_INFO_DATA *data,
2934 print_queue_struct *queue,
2935 NT_PRINTER_INFO_LEVEL *printer,
2936 TALLOC_CTX *mem_ctx)
2941 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2943 data->notify_data.data.length = len;
2944 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2946 if (!data->notify_data.data.string) {
2947 data->notify_data.data.length = 0;
2951 memcpy(data->notify_data.data.string, temp, len);
2954 /*******************************************************************
2955 * fill a notify_info_data with the print processor
2956 * jfm:xxxx return always winprint to indicate we don't do anything to it
2957 ********************************************************************/
2959 void spoolss_notify_print_processor(int snum,
2960 SPOOL_NOTIFY_INFO_DATA *data,
2961 print_queue_struct *queue,
2962 NT_PRINTER_INFO_LEVEL *printer,
2963 TALLOC_CTX *mem_ctx)
2968 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2970 data->notify_data.data.length = len;
2971 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2973 if (!data->notify_data.data.string) {
2974 data->notify_data.data.length = 0;
2978 memcpy(data->notify_data.data.string, temp, len);
2981 /*******************************************************************
2982 * fill a notify_info_data with the print processor options
2983 * jfm:xxxx send an empty string
2984 ********************************************************************/
2986 void spoolss_notify_parameters(int snum,
2987 SPOOL_NOTIFY_INFO_DATA *data,
2988 print_queue_struct *queue,
2989 NT_PRINTER_INFO_LEVEL *printer,
2990 TALLOC_CTX *mem_ctx)
2995 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2997 data->notify_data.data.length = len;
2998 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3000 if (!data->notify_data.data.string) {
3001 data->notify_data.data.length = 0;
3005 memcpy(data->notify_data.data.string, temp, len);
3008 /*******************************************************************
3009 * fill a notify_info_data with the data type
3010 * jfm:xxxx always send RAW as data type
3011 ********************************************************************/
3013 void spoolss_notify_datatype(int snum,
3014 SPOOL_NOTIFY_INFO_DATA *data,
3015 print_queue_struct *queue,
3016 NT_PRINTER_INFO_LEVEL *printer,
3017 TALLOC_CTX *mem_ctx)
3022 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3024 data->notify_data.data.length = len;
3025 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3027 if (!data->notify_data.data.string) {
3028 data->notify_data.data.length = 0;
3032 memcpy(data->notify_data.data.string, temp, len);
3035 /*******************************************************************
3036 * fill a notify_info_data with the security descriptor
3037 * jfm:xxxx send an null pointer to say no security desc
3038 * have to implement security before !
3039 ********************************************************************/
3041 static void spoolss_notify_security_desc(int snum,
3042 SPOOL_NOTIFY_INFO_DATA *data,
3043 print_queue_struct *queue,
3044 NT_PRINTER_INFO_LEVEL *printer,
3045 TALLOC_CTX *mem_ctx)
3047 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3048 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3051 /*******************************************************************
3052 * fill a notify_info_data with the attributes
3053 * jfm:xxxx a samba printer is always shared
3054 ********************************************************************/
3056 void spoolss_notify_attributes(int snum,
3057 SPOOL_NOTIFY_INFO_DATA *data,
3058 print_queue_struct *queue,
3059 NT_PRINTER_INFO_LEVEL *printer,
3060 TALLOC_CTX *mem_ctx)
3062 data->notify_data.value[0] = printer->info_2->attributes;
3063 data->notify_data.value[1] = 0;
3066 /*******************************************************************
3067 * fill a notify_info_data with the priority
3068 ********************************************************************/
3070 static void spoolss_notify_priority(int snum,
3071 SPOOL_NOTIFY_INFO_DATA *data,
3072 print_queue_struct *queue,
3073 NT_PRINTER_INFO_LEVEL *printer,
3074 TALLOC_CTX *mem_ctx)
3076 data->notify_data.value[0] = printer->info_2->priority;
3077 data->notify_data.value[1] = 0;
3080 /*******************************************************************
3081 * fill a notify_info_data with the default priority
3082 ********************************************************************/
3084 static void spoolss_notify_default_priority(int snum,
3085 SPOOL_NOTIFY_INFO_DATA *data,
3086 print_queue_struct *queue,
3087 NT_PRINTER_INFO_LEVEL *printer,
3088 TALLOC_CTX *mem_ctx)
3090 data->notify_data.value[0] = printer->info_2->default_priority;
3091 data->notify_data.value[1] = 0;
3094 /*******************************************************************
3095 * fill a notify_info_data with the start time
3096 ********************************************************************/
3098 static void spoolss_notify_start_time(int snum,
3099 SPOOL_NOTIFY_INFO_DATA *data,
3100 print_queue_struct *queue,
3101 NT_PRINTER_INFO_LEVEL *printer,
3102 TALLOC_CTX *mem_ctx)
3104 data->notify_data.value[0] = printer->info_2->starttime;
3105 data->notify_data.value[1] = 0;
3108 /*******************************************************************
3109 * fill a notify_info_data with the until time
3110 ********************************************************************/
3112 static void spoolss_notify_until_time(int snum,
3113 SPOOL_NOTIFY_INFO_DATA *data,
3114 print_queue_struct *queue,
3115 NT_PRINTER_INFO_LEVEL *printer,
3116 TALLOC_CTX *mem_ctx)
3118 data->notify_data.value[0] = printer->info_2->untiltime;
3119 data->notify_data.value[1] = 0;
3122 /*******************************************************************
3123 * fill a notify_info_data with the status
3124 ********************************************************************/
3126 static void spoolss_notify_status(int snum,
3127 SPOOL_NOTIFY_INFO_DATA *data,
3128 print_queue_struct *queue,
3129 NT_PRINTER_INFO_LEVEL *printer,
3130 TALLOC_CTX *mem_ctx)
3132 print_status_struct status;
3134 print_queue_length(snum, &status);
3135 data->notify_data.value[0]=(uint32) status.status;
3136 data->notify_data.value[1] = 0;
3139 /*******************************************************************
3140 * fill a notify_info_data with the number of jobs queued
3141 ********************************************************************/
3143 void spoolss_notify_cjobs(int snum,
3144 SPOOL_NOTIFY_INFO_DATA *data,
3145 print_queue_struct *queue,
3146 NT_PRINTER_INFO_LEVEL *printer,
3147 TALLOC_CTX *mem_ctx)
3149 data->notify_data.value[0] = print_queue_length(snum, NULL);
3150 data->notify_data.value[1] = 0;
3153 /*******************************************************************
3154 * fill a notify_info_data with the average ppm
3155 ********************************************************************/
3157 static void spoolss_notify_average_ppm(int snum,
3158 SPOOL_NOTIFY_INFO_DATA *data,
3159 print_queue_struct *queue,
3160 NT_PRINTER_INFO_LEVEL *printer,
3161 TALLOC_CTX *mem_ctx)
3163 /* always respond 8 pages per minutes */
3164 /* a little hard ! */
3165 data->notify_data.value[0] = printer->info_2->averageppm;
3166 data->notify_data.value[1] = 0;
3169 /*******************************************************************
3170 * fill a notify_info_data with username
3171 ********************************************************************/
3173 static void spoolss_notify_username(int snum,
3174 SPOOL_NOTIFY_INFO_DATA *data,
3175 print_queue_struct *queue,
3176 NT_PRINTER_INFO_LEVEL *printer,
3177 TALLOC_CTX *mem_ctx)
3182 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3184 data->notify_data.data.length = len;
3185 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3187 if (!data->notify_data.data.string) {
3188 data->notify_data.data.length = 0;
3192 memcpy(data->notify_data.data.string, temp, len);
3195 /*******************************************************************
3196 * fill a notify_info_data with job status
3197 ********************************************************************/
3199 static void spoolss_notify_job_status(int snum,
3200 SPOOL_NOTIFY_INFO_DATA *data,
3201 print_queue_struct *queue,
3202 NT_PRINTER_INFO_LEVEL *printer,
3203 TALLOC_CTX *mem_ctx)
3205 data->notify_data.value[0]=nt_printj_status(queue->status);
3206 data->notify_data.value[1] = 0;
3209 /*******************************************************************
3210 * fill a notify_info_data with job name
3211 ********************************************************************/
3213 static void spoolss_notify_job_name(int snum,
3214 SPOOL_NOTIFY_INFO_DATA *data,
3215 print_queue_struct *queue,
3216 NT_PRINTER_INFO_LEVEL *printer,
3217 TALLOC_CTX *mem_ctx)
3222 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3224 data->notify_data.data.length = len;
3225 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3227 if (!data->notify_data.data.string) {
3228 data->notify_data.data.length = 0;
3232 memcpy(data->notify_data.data.string, temp, len);
3235 /*******************************************************************
3236 * fill a notify_info_data with job status
3237 ********************************************************************/
3239 static void spoolss_notify_job_status_string(int snum,
3240 SPOOL_NOTIFY_INFO_DATA *data,
3241 print_queue_struct *queue,
3242 NT_PRINTER_INFO_LEVEL *printer,
3243 TALLOC_CTX *mem_ctx)
3246 * Now we're returning job status codes we just return a "" here. JRA.
3253 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3256 switch (queue->status) {
3261 p = ""; /* NT provides the paused string */
3270 #endif /* NO LONGER NEEDED. */
3272 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3274 data->notify_data.data.length = len;
3275 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3277 if (!data->notify_data.data.string) {
3278 data->notify_data.data.length = 0;
3282 memcpy(data->notify_data.data.string, temp, len);
3285 /*******************************************************************
3286 * fill a notify_info_data with job time
3287 ********************************************************************/
3289 static void spoolss_notify_job_time(int snum,
3290 SPOOL_NOTIFY_INFO_DATA *data,
3291 print_queue_struct *queue,
3292 NT_PRINTER_INFO_LEVEL *printer,
3293 TALLOC_CTX *mem_ctx)
3295 data->notify_data.value[0]=0x0;
3296 data->notify_data.value[1]=0;
3299 /*******************************************************************
3300 * fill a notify_info_data with job size
3301 ********************************************************************/
3303 static void spoolss_notify_job_size(int snum,
3304 SPOOL_NOTIFY_INFO_DATA *data,
3305 print_queue_struct *queue,
3306 NT_PRINTER_INFO_LEVEL *printer,
3307 TALLOC_CTX *mem_ctx)
3309 data->notify_data.value[0]=queue->size;
3310 data->notify_data.value[1]=0;
3313 /*******************************************************************
3314 * fill a notify_info_data with page info
3315 ********************************************************************/
3316 static void spoolss_notify_total_pages(int snum,
3317 SPOOL_NOTIFY_INFO_DATA *data,
3318 print_queue_struct *queue,
3319 NT_PRINTER_INFO_LEVEL *printer,
3320 TALLOC_CTX *mem_ctx)
3322 data->notify_data.value[0]=queue->page_count;
3323 data->notify_data.value[1]=0;
3326 /*******************************************************************
3327 * fill a notify_info_data with pages printed info.
3328 ********************************************************************/
3329 static void spoolss_notify_pages_printed(int snum,
3330 SPOOL_NOTIFY_INFO_DATA *data,
3331 print_queue_struct *queue,
3332 NT_PRINTER_INFO_LEVEL *printer,
3333 TALLOC_CTX *mem_ctx)
3335 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3336 data->notify_data.value[1]=0;
3339 /*******************************************************************
3340 Fill a notify_info_data with job position.
3341 ********************************************************************/
3343 static void spoolss_notify_job_position(int snum,
3344 SPOOL_NOTIFY_INFO_DATA *data,
3345 print_queue_struct *queue,
3346 NT_PRINTER_INFO_LEVEL *printer,
3347 TALLOC_CTX *mem_ctx)
3349 data->notify_data.value[0]=queue->job;
3350 data->notify_data.value[1]=0;
3353 /*******************************************************************
3354 Fill a notify_info_data with submitted time.
3355 ********************************************************************/
3357 static void spoolss_notify_submitted_time(int snum,
3358 SPOOL_NOTIFY_INFO_DATA *data,
3359 print_queue_struct *queue,
3360 NT_PRINTER_INFO_LEVEL *printer,
3361 TALLOC_CTX *mem_ctx)
3368 t=gmtime(&queue->time);
3370 len = sizeof(SYSTEMTIME);
3372 data->notify_data.data.length = len;
3373 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3375 if (!data->notify_data.data.string) {
3376 data->notify_data.data.length = 0;
3380 make_systemtime(&st, t);
3383 * Systemtime must be linearized as a set of UINT16's.
3384 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3387 p = (char *)data->notify_data.data.string;
3388 SSVAL(p, 0, st.year);
3389 SSVAL(p, 2, st.month);
3390 SSVAL(p, 4, st.dayofweek);
3391 SSVAL(p, 6, st.day);
3392 SSVAL(p, 8, st.hour);
3393 SSVAL(p, 10, st.minute);
3394 SSVAL(p, 12, st.second);
3395 SSVAL(p, 14, st.milliseconds);
3398 struct s_notify_info_data_table
3404 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3405 print_queue_struct *queue,
3406 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3409 /* A table describing the various print notification constants and
3410 whether the notification data is a pointer to a variable sized
3411 buffer, a one value uint32 or a two value uint32. */
3413 static const struct s_notify_info_data_table notify_info_data_table[] =
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3445 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3446 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3447 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3448 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3449 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3450 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3452 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3453 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3454 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3455 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3456 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3457 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3458 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3463 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3466 /*******************************************************************
3467 Return the size of info_data structure.
3468 ********************************************************************/
3470 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3474 for (i = 0; i < sizeof(notify_info_data_table); i++)
3476 if ( (notify_info_data_table[i].type == type)
3477 && (notify_info_data_table[i].field == field) )
3479 switch(notify_info_data_table[i].size)
3481 case NOTIFY_ONE_VALUE:
3482 case NOTIFY_TWO_VALUE:
3487 /* The only pointer notify data I have seen on
3488 the wire is the submitted time and this has
3489 the notify size set to 4. -tpot */
3491 case NOTIFY_POINTER:
3494 case NOTIFY_SECDESC:
3500 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3505 /*******************************************************************
3506 Return the type of notify_info_data.
3507 ********************************************************************/
3509 static int type_of_notify_info_data(uint16 type, uint16 field)
3513 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3514 if (notify_info_data_table[i].type == type &&
3515 notify_info_data_table[i].field == field)
3516 return notify_info_data_table[i].size;
3522 /****************************************************************************
3523 ****************************************************************************/
3525 static int search_notify(uint16 type, uint16 field, int *value)
3529 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3530 if (notify_info_data_table[i].type == type &&
3531 notify_info_data_table[i].field == field &&
3532 notify_info_data_table[i].fn != NULL) {
3541 /****************************************************************************
3542 ****************************************************************************/
3544 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3546 info_data->type = type;
3547 info_data->field = field;
3548 info_data->reserved = 0;
3550 info_data->size = size_of_notify_info_data(type, field);
3551 info_data->enc_type = type_of_notify_info_data(type, field);
3558 /*******************************************************************
3560 * fill a notify_info struct with info asked
3562 ********************************************************************/
3564 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3565 snum, SPOOL_NOTIFY_OPTION_TYPE
3566 *option_type, uint32 id,
3567 TALLOC_CTX *mem_ctx)
3573 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3574 NT_PRINTER_INFO_LEVEL *printer = NULL;
3575 print_queue_struct *queue=NULL;
3577 type=option_type->type;
3579 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3580 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3581 option_type->count, lp_servicename(snum)));
3583 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3586 for(field_num=0; field_num<option_type->count; field_num++) {
3587 field = option_type->fields[field_num];
3589 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3591 if (!search_notify(type, field, &j) )
3594 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3595 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3600 current_data = &info->data[info->count];
3602 construct_info_data(current_data, type, field, id);
3604 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3605 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3607 notify_info_data_table[j].fn(snum, current_data, queue,
3613 free_a_printer(&printer, 2);
3617 /*******************************************************************
3619 * fill a notify_info struct with info asked
3621 ********************************************************************/
3623 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3624 SPOOL_NOTIFY_INFO *info,
3625 NT_PRINTER_INFO_LEVEL *printer,
3626 int snum, SPOOL_NOTIFY_OPTION_TYPE
3627 *option_type, uint32 id,
3628 TALLOC_CTX *mem_ctx)
3634 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3636 DEBUG(4,("construct_notify_jobs_info\n"));
3638 type = option_type->type;
3640 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3641 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3642 option_type->count));
3644 for(field_num=0; field_num<option_type->count; field_num++) {
3645 field = option_type->fields[field_num];
3647 if (!search_notify(type, field, &j) )
3650 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3651 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3654 else info->data = tid;
3656 current_data=&(info->data[info->count]);
3658 construct_info_data(current_data, type, field, id);
3659 notify_info_data_table[j].fn(snum, current_data, queue,
3668 * JFM: The enumeration is not that simple, it's even non obvious.
3670 * let's take an example: I want to monitor the PRINTER SERVER for
3671 * the printer's name and the number of jobs currently queued.
3672 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3673 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3675 * I have 3 printers on the back of my server.
3677 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3680 * 1 printer 1 name 1
3681 * 2 printer 1 cjob 1
3682 * 3 printer 2 name 2
3683 * 4 printer 2 cjob 2
3684 * 5 printer 3 name 3
3685 * 6 printer 3 name 3
3687 * that's the print server case, the printer case is even worse.
3690 /*******************************************************************
3692 * enumerate all printers on the printserver
3693 * fill a notify_info struct with info asked
3695 ********************************************************************/
3697 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3698 SPOOL_NOTIFY_INFO *info,
3699 TALLOC_CTX *mem_ctx)
3702 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3703 int n_services=lp_numservices();
3706 SPOOL_NOTIFY_OPTION *option;
3707 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3709 DEBUG(4,("printserver_notify_info\n"));
3714 option=Printer->notify.option;
3720 for (i=0; i<option->count; i++) {
3721 option_type=&(option->ctr.type[i]);
3723 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3726 for (snum=0; snum<n_services; snum++)
3728 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3729 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3735 * Debugging information, don't delete.
3738 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3739 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3740 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3742 for (i=0; i<info->count; i++) {
3743 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3744 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3745 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3752 /*******************************************************************
3754 * fill a notify_info struct with info asked
3756 ********************************************************************/
3758 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3759 TALLOC_CTX *mem_ctx)
3762 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3765 SPOOL_NOTIFY_OPTION *option;
3766 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3768 print_queue_struct *queue=NULL;
3769 print_status_struct status;
3771 DEBUG(4,("printer_notify_info\n"));
3776 option=Printer->notify.option;
3782 get_printer_snum(p, hnd, &snum);
3784 for (i=0; i<option->count; i++) {
3785 option_type=&option->ctr.type[i];
3787 switch ( option_type->type ) {
3788 case PRINTER_NOTIFY_TYPE:
3789 if(construct_notify_printer_info(Printer, info, snum,
3795 case JOB_NOTIFY_TYPE: {
3796 NT_PRINTER_INFO_LEVEL *printer = NULL;
3798 count = print_queue_status(snum, &queue, &status);
3800 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3803 for (j=0; j<count; j++) {
3804 construct_notify_jobs_info(&queue[j], info,
3811 free_a_printer(&printer, 2);
3821 * Debugging information, don't delete.
3824 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3825 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3826 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3828 for (i=0; i<info->count; i++) {
3829 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3830 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3831 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3837 /********************************************************************
3839 ********************************************************************/
3841 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3843 POLICY_HND *handle = &q_u->handle;
3844 SPOOL_NOTIFY_INFO *info = &r_u->info;
3846 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3847 WERROR result = WERR_BADFID;
3849 /* we always have a NOTIFY_INFO struct */
3853 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3854 OUR_HANDLE(handle)));
3858 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3861 * We are now using the change value, and
3862 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3863 * I don't have a global notification system, I'm sending back all the
3864 * informations even when _NOTHING_ has changed.
3867 /* We need to keep track of the change value to send back in
3868 RRPCN replies otherwise our updates are ignored. */
3870 Printer->notify.fnpcn = True;
3872 if (Printer->notify.client_connected) {
3873 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3874 Printer->notify.change = q_u->change;
3877 /* just ignore the SPOOL_NOTIFY_OPTION */
3879 switch (Printer->printer_type) {
3880 case PRINTER_HANDLE_IS_PRINTSERVER:
3881 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3884 case PRINTER_HANDLE_IS_PRINTER:
3885 result = printer_notify_info(p, handle, info, p->mem_ctx);
3889 Printer->notify.fnpcn = False;
3895 /********************************************************************
3896 * construct_printer_info_0
3897 * fill a printer_info_0 struct
3898 ********************************************************************/
3900 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3904 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3905 counter_printer_0 *session_counter;
3906 uint32 global_counter;
3909 print_status_struct status;
3911 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3914 count = print_queue_length(snum, &status);
3916 /* check if we already have a counter for this printer */
3917 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3919 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3920 if (session_counter->snum == snum)
3924 /* it's the first time, add it to the list */
3925 if (session_counter==NULL) {
3926 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3927 free_a_printer(&ntprinter, 2);
3930 ZERO_STRUCTP(session_counter);
3931 session_counter->snum=snum;
3932 session_counter->counter=0;
3933 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3937 session_counter->counter++;
3940 * the global_counter should be stored in a TDB as it's common to all the clients
3941 * and should be zeroed on samba startup
3943 global_counter=session_counter->counter;
3945 pstrcpy(chaine,ntprinter->info_2->printername);
3947 init_unistr(&printer->printername, chaine);
3949 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3950 init_unistr(&printer->servername, chaine);
3952 printer->cjobs = count;
3953 printer->total_jobs = 0;
3954 printer->total_bytes = 0;
3956 setuptime = (time_t)ntprinter->info_2->setuptime;
3957 t=gmtime(&setuptime);
3959 printer->year = t->tm_year+1900;
3960 printer->month = t->tm_mon+1;
3961 printer->dayofweek = t->tm_wday;
3962 printer->day = t->tm_mday;
3963 printer->hour = t->tm_hour;
3964 printer->minute = t->tm_min;
3965 printer->second = t->tm_sec;
3966 printer->milliseconds = 0;
3968 printer->global_counter = global_counter;
3969 printer->total_pages = 0;
3971 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3972 printer->major_version = 0x0005; /* NT 5 */
3973 printer->build_version = 0x0893; /* build 2195 */
3975 printer->unknown7 = 0x1;
3976 printer->unknown8 = 0x0;
3977 printer->unknown9 = 0x0;
3978 printer->session_counter = session_counter->counter;
3979 printer->unknown11 = 0x0;
3980 printer->printer_errors = 0x0; /* number of print failure */
3981 printer->unknown13 = 0x0;
3982 printer->unknown14 = 0x1;
3983 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3984 printer->unknown16 = 0x0;
3985 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3986 printer->unknown18 = 0x0;
3987 printer->status = nt_printq_status(status.status);
3988 printer->unknown20 = 0x0;
3989 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3990 printer->unknown22 = 0x0;
3991 printer->unknown23 = 0x6; /* 6 ???*/
3992 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3993 printer->unknown25 = 0;
3994 printer->unknown26 = 0;
3995 printer->unknown27 = 0;
3996 printer->unknown28 = 0;
3997 printer->unknown29 = 0;
3999 free_a_printer(&ntprinter,2);
4003 /********************************************************************
4004 * construct_printer_info_1
4005 * fill a printer_info_1 struct
4006 ********************************************************************/
4007 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4011 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4013 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4016 printer->flags=flags;
4018 if (*ntprinter->info_2->comment == '\0') {
4019 init_unistr(&printer->comment, lp_comment(snum));
4020 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4021 ntprinter->info_2->drivername, lp_comment(snum));
4024 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4025 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4026 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4029 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4031 init_unistr(&printer->description, chaine);
4032 init_unistr(&printer->name, chaine2);
4034 free_a_printer(&ntprinter,2);
4039 /****************************************************************************
4040 Free a DEVMODE struct.
4041 ****************************************************************************/
4043 static void free_dev_mode(DEVICEMODE *dev)
4048 SAFE_FREE(dev->private);
4053 /****************************************************************************
4054 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4055 should be valid upon entry
4056 ****************************************************************************/
4058 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4060 if ( !devmode || !ntdevmode )
4063 init_unistr(&devmode->devicename, ntdevmode->devicename);
4065 init_unistr(&devmode->formname, ntdevmode->formname);
4067 devmode->specversion = ntdevmode->specversion;
4068 devmode->driverversion = ntdevmode->driverversion;
4069 devmode->size = ntdevmode->size;
4070 devmode->driverextra = ntdevmode->driverextra;
4071 devmode->fields = ntdevmode->fields;
4073 devmode->orientation = ntdevmode->orientation;
4074 devmode->papersize = ntdevmode->papersize;
4075 devmode->paperlength = ntdevmode->paperlength;
4076 devmode->paperwidth = ntdevmode->paperwidth;
4077 devmode->scale = ntdevmode->scale;
4078 devmode->copies = ntdevmode->copies;
4079 devmode->defaultsource = ntdevmode->defaultsource;
4080 devmode->printquality = ntdevmode->printquality;
4081 devmode->color = ntdevmode->color;
4082 devmode->duplex = ntdevmode->duplex;
4083 devmode->yresolution = ntdevmode->yresolution;
4084 devmode->ttoption = ntdevmode->ttoption;
4085 devmode->collate = ntdevmode->collate;
4086 devmode->icmmethod = ntdevmode->icmmethod;
4087 devmode->icmintent = ntdevmode->icmintent;
4088 devmode->mediatype = ntdevmode->mediatype;
4089 devmode->dithertype = ntdevmode->dithertype;
4091 if (ntdevmode->private != NULL) {
4092 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4099 /****************************************************************************
4100 Create a DEVMODE struct. Returns malloced memory.
4101 ****************************************************************************/
4103 DEVICEMODE *construct_dev_mode(int snum)
4105 NT_PRINTER_INFO_LEVEL *printer = NULL;
4106 DEVICEMODE *devmode = NULL;
4108 DEBUG(7,("construct_dev_mode\n"));
4110 DEBUGADD(8,("getting printer characteristics\n"));
4112 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4115 if ( !printer->info_2->devmode ) {
4116 DEBUG(5, ("BONG! There was no device mode!\n"));
4120 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4121 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4125 ZERO_STRUCTP(devmode);
4127 DEBUGADD(8,("loading DEVICEMODE\n"));
4129 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4130 free_dev_mode( devmode );
4135 free_a_printer(&printer,2);
4140 /********************************************************************
4141 * construct_printer_info_2
4142 * fill a printer_info_2 struct
4143 ********************************************************************/
4145 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4148 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4150 print_status_struct status;
4152 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4155 count = print_queue_length(snum, &status);
4157 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4158 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4159 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4160 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4161 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4163 if (*ntprinter->info_2->comment == '\0')
4164 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4166 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4168 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4169 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4170 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4171 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4172 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4174 printer->attributes = ntprinter->info_2->attributes;
4176 printer->priority = ntprinter->info_2->priority; /* priority */
4177 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4178 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4179 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4180 printer->status = nt_printq_status(status.status); /* status */
4181 printer->cjobs = count; /* jobs */
4182 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4184 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4185 DEBUG(8, ("Returning NULL Devicemode!\n"));
4188 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4189 /* steal the printer info sec_desc structure. [badly done]. */
4190 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4191 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4192 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4193 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4196 printer->secdesc = NULL;
4199 free_a_printer(&ntprinter, 2);
4203 /********************************************************************
4204 * construct_printer_info_3
4205 * fill a printer_info_3 struct
4206 ********************************************************************/
4208 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4210 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4211 PRINTER_INFO_3 *printer = NULL;
4213 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4217 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4218 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4222 ZERO_STRUCTP(printer);
4224 printer->flags = 4; /* These are the components of the SD we are returning. */
4225 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4226 /* steal the printer info sec_desc structure. [badly done]. */
4227 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4231 * Set the flags for the components we are returning.
4234 if (printer->secdesc->owner_sid)
4235 printer->flags |= OWNER_SECURITY_INFORMATION;
4237 if (printer->secdesc->grp_sid)
4238 printer->flags |= GROUP_SECURITY_INFORMATION;
4240 if (printer->secdesc->dacl)
4241 printer->flags |= DACL_SECURITY_INFORMATION;
4243 if (printer->secdesc->sacl)
4244 printer->flags |= SACL_SECURITY_INFORMATION;
4247 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4248 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4249 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4252 free_a_printer(&ntprinter, 2);
4254 *pp_printer = printer;
4258 /********************************************************************
4259 * construct_printer_info_4
4260 * fill a printer_info_4 struct
4261 ********************************************************************/
4263 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4265 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4267 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4270 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4271 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4272 printer->attributes = ntprinter->info_2->attributes;
4274 free_a_printer(&ntprinter, 2);
4278 /********************************************************************
4279 * construct_printer_info_5
4280 * fill a printer_info_5 struct
4281 ********************************************************************/
4283 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4285 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4287 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4290 init_unistr(&printer->printername, ntprinter->info_2->printername);
4291 init_unistr(&printer->portname, ntprinter->info_2->portname);
4292 printer->attributes = ntprinter->info_2->attributes;
4294 /* these two are not used by NT+ according to MSDN */
4296 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4297 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4299 free_a_printer(&ntprinter, 2);
4304 /********************************************************************
4305 * construct_printer_info_7
4306 * fill a printer_info_7 struct
4307 ********************************************************************/
4309 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4311 char *guid_str = NULL;
4314 if (is_printer_published(print_hnd, snum, &guid)) {
4315 asprintf(&guid_str, "{%s}", uuid_string_static(guid));
4317 init_unistr(&printer->guid, guid_str);
4318 printer->action = SPOOL_DS_PUBLISH;
4320 init_unistr(&printer->guid, "");
4321 printer->action = SPOOL_DS_UNPUBLISH;
4327 /********************************************************************
4328 Spoolss_enumprinters.
4329 ********************************************************************/
4331 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4335 int n_services=lp_numservices();
4336 PRINTER_INFO_1 *tp, *printers=NULL;
4337 PRINTER_INFO_1 current_prt;
4339 DEBUG(4,("enum_all_printers_info_1\n"));
4341 for (snum=0; snum<n_services; snum++) {
4342 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4343 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4345 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4346 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4347 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4348 SAFE_FREE(printers);
4353 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4355 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4361 /* check the required size. */
4362 for (i=0; i<*returned; i++)
4363 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4365 if (!alloc_buffer_size(buffer, *needed))
4366 return WERR_INSUFFICIENT_BUFFER;
4368 /* fill the buffer with the structures */
4369 for (i=0; i<*returned; i++)
4370 smb_io_printer_info_1("", buffer, &printers[i], 0);
4373 SAFE_FREE(printers);
4375 if (*needed > offered) {
4377 return WERR_INSUFFICIENT_BUFFER;
4383 /********************************************************************
4384 enum_all_printers_info_1_local.
4385 *********************************************************************/
4387 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4389 DEBUG(4,("enum_all_printers_info_1_local\n"));
4391 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4394 /********************************************************************
4395 enum_all_printers_info_1_name.
4396 *********************************************************************/
4398 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4402 DEBUG(4,("enum_all_printers_info_1_name\n"));
4404 if ((name[0] == '\\') && (name[1] == '\\'))
4407 if (is_myname_or_ipaddr(s)) {
4408 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4411 return WERR_INVALID_NAME;
4414 /********************************************************************
4415 enum_all_printers_info_1_remote.
4416 *********************************************************************/
4418 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4420 PRINTER_INFO_1 *printer;
4421 fstring printername;
4424 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4426 /* JFM: currently it's more a place holder than anything else.
4427 * In the spooler world there is a notion of server registration.
4428 * the print servers are registring (sp ?) on the PDC (in the same domain)
4430 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4433 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4438 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4439 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4440 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4442 init_unistr(&printer->description, desc);
4443 init_unistr(&printer->name, printername);
4444 init_unistr(&printer->comment, comment);
4445 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4447 /* check the required size. */
4448 *needed += spoolss_size_printer_info_1(printer);
4450 if (!alloc_buffer_size(buffer, *needed)) {
4452 return WERR_INSUFFICIENT_BUFFER;
4455 /* fill the buffer with the structures */
4456 smb_io_printer_info_1("", buffer, printer, 0);
4461 if (*needed > offered) {
4463 return WERR_INSUFFICIENT_BUFFER;
4469 /********************************************************************
4470 enum_all_printers_info_1_network.
4471 *********************************************************************/
4473 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4477 DEBUG(4,("enum_all_printers_info_1_network\n"));
4479 /* If we respond to a enum_printers level 1 on our name with flags
4480 set to PRINTER_ENUM_REMOTE with a list of printers then these
4481 printers incorrectly appear in the APW browse list.
4482 Specifically the printers for the server appear at the workgroup
4483 level where all the other servers in the domain are
4484 listed. Windows responds to this call with a
4485 WERR_CAN_NOT_COMPLETE so we should do the same. */
4487 if (name[0] == '\\' && name[1] == '\\')
4490 if (is_myname_or_ipaddr(s))
4491 return WERR_CAN_NOT_COMPLETE;
4493 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4496 /********************************************************************
4497 * api_spoolss_enumprinters
4499 * called from api_spoolss_enumprinters (see this to understand)
4500 ********************************************************************/
4502 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4506 int n_services=lp_numservices();
4507 PRINTER_INFO_2 *tp, *printers=NULL;
4508 PRINTER_INFO_2 current_prt;
4510 for (snum=0; snum<n_services; snum++) {
4511 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4512 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4514 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4515 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4516 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4517 SAFE_FREE(printers);
4522 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4523 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4529 /* check the required size. */
4530 for (i=0; i<*returned; i++)
4531 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4533 if (!alloc_buffer_size(buffer, *needed)) {
4534 for (i=0; i<*returned; i++) {
4535 free_devmode(printers[i].devmode);
4537 SAFE_FREE(printers);
4538 return WERR_INSUFFICIENT_BUFFER;
4541 /* fill the buffer with the structures */
4542 for (i=0; i<*returned; i++)
4543 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4546 for (i=0; i<*returned; i++) {
4547 free_devmode(printers[i].devmode);
4549 SAFE_FREE(printers);
4551 if (*needed > offered) {
4553 return WERR_INSUFFICIENT_BUFFER;
4559 /********************************************************************
4560 * handle enumeration of printers at level 1
4561 ********************************************************************/
4563 static WERROR enumprinters_level1( uint32 flags, fstring name,
4564 NEW_BUFFER *buffer, uint32 offered,
4565 uint32 *needed, uint32 *returned)
4567 /* Not all the flags are equals */
4569 if (flags & PRINTER_ENUM_LOCAL)
4570 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4572 if (flags & PRINTER_ENUM_NAME)
4573 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4575 if (flags & PRINTER_ENUM_REMOTE)
4576 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4578 if (flags & PRINTER_ENUM_NETWORK)
4579 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4581 return WERR_OK; /* NT4sp5 does that */
4584 /********************************************************************
4585 * handle enumeration of printers at level 2
4586 ********************************************************************/
4588 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4589 NEW_BUFFER *buffer, uint32 offered,
4590 uint32 *needed, uint32 *returned)
4592 char *s = servername;
4594 if (flags & PRINTER_ENUM_LOCAL) {
4595 return enum_all_printers_info_2(buffer, offered, needed, returned);
4598 if (flags & PRINTER_ENUM_NAME) {
4599 if ((servername[0] == '\\') && (servername[1] == '\\'))
4601 if (is_myname_or_ipaddr(s))
4602 return enum_all_printers_info_2(buffer, offered, needed, returned);
4604 return WERR_INVALID_NAME;
4607 if (flags & PRINTER_ENUM_REMOTE)
4608 return WERR_UNKNOWN_LEVEL;
4613 /********************************************************************
4614 * handle enumeration of printers at level 5
4615 ********************************************************************/
4617 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4618 NEW_BUFFER *buffer, uint32 offered,
4619 uint32 *needed, uint32 *returned)
4621 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4625 /********************************************************************
4626 * api_spoolss_enumprinters
4628 * called from api_spoolss_enumprinters (see this to understand)
4629 ********************************************************************/
4631 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4633 uint32 flags = q_u->flags;
4634 UNISTR2 *servername = &q_u->servername;
4635 uint32 level = q_u->level;
4636 NEW_BUFFER *buffer = NULL;
4637 uint32 offered = q_u->offered;
4638 uint32 *needed = &r_u->needed;
4639 uint32 *returned = &r_u->returned;
4643 /* that's an [in out] buffer */
4644 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4645 buffer = r_u->buffer;
4647 DEBUG(4,("_spoolss_enumprinters\n"));
4654 * flags==PRINTER_ENUM_NAME
4655 * if name=="" then enumerates all printers
4656 * if name!="" then enumerate the printer
4657 * flags==PRINTER_ENUM_REMOTE
4658 * name is NULL, enumerate printers
4659 * Level 2: name!="" enumerates printers, name can't be NULL
4660 * Level 3: doesn't exist
4661 * Level 4: does a local registry lookup
4662 * Level 5: same as Level 2
4665 unistr2_to_ascii(name, servername, sizeof(name)-1);
4670 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4672 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4674 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4679 return WERR_UNKNOWN_LEVEL;
4682 /****************************************************************************
4683 ****************************************************************************/
4685 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4687 PRINTER_INFO_0 *printer=NULL;
4689 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4692 construct_printer_info_0(print_hnd, printer, snum);
4694 /* check the required size. */
4695 *needed += spoolss_size_printer_info_0(printer);
4697 if (!alloc_buffer_size(buffer, *needed)) {
4699 return WERR_INSUFFICIENT_BUFFER;
4702 /* fill the buffer with the structures */
4703 smb_io_printer_info_0("", buffer, printer, 0);
4708 if (*needed > offered) {
4709 return WERR_INSUFFICIENT_BUFFER;
4715 /****************************************************************************
4716 ****************************************************************************/
4718 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4720 PRINTER_INFO_1 *printer=NULL;
4722 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4725 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4727 /* check the required size. */
4728 *needed += spoolss_size_printer_info_1(printer);
4730 if (!alloc_buffer_size(buffer, *needed)) {
4732 return WERR_INSUFFICIENT_BUFFER;
4735 /* fill the buffer with the structures */
4736 smb_io_printer_info_1("", buffer, printer, 0);
4741 if (*needed > offered) {
4742 return WERR_INSUFFICIENT_BUFFER;
4748 /****************************************************************************
4749 ****************************************************************************/
4751 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4753 PRINTER_INFO_2 *printer=NULL;
4755 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4758 construct_printer_info_2(print_hnd, printer, snum);
4760 /* check the required size. */
4761 *needed += spoolss_size_printer_info_2(printer);
4763 if (!alloc_buffer_size(buffer, *needed)) {
4764 free_printer_info_2(printer);
4765 return WERR_INSUFFICIENT_BUFFER;
4768 /* fill the buffer with the structures */
4769 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4770 free_printer_info_2(printer);
4775 free_printer_info_2(printer);
4777 if (*needed > offered) {
4778 return WERR_INSUFFICIENT_BUFFER;
4784 /****************************************************************************
4785 ****************************************************************************/
4787 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4789 PRINTER_INFO_3 *printer=NULL;
4791 if (!construct_printer_info_3(print_hnd, &printer, snum))
4794 /* check the required size. */
4795 *needed += spoolss_size_printer_info_3(printer);
4797 if (!alloc_buffer_size(buffer, *needed)) {
4798 free_printer_info_3(printer);
4799 return WERR_INSUFFICIENT_BUFFER;
4802 /* fill the buffer with the structures */
4803 smb_io_printer_info_3("", buffer, printer, 0);
4806 free_printer_info_3(printer);
4808 if (*needed > offered) {
4809 return WERR_INSUFFICIENT_BUFFER;
4815 /****************************************************************************
4816 ****************************************************************************/
4818 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4820 PRINTER_INFO_4 *printer=NULL;
4822 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4825 if (!construct_printer_info_4(print_hnd, printer, snum))
4828 /* check the required size. */
4829 *needed += spoolss_size_printer_info_4(printer);
4831 if (!alloc_buffer_size(buffer, *needed)) {
4832 free_printer_info_4(printer);
4833 return WERR_INSUFFICIENT_BUFFER;
4836 /* fill the buffer with the structures */
4837 smb_io_printer_info_4("", buffer, printer, 0);
4840 free_printer_info_4(printer);
4842 if (*needed > offered) {
4843 return WERR_INSUFFICIENT_BUFFER;
4849 /****************************************************************************
4850 ****************************************************************************/
4852 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4854 PRINTER_INFO_5 *printer=NULL;
4856 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4859 if (!construct_printer_info_5(print_hnd, printer, snum))
4862 /* check the required size. */
4863 *needed += spoolss_size_printer_info_5(printer);
4865 if (!alloc_buffer_size(buffer, *needed)) {
4866 free_printer_info_5(printer);
4867 return WERR_INSUFFICIENT_BUFFER;
4870 /* fill the buffer with the structures */
4871 smb_io_printer_info_5("", buffer, printer, 0);
4874 free_printer_info_5(printer);
4876 if (*needed > offered) {
4877 return WERR_INSUFFICIENT_BUFFER;
4883 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4885 PRINTER_INFO_7 *printer=NULL;
4887 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4890 if (!construct_printer_info_7(print_hnd, printer, snum))
4893 /* check the required size. */
4894 *needed += spoolss_size_printer_info_7(printer);
4896 if (!alloc_buffer_size(buffer, *needed)) {
4897 free_printer_info_7(printer);
4898 return WERR_INSUFFICIENT_BUFFER;
4901 /* fill the buffer with the structures */
4902 smb_io_printer_info_7("", buffer, printer, 0);
4905 free_printer_info_7(printer);
4907 if (*needed > offered) {
4908 return WERR_INSUFFICIENT_BUFFER;
4914 /****************************************************************************
4915 ****************************************************************************/
4917 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4919 POLICY_HND *handle = &q_u->handle;
4920 uint32 level = q_u->level;
4921 NEW_BUFFER *buffer = NULL;
4922 uint32 offered = q_u->offered;
4923 uint32 *needed = &r_u->needed;
4924 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4928 /* that's an [in out] buffer */
4929 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4930 buffer = r_u->buffer;
4934 if (!get_printer_snum(p, handle, &snum))
4939 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4941 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4943 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4945 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4947 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4949 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4951 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4953 return WERR_UNKNOWN_LEVEL;
4956 /********************************************************************
4957 * fill a DRIVER_INFO_1 struct
4958 ********************************************************************/
4960 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4962 init_unistr( &info->name, driver.info_3->name);
4965 /********************************************************************
4966 * construct_printer_driver_info_1
4967 ********************************************************************/
4969 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4971 NT_PRINTER_INFO_LEVEL *printer = NULL;
4972 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4974 ZERO_STRUCT(driver);
4976 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4977 return WERR_INVALID_PRINTER_NAME;
4979 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4980 return WERR_UNKNOWN_PRINTER_DRIVER;
4982 fill_printer_driver_info_1(info, driver, servername, architecture);
4984 free_a_printer(&printer,2);
4989 /********************************************************************
4990 * construct_printer_driver_info_2
4991 * fill a printer_info_2 struct
4992 ********************************************************************/
4994 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4998 info->version=driver.info_3->cversion;
5000 init_unistr( &info->name, driver.info_3->name );
5001 init_unistr( &info->architecture, driver.info_3->environment );
5004 if (strlen(driver.info_3->driverpath)) {
5005 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5006 init_unistr( &info->driverpath, temp );
5008 init_unistr( &info->driverpath, "" );
5010 if (strlen(driver.info_3->datafile)) {
5011 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5012 init_unistr( &info->datafile, temp );
5014 init_unistr( &info->datafile, "" );
5016 if (strlen(driver.info_3->configfile)) {
5017 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5018 init_unistr( &info->configfile, temp );
5020 init_unistr( &info->configfile, "" );
5023 /********************************************************************
5024 * construct_printer_driver_info_2
5025 * fill a printer_info_2 struct
5026 ********************************************************************/
5028 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5030 NT_PRINTER_INFO_LEVEL *printer = NULL;
5031 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5033 ZERO_STRUCT(printer);
5034 ZERO_STRUCT(driver);
5036 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5037 return WERR_INVALID_PRINTER_NAME;
5039 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5040 return WERR_UNKNOWN_PRINTER_DRIVER;
5042 fill_printer_driver_info_2(info, driver, servername);
5044 free_a_printer(&printer,2);
5049 /********************************************************************
5050 * copy a strings array and convert to UNICODE
5052 * convert an array of ascii string to a UNICODE string
5053 ********************************************************************/
5055 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5063 DEBUG(6,("init_unistr_array\n"));
5074 v = ""; /* hack to handle null lists */
5077 /* hack to allow this to be used in places other than when generating
5078 the list of dependent files */
5081 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5085 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
5087 /* add one extra unit16 for the second terminating NULL */
5089 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5090 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5098 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5103 /* special case for ""; we need to add both NULL's here */
5105 (*uni_array)[j++]=0x0000;
5106 (*uni_array)[j]=0x0000;
5109 DEBUGADD(6,("last one:done\n"));
5111 /* return size of array in uint16's */
5116 /********************************************************************
5117 * construct_printer_info_3
5118 * fill a printer_info_3 struct
5119 ********************************************************************/
5121 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5127 info->version=driver.info_3->cversion;
5129 init_unistr( &info->name, driver.info_3->name );
5130 init_unistr( &info->architecture, driver.info_3->environment );
5132 if (strlen(driver.info_3->driverpath)) {
5133 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5134 init_unistr( &info->driverpath, temp );
5136 init_unistr( &info->driverpath, "" );
5138 if (strlen(driver.info_3->datafile)) {
5139 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5140 init_unistr( &info->datafile, temp );
5142 init_unistr( &info->datafile, "" );
5144 if (strlen(driver.info_3->configfile)) {
5145 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5146 init_unistr( &info->configfile, temp );
5148 init_unistr( &info->configfile, "" );
5150 if (strlen(driver.info_3->helpfile)) {
5151 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5152 init_unistr( &info->helpfile, temp );
5154 init_unistr( &info->helpfile, "" );
5156 init_unistr( &info->monitorname, driver.info_3->monitorname );
5157 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5159 info->dependentfiles=NULL;
5160 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5163 /********************************************************************
5164 * construct_printer_info_3
5165 * fill a printer_info_3 struct
5166 ********************************************************************/
5168 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5170 NT_PRINTER_INFO_LEVEL *printer = NULL;
5171 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5173 ZERO_STRUCT(driver);
5175 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5176 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5177 if (!W_ERROR_IS_OK(status))
5178 return WERR_INVALID_PRINTER_NAME;
5180 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5181 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5186 * I put this code in during testing. Helpful when commenting out the
5187 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5188 * as win2k always queries the driver using an infor level of 6.
5189 * I've left it in (but ifdef'd out) because I'll probably
5190 * use it in experimentation again in the future. --jerry 22/01/2002
5193 if (!W_ERROR_IS_OK(status)) {
5195 * Is this a W2k client ?
5198 /* Yes - try again with a WinNT driver. */
5200 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5201 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5205 if (!W_ERROR_IS_OK(status)) {
5206 free_a_printer(&printer,2);
5207 return WERR_UNKNOWN_PRINTER_DRIVER;
5215 fill_printer_driver_info_3(info, driver, servername);
5217 free_a_printer(&printer,2);
5222 /********************************************************************
5223 * construct_printer_info_6
5224 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5225 ********************************************************************/
5227 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5233 memset(&nullstr, '\0', sizeof(fstring));
5235 info->version=driver.info_3->cversion;
5237 init_unistr( &info->name, driver.info_3->name );
5238 init_unistr( &info->architecture, driver.info_3->environment );
5240 if (strlen(driver.info_3->driverpath)) {
5241 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5242 init_unistr( &info->driverpath, temp );
5244 init_unistr( &info->driverpath, "" );
5246 if (strlen(driver.info_3->datafile)) {
5247 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5248 init_unistr( &info->datafile, temp );
5250 init_unistr( &info->datafile, "" );
5252 if (strlen(driver.info_3->configfile)) {
5253 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5254 init_unistr( &info->configfile, temp );
5256 init_unistr( &info->configfile, "" );
5258 if (strlen(driver.info_3->helpfile)) {
5259 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5260 init_unistr( &info->helpfile, temp );
5262 init_unistr( &info->helpfile, "" );
5264 init_unistr( &info->monitorname, driver.info_3->monitorname );
5265 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5267 info->dependentfiles = NULL;
5268 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5270 info->previousdrivernames=NULL;
5271 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5273 info->driver_date.low=0;
5274 info->driver_date.high=0;
5277 info->driver_version_low=0;
5278 info->driver_version_high=0;
5280 init_unistr( &info->mfgname, "");
5281 init_unistr( &info->oem_url, "");
5282 init_unistr( &info->hardware_id, "");
5283 init_unistr( &info->provider, "");
5286 /********************************************************************
5287 * construct_printer_info_6
5288 * fill a printer_info_6 struct
5289 ********************************************************************/
5291 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5292 fstring servername, fstring architecture, uint32 version)
5294 NT_PRINTER_INFO_LEVEL *printer = NULL;
5295 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5298 ZERO_STRUCT(driver);
5300 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5302 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5304 if (!W_ERROR_IS_OK(status))
5305 return WERR_INVALID_PRINTER_NAME;
5307 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5309 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5311 if (!W_ERROR_IS_OK(status))
5314 * Is this a W2k client ?
5318 free_a_printer(&printer,2);
5319 return WERR_UNKNOWN_PRINTER_DRIVER;
5322 /* Yes - try again with a WinNT driver. */
5324 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5325 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5326 if (!W_ERROR_IS_OK(status)) {
5327 free_a_printer(&printer,2);
5328 return WERR_UNKNOWN_PRINTER_DRIVER;
5332 fill_printer_driver_info_6(info, driver, servername);
5334 free_a_printer(&printer,2);
5335 free_a_printer_driver(driver, 3);
5340 /****************************************************************************
5341 ****************************************************************************/
5343 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5345 SAFE_FREE(info->dependentfiles);
5348 /****************************************************************************
5349 ****************************************************************************/
5351 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5353 SAFE_FREE(info->dependentfiles);
5357 /****************************************************************************
5358 ****************************************************************************/
5360 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5362 DRIVER_INFO_1 *info=NULL;
5365 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5368 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5369 if (!W_ERROR_IS_OK(status)) {
5374 /* check the required size. */
5375 *needed += spoolss_size_printer_driver_info_1(info);
5377 if (!alloc_buffer_size(buffer, *needed)) {
5379 return WERR_INSUFFICIENT_BUFFER;
5382 /* fill the buffer with the structures */
5383 smb_io_printer_driver_info_1("", buffer, info, 0);
5388 if (*needed > offered)
5389 return WERR_INSUFFICIENT_BUFFER;
5394 /****************************************************************************
5395 ****************************************************************************/
5397 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5399 DRIVER_INFO_2 *info=NULL;
5402 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5405 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5406 if (!W_ERROR_IS_OK(status)) {
5411 /* check the required size. */
5412 *needed += spoolss_size_printer_driver_info_2(info);
5414 if (!alloc_buffer_size(buffer, *needed)) {
5416 return WERR_INSUFFICIENT_BUFFER;
5419 /* fill the buffer with the structures */
5420 smb_io_printer_driver_info_2("", buffer, info, 0);
5425 if (*needed > offered)
5426 return WERR_INSUFFICIENT_BUFFER;
5431 /****************************************************************************
5432 ****************************************************************************/
5434 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5441 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5442 if (!W_ERROR_IS_OK(status)) {
5446 /* check the required size. */
5447 *needed += spoolss_size_printer_driver_info_3(&info);
5449 if (!alloc_buffer_size(buffer, *needed)) {
5450 free_printer_driver_info_3(&info);
5451 return WERR_INSUFFICIENT_BUFFER;
5454 /* fill the buffer with the structures */
5455 smb_io_printer_driver_info_3("", buffer, &info, 0);
5457 free_printer_driver_info_3(&info);
5459 if (*needed > offered)
5460 return WERR_INSUFFICIENT_BUFFER;
5465 /****************************************************************************
5466 ****************************************************************************/
5468 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5475 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5476 if (!W_ERROR_IS_OK(status)) {
5480 /* check the required size. */
5481 *needed += spoolss_size_printer_driver_info_6(&info);
5483 if (!alloc_buffer_size(buffer, *needed)) {
5484 free_printer_driver_info_6(&info);
5485 return WERR_INSUFFICIENT_BUFFER;
5488 /* fill the buffer with the structures */
5489 smb_io_printer_driver_info_6("", buffer, &info, 0);
5491 free_printer_driver_info_6(&info);
5493 if (*needed > offered)
5494 return WERR_INSUFFICIENT_BUFFER;
5499 /****************************************************************************
5500 ****************************************************************************/
5502 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5504 POLICY_HND *handle = &q_u->handle;
5505 UNISTR2 *uni_arch = &q_u->architecture;
5506 uint32 level = q_u->level;
5507 uint32 clientmajorversion = q_u->clientmajorversion;
5508 NEW_BUFFER *buffer = NULL;
5509 uint32 offered = q_u->offered;
5510 uint32 *needed = &r_u->needed;
5511 uint32 *servermajorversion = &r_u->servermajorversion;
5512 uint32 *serverminorversion = &r_u->serverminorversion;
5515 fstring architecture;
5518 /* that's an [in out] buffer */
5519 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5520 buffer = r_u->buffer;
5522 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5525 *servermajorversion = 0;
5526 *serverminorversion = 0;
5528 fstrcpy(servername, get_called_name());
5529 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5531 if (!get_printer_snum(p, handle, &snum))
5536 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5538 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5540 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5542 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5545 return WERR_UNKNOWN_LEVEL;
5548 /****************************************************************************
5549 ****************************************************************************/
5551 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5553 POLICY_HND *handle = &q_u->handle;
5555 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5558 DEBUG(3,("Error in startpageprinter printer handle\n"));
5562 Printer->page_started=True;
5566 /****************************************************************************
5567 ****************************************************************************/
5569 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5571 POLICY_HND *handle = &q_u->handle;
5574 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5577 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5581 if (!get_printer_snum(p, handle, &snum))
5584 Printer->page_started=False;
5585 print_job_endpage(snum, Printer->jobid);
5590 /********************************************************************
5591 * api_spoolss_getprinter
5592 * called from the spoolss dispatcher
5594 ********************************************************************/
5596 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5598 POLICY_HND *handle = &q_u->handle;
5599 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5600 uint32 *jobid = &r_u->jobid;
5602 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5606 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5607 struct current_user user;
5610 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5614 get_current_user(&user, p);
5617 * a nice thing with NT is it doesn't listen to what you tell it.
5618 * when asked to send _only_ RAW datas, it tries to send datas
5621 * So I add checks like in NT Server ...
5624 if (info_1->p_datatype != 0) {
5625 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5626 if (strcmp(datatype, "RAW") != 0) {
5628 return WERR_INVALID_DATATYPE;
5632 /* get the share number of the printer */
5633 if (!get_printer_snum(p, handle, &snum)) {
5637 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5639 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5641 /* An error occured in print_job_start() so return an appropriate
5644 if (Printer->jobid == -1) {
5645 return map_werror_from_unix(errno);
5648 Printer->document_started=True;
5649 (*jobid) = Printer->jobid;
5654 /********************************************************************
5655 * api_spoolss_getprinter
5656 * called from the spoolss dispatcher
5658 ********************************************************************/
5660 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5662 POLICY_HND *handle = &q_u->handle;
5664 return _spoolss_enddocprinter_internal(p, handle);
5667 /****************************************************************************
5668 ****************************************************************************/
5670 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5672 POLICY_HND *handle = &q_u->handle;
5673 uint32 buffer_size = q_u->buffer_size;
5674 uint8 *buffer = q_u->buffer;
5675 uint32 *buffer_written = &q_u->buffer_size2;
5677 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5680 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5681 r_u->buffer_written = q_u->buffer_size2;
5685 if (!get_printer_snum(p, handle, &snum))
5688 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5689 if (*buffer_written == -1) {
5690 r_u->buffer_written = 0;
5691 if (errno == ENOSPC)
5692 return WERR_NO_SPOOL_SPACE;
5694 return WERR_ACCESS_DENIED;
5697 r_u->buffer_written = q_u->buffer_size2;
5702 /********************************************************************
5703 * api_spoolss_getprinter
5704 * called from the spoolss dispatcher
5706 ********************************************************************/
5708 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5711 struct current_user user;
5713 WERROR errcode = WERR_BADFUNC;
5714 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5716 get_current_user(&user, p);
5719 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5723 if (!get_printer_snum(p, handle, &snum))
5727 case PRINTER_CONTROL_PAUSE:
5728 if (print_queue_pause(&user, snum, &errcode)) {
5732 case PRINTER_CONTROL_RESUME:
5733 case PRINTER_CONTROL_UNPAUSE:
5734 if (print_queue_resume(&user, snum, &errcode)) {
5738 case PRINTER_CONTROL_PURGE:
5739 if (print_queue_purge(&user, snum, &errcode)) {
5744 return WERR_UNKNOWN_LEVEL;
5750 /********************************************************************
5751 * api_spoolss_abortprinter
5752 * From MSDN: "Deletes printer's spool file if printer is configured
5754 ********************************************************************/
5756 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5758 POLICY_HND *handle = &q_u->handle;
5759 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5761 struct current_user user;
5762 WERROR errcode = WERR_OK;
5765 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5769 if (!get_printer_snum(p, handle, &snum))
5772 get_current_user( &user, p );
5774 print_job_delete( &user, snum, Printer->jobid, &errcode );
5779 /********************************************************************
5780 * called by spoolss_api_setprinter
5781 * when updating a printer description
5782 ********************************************************************/
5784 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5785 const SPOOL_PRINTER_INFO_LEVEL *info,
5786 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5788 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5789 struct current_user user;
5793 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5795 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5796 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5797 OUR_HANDLE(handle)));
5799 result = WERR_BADFID;
5803 /* NT seems to like setting the security descriptor even though
5804 nothing may have actually changed. This causes annoying
5805 dialog boxes when the user doesn't have permission to change
5806 the security descriptor. */
5808 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5810 if (DEBUGLEVEL >= 10) {
5814 the_acl = old_secdesc_ctr->sec->dacl;
5815 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5816 PRINTERNAME(snum), the_acl->num_aces));
5818 for (i = 0; i < the_acl->num_aces; i++) {
5821 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5823 DEBUG(10, ("%s 0x%08x\n", sid_str,
5824 the_acl->ace[i].info.mask));
5827 the_acl = secdesc_ctr->sec->dacl;
5830 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5831 PRINTERNAME(snum), the_acl->num_aces));
5833 for (i = 0; i < the_acl->num_aces; i++) {
5836 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5838 DEBUG(10, ("%s 0x%08x\n", sid_str,
5839 the_acl->ace[i].info.mask));
5842 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5846 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5848 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5853 /* Work out which user is performing the operation */
5855 get_current_user(&user, p);
5857 /* Check the user has permissions to change the security
5858 descriptor. By experimentation with two NT machines, the user
5859 requires Full Access to the printer to change security
5862 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5863 result = WERR_ACCESS_DENIED;
5867 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5874 /********************************************************************
5875 Do Samba sanity checks on a printer info struct.
5876 this has changed purpose: it now "canonicalises" printer
5877 info from a client rather than just checking it is correct
5878 ********************************************************************/
5880 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5882 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5883 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5885 /* we force some elements to "correct" values */
5886 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5887 fstrcpy(info->sharename, lp_servicename(snum));
5888 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5889 get_called_name(), info->sharename);
5890 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5896 /****************************************************************************
5897 ****************************************************************************/
5899 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5901 extern userdom_struct current_user_info;
5902 char *cmd = lp_addprinter_cmd();
5908 fstring remote_machine = "%m";
5910 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5912 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5913 cmd, printer->info_2->printername, printer->info_2->sharename,
5914 printer->info_2->portname, printer->info_2->drivername,
5915 printer->info_2->location, printer->info_2->comment, remote_machine);
5917 DEBUG(10,("Running [%s]\n", command));
5918 ret = smbrun(command, &fd);
5919 DEBUGADD(10,("returned [%d]\n", ret));
5928 /* Get lines and convert them back to dos-codepage */
5929 qlines = fd_lines_load(fd, &numlines);
5930 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5934 /* Set the portname to what the script says the portname should be. */
5935 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5936 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5938 /* Send SIGHUP to process group... is there a better way? */
5941 /* reload our services immediately */
5942 reload_services( False );
5945 file_lines_free(qlines);
5949 /********************************************************************
5950 * Called by spoolss_api_setprinter
5951 * when updating a printer description.
5952 ********************************************************************/
5954 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5955 const SPOOL_PRINTER_INFO_LEVEL *info,
5956 DEVICEMODE *devmode)
5959 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5960 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5965 DEBUG(8,("update_printer\n"));
5970 result = WERR_BADFID;
5974 if (!get_printer_snum(p, handle, &snum)) {
5975 result = WERR_BADFID;
5979 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5980 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5981 result = WERR_BADFID;
5985 DEBUGADD(8,("Converting info_2 struct\n"));
5988 * convert_printer_info converts the incoming
5989 * info from the client and overwrites the info
5990 * just read from the tdb in the pointer 'printer'.
5993 if (!convert_printer_info(info, printer, level)) {
5994 result = WERR_NOMEM;
5999 /* we have a valid devmode
6000 convert it and link it*/
6002 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6003 if (!convert_devicemode(printer->info_2->printername, devmode,
6004 &printer->info_2->devmode)) {
6005 result = WERR_NOMEM;
6010 /* Do sanity check on the requested changes for Samba */
6012 if (!check_printer_ok(printer->info_2, snum)) {
6013 result = WERR_INVALID_PARAM;
6017 /* FIXME!!! If the driver has changed we really should verify that
6018 it is installed before doing much else --jerry */
6020 /* Check calling user has permission to update printer description */
6022 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6023 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6024 result = WERR_ACCESS_DENIED;
6028 /* Call addprinter hook */
6029 /* Check changes to see if this is really needed */
6031 if ( *lp_addprinter_cmd()
6032 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6033 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6034 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6035 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6037 if ( !add_printer_hook(printer) ) {
6038 result = WERR_ACCESS_DENIED;
6043 * make sure we actually reload the services after
6044 * this as smb.conf could have a new section in it
6045 * .... shouldn't .... but could
6047 reload_services(False);
6051 * When a *new* driver is bound to a printer, the drivername is used to
6052 * lookup previously saved driver initialization info, which is then
6053 * bound to the printer, simulating what happens in the Windows arch.
6055 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6057 if (!set_driver_init(printer, 2))
6059 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6060 printer->info_2->drivername));
6063 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6064 printer->info_2->drivername));
6066 notify_printer_driver(snum, printer->info_2->drivername);
6070 * flag which changes actually occured. This is a small subset of
6071 * all the possible changes. We also have to update things in the
6075 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6076 init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 );
6077 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6078 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6080 notify_printer_comment(snum, printer->info_2->comment);
6083 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6084 init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 );
6085 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6086 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6087 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6088 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6090 notify_printer_sharename(snum, printer->info_2->sharename);
6093 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6094 init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 );
6095 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6096 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6098 notify_printer_port(snum, printer->info_2->portname);
6101 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6102 init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 );
6103 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6104 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6106 notify_printer_location(snum, printer->info_2->location);
6109 /* here we need to update some more DsSpooler keys */
6110 /* uNCName, serverName, shortServerName */
6112 init_unistr2( &buffer, global_myname(), strlen(global_myname())+1 );
6113 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6114 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6115 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6116 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6118 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6119 global_myname(), printer->info_2->sharename );
6120 init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 );
6121 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6122 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6124 /* Update printer info */
6125 result = mod_a_printer(*printer, 2);
6128 free_a_printer(&printer, 2);
6129 free_a_printer(&old_printer, 2);
6135 /****************************************************************************
6136 ****************************************************************************/
6137 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6138 const SPOOL_PRINTER_INFO_LEVEL *info)
6141 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6143 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6146 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6153 if (!get_printer_snum(p, handle, &snum))
6156 nt_printer_publish(Printer, snum, info7->action);
6160 return WERR_UNKNOWN_LEVEL;
6163 /****************************************************************************
6164 ****************************************************************************/
6166 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6168 POLICY_HND *handle = &q_u->handle;
6169 uint32 level = q_u->level;
6170 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6171 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6172 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6173 uint32 command = q_u->command;
6175 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6178 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6182 /* check the level */
6185 return control_printer(handle, command, p);
6187 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6189 return update_printer_sec(handle, level, info, p,
6192 return publish_or_unpublish_printer(p, handle, info);
6194 return WERR_UNKNOWN_LEVEL;
6198 /****************************************************************************
6199 ****************************************************************************/
6201 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6203 POLICY_HND *handle = &q_u->handle;
6204 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6207 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6211 if (Printer->notify.client_connected==True) {
6214 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6216 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6217 !get_printer_snum(p, handle, &snum) )
6220 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6223 Printer->notify.flags=0;
6224 Printer->notify.options=0;
6225 Printer->notify.localmachine[0]='\0';
6226 Printer->notify.printerlocal=0;
6227 if (Printer->notify.option)
6228 free_spool_notify_option(&Printer->notify.option);
6229 Printer->notify.client_connected=False;
6234 /****************************************************************************
6235 ****************************************************************************/
6237 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6239 /* that's an [in out] buffer (despite appearences to the contrary) */
6240 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6243 return WERR_INVALID_PARAM; /* this is what a NT server
6244 returns for AddJob. AddJob
6245 must fail on non-local
6249 /****************************************************************************
6250 ****************************************************************************/
6252 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6253 int position, int snum)
6259 t=gmtime(&queue->time);
6260 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6262 job_info->jobid=queue->job;
6263 init_unistr(&job_info->printername, lp_servicename(snum));
6264 init_unistr(&job_info->machinename, temp_name);
6265 init_unistr(&job_info->username, queue->fs_user);
6266 init_unistr(&job_info->document, queue->fs_file);
6267 init_unistr(&job_info->datatype, "RAW");
6268 init_unistr(&job_info->text_status, "");
6269 job_info->status=nt_printj_status(queue->status);
6270 job_info->priority=queue->priority;
6271 job_info->position=position;
6272 job_info->totalpages=queue->page_count;
6273 job_info->pagesprinted=0;
6275 make_systemtime(&job_info->submitted, t);
6278 /****************************************************************************
6279 ****************************************************************************/
6281 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6282 int position, int snum,
6283 NT_PRINTER_INFO_LEVEL *ntprinter,
6284 DEVICEMODE *devmode)
6289 t=gmtime(&queue->time);
6290 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6292 job_info->jobid=queue->job;
6294 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6296 init_unistr(&job_info->machinename, temp_name);
6297 init_unistr(&job_info->username, queue->fs_user);
6298 init_unistr(&job_info->document, queue->fs_file);
6299 init_unistr(&job_info->notifyname, queue->fs_user);
6300 init_unistr(&job_info->datatype, "RAW");
6301 init_unistr(&job_info->printprocessor, "winprint");
6302 init_unistr(&job_info->parameters, "");
6303 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6304 init_unistr(&job_info->text_status, "");
6306 /* and here the security descriptor */
6308 job_info->status=nt_printj_status(queue->status);
6309 job_info->priority=queue->priority;
6310 job_info->position=position;
6311 job_info->starttime=0;
6312 job_info->untiltime=0;
6313 job_info->totalpages=queue->page_count;
6314 job_info->size=queue->size;
6315 make_systemtime(&(job_info->submitted), t);
6316 job_info->timeelapsed=0;
6317 job_info->pagesprinted=0;
6319 job_info->devmode = devmode;
6324 /****************************************************************************
6325 Enumjobs at level 1.
6326 ****************************************************************************/
6328 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6329 NEW_BUFFER *buffer, uint32 offered,
6330 uint32 *needed, uint32 *returned)
6335 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6342 for (i=0; i<*returned; i++)
6343 fill_job_info_1(&info[i], &queue[i], i, snum);
6347 /* check the required size. */
6348 for (i=0; i<*returned; i++)
6349 (*needed) += spoolss_size_job_info_1(&info[i]);
6351 if (!alloc_buffer_size(buffer, *needed)) {
6353 return WERR_INSUFFICIENT_BUFFER;
6356 /* fill the buffer with the structures */
6357 for (i=0; i<*returned; i++)
6358 smb_io_job_info_1("", buffer, &info[i], 0);
6363 if (*needed > offered) {
6365 return WERR_INSUFFICIENT_BUFFER;
6371 /****************************************************************************
6372 Enumjobs at level 2.
6373 ****************************************************************************/
6375 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6376 NEW_BUFFER *buffer, uint32 offered,
6377 uint32 *needed, uint32 *returned)
6379 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6380 JOB_INFO_2 *info = NULL;
6383 DEVICEMODE *devmode = NULL;
6385 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6388 result = WERR_NOMEM;
6392 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6393 if (!W_ERROR_IS_OK(result)) {
6398 /* this should not be a failure condition if the devmode is NULL */
6400 devmode = construct_dev_mode(snum);
6402 for (i=0; i<*returned; i++)
6403 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6406 free_a_printer(&ntprinter, 2);
6409 /* check the required size. */
6410 for (i=0; i<*returned; i++)
6411 (*needed) += spoolss_size_job_info_2(&info[i]);
6413 if (*needed > offered) {
6415 result = WERR_INSUFFICIENT_BUFFER;
6419 if (!alloc_buffer_size(buffer, *needed)) {
6421 result = WERR_INSUFFICIENT_BUFFER;
6425 /* fill the buffer with the structures */
6426 for (i=0; i<*returned; i++)
6427 smb_io_job_info_2("", buffer, &info[i], 0);
6432 free_a_printer(&ntprinter, 2);
6433 free_devmode(devmode);
6441 /****************************************************************************
6443 ****************************************************************************/
6445 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6447 POLICY_HND *handle = &q_u->handle;
6448 uint32 level = q_u->level;
6449 NEW_BUFFER *buffer = NULL;
6450 uint32 offered = q_u->offered;
6451 uint32 *needed = &r_u->needed;
6452 uint32 *returned = &r_u->returned;
6456 print_status_struct prt_status;
6457 print_queue_struct *queue=NULL;
6459 /* that's an [in out] buffer */
6460 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6461 buffer = r_u->buffer;
6463 DEBUG(4,("_spoolss_enumjobs\n"));
6468 if (!get_printer_snum(p, handle, &snum))
6471 *returned = print_queue_status(snum, &queue, &prt_status);
6472 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6474 if (*returned == 0) {
6475 set_enumjobs_timestamp(snum);
6482 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6483 set_enumjobs_timestamp(snum);
6486 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6487 set_enumjobs_timestamp(snum);
6492 return WERR_UNKNOWN_LEVEL;
6496 /****************************************************************************
6497 ****************************************************************************/
6499 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6504 /****************************************************************************
6505 ****************************************************************************/
6507 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6509 POLICY_HND *handle = &q_u->handle;
6510 uint32 jobid = q_u->jobid;
6511 uint32 command = q_u->command;
6513 struct current_user user;
6515 WERROR errcode = WERR_BADFUNC;
6517 if (!get_printer_snum(p, handle, &snum)) {
6521 if (!print_job_exists(snum, jobid)) {
6522 return WERR_INVALID_PRINTER_NAME;
6525 get_current_user(&user, p);
6528 case JOB_CONTROL_CANCEL:
6529 case JOB_CONTROL_DELETE:
6530 if (print_job_delete(&user, snum, jobid, &errcode)) {
6534 case JOB_CONTROL_PAUSE:
6535 if (print_job_pause(&user, snum, jobid, &errcode)) {
6539 case JOB_CONTROL_RESTART:
6540 case JOB_CONTROL_RESUME:
6541 if (print_job_resume(&user, snum, jobid, &errcode)) {
6546 return WERR_UNKNOWN_LEVEL;
6552 /****************************************************************************
6553 Enumerates all printer drivers at level 1.
6554 ****************************************************************************/
6556 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6561 fstring *list = NULL;
6563 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6564 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6568 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6570 ndrivers=get_ntdrivers(&list, architecture, version);
6571 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6577 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6578 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6579 SAFE_FREE(driver_info_1);
6583 else driver_info_1 = tdi1;
6586 for (i=0; i<ndrivers; i++) {
6588 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6589 ZERO_STRUCT(driver);
6590 status = get_a_printer_driver(&driver, 3, list[i],
6591 architecture, version);
6592 if (!W_ERROR_IS_OK(status)) {
6596 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6597 free_a_printer_driver(driver, 3);
6600 *returned+=ndrivers;
6604 /* check the required size. */
6605 for (i=0; i<*returned; i++) {
6606 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6607 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6610 if (!alloc_buffer_size(buffer, *needed)) {
6611 SAFE_FREE(driver_info_1);
6612 return WERR_INSUFFICIENT_BUFFER;
6615 /* fill the buffer with the driver structures */
6616 for (i=0; i<*returned; i++) {
6617 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6618 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6621 SAFE_FREE(driver_info_1);
6623 if (*needed > offered) {
6625 return WERR_INSUFFICIENT_BUFFER;
6631 /****************************************************************************
6632 Enumerates all printer drivers at level 2.
6633 ****************************************************************************/
6635 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6640 fstring *list = NULL;
6642 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6643 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6647 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6649 ndrivers=get_ntdrivers(&list, architecture, version);
6650 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6656 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6657 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6658 SAFE_FREE(driver_info_2);
6662 else driver_info_2 = tdi2;
6665 for (i=0; i<ndrivers; i++) {
6668 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6669 ZERO_STRUCT(driver);
6670 status = get_a_printer_driver(&driver, 3, list[i],
6671 architecture, version);
6672 if (!W_ERROR_IS_OK(status)) {
6676 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6677 free_a_printer_driver(driver, 3);
6680 *returned+=ndrivers;
6684 /* check the required size. */
6685 for (i=0; i<*returned; i++) {
6686 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6687 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6690 if (!alloc_buffer_size(buffer, *needed)) {
6691 SAFE_FREE(driver_info_2);
6692 return WERR_INSUFFICIENT_BUFFER;
6695 /* fill the buffer with the form structures */
6696 for (i=0; i<*returned; i++) {
6697 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6698 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6701 SAFE_FREE(driver_info_2);
6703 if (*needed > offered) {
6705 return WERR_INSUFFICIENT_BUFFER;
6711 /****************************************************************************
6712 Enumerates all printer drivers at level 3.
6713 ****************************************************************************/
6715 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6720 fstring *list = NULL;
6722 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6723 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6727 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6729 ndrivers=get_ntdrivers(&list, architecture, version);
6730 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6736 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6737 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6738 SAFE_FREE(driver_info_3);
6742 else driver_info_3 = tdi3;
6745 for (i=0; i<ndrivers; i++) {
6748 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6749 ZERO_STRUCT(driver);
6750 status = get_a_printer_driver(&driver, 3, list[i],
6751 architecture, version);
6752 if (!W_ERROR_IS_OK(status)) {
6756 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6757 free_a_printer_driver(driver, 3);
6760 *returned+=ndrivers;
6764 /* check the required size. */
6765 for (i=0; i<*returned; i++) {
6766 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6767 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6770 if (!alloc_buffer_size(buffer, *needed)) {
6771 SAFE_FREE(driver_info_3);
6772 return WERR_INSUFFICIENT_BUFFER;
6775 /* fill the buffer with the driver structures */
6776 for (i=0; i<*returned; i++) {
6777 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6778 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6781 for (i=0; i<*returned; i++)
6782 SAFE_FREE(driver_info_3[i].dependentfiles);
6784 SAFE_FREE(driver_info_3);
6786 if (*needed > offered) {
6788 return WERR_INSUFFICIENT_BUFFER;
6794 /****************************************************************************
6795 Enumerates all printer drivers.
6796 ****************************************************************************/
6798 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6800 UNISTR2 *environment = &q_u->environment;
6801 uint32 level = q_u->level;
6802 NEW_BUFFER *buffer = NULL;
6803 uint32 offered = q_u->offered;
6804 uint32 *needed = &r_u->needed;
6805 uint32 *returned = &r_u->returned;
6807 fstring *list = NULL;
6809 fstring architecture;
6811 /* that's an [in out] buffer */
6812 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6813 buffer = r_u->buffer;
6815 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6816 fstrcpy(servername, get_called_name());
6820 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6824 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6826 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6828 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6832 return WERR_UNKNOWN_LEVEL;
6836 /****************************************************************************
6837 ****************************************************************************/
6839 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6841 form->flag=list->flag;
6842 init_unistr(&form->name, list->name);
6843 form->width=list->width;
6844 form->length=list->length;
6845 form->left=list->left;
6846 form->top=list->top;
6847 form->right=list->right;
6848 form->bottom=list->bottom;
6851 /****************************************************************************
6852 ****************************************************************************/
6854 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6856 uint32 level = q_u->level;
6857 NEW_BUFFER *buffer = NULL;
6858 uint32 offered = q_u->offered;
6859 uint32 *needed = &r_u->needed;
6860 uint32 *numofforms = &r_u->numofforms;
6861 uint32 numbuiltinforms;
6863 nt_forms_struct *list=NULL;
6864 nt_forms_struct *builtinlist=NULL;
6869 /* that's an [in out] buffer */
6870 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6871 buffer = r_u->buffer;
6873 DEBUG(4,("_spoolss_enumforms\n"));
6874 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6875 DEBUGADD(5,("Info level [%d]\n", level));
6877 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6878 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6879 *numofforms = get_ntforms(&list);
6880 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6881 *numofforms += numbuiltinforms;
6883 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6887 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6892 /* construct the list of form structures */
6893 for (i=0; i<numbuiltinforms; i++) {
6894 DEBUGADD(6,("Filling form number [%d]\n",i));
6895 fill_form_1(&forms_1[i], &builtinlist[i]);
6898 SAFE_FREE(builtinlist);
6900 for (; i<*numofforms; i++) {
6901 DEBUGADD(6,("Filling form number [%d]\n",i));
6902 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6907 /* check the required size. */
6908 for (i=0; i<numbuiltinforms; i++) {
6909 DEBUGADD(6,("adding form [%d]'s size\n",i));
6910 buffer_size += spoolss_size_form_1(&forms_1[i]);
6912 for (; i<*numofforms; i++) {
6913 DEBUGADD(6,("adding form [%d]'s size\n",i));
6914 buffer_size += spoolss_size_form_1(&forms_1[i]);
6917 *needed=buffer_size;
6919 if (!alloc_buffer_size(buffer, buffer_size)){
6921 return WERR_INSUFFICIENT_BUFFER;
6924 /* fill the buffer with the form structures */
6925 for (i=0; i<numbuiltinforms; i++) {
6926 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6927 smb_io_form_1("", buffer, &forms_1[i], 0);
6929 for (; i<*numofforms; i++) {
6930 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6931 smb_io_form_1("", buffer, &forms_1[i], 0);
6936 if (*needed > offered) {
6938 return WERR_INSUFFICIENT_BUFFER;
6945 SAFE_FREE(builtinlist);
6946 return WERR_UNKNOWN_LEVEL;
6951 /****************************************************************************
6952 ****************************************************************************/
6954 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6956 uint32 level = q_u->level;
6957 UNISTR2 *uni_formname = &q_u->formname;
6958 NEW_BUFFER *buffer = NULL;
6959 uint32 offered = q_u->offered;
6960 uint32 *needed = &r_u->needed;
6962 nt_forms_struct *list=NULL;
6963 nt_forms_struct builtin_form;
6968 int numofforms=0, i=0;
6970 /* that's an [in out] buffer */
6971 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6972 buffer = r_u->buffer;
6974 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6976 DEBUG(4,("_spoolss_getform\n"));
6977 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6978 DEBUGADD(5,("Info level [%d]\n", level));
6980 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6981 if (!foundBuiltin) {
6982 numofforms = get_ntforms(&list);
6983 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6985 if (numofforms == 0)
6992 fill_form_1(&form_1, &builtin_form);
6995 /* Check if the requested name is in the list of form structures */
6996 for (i=0; i<numofforms; i++) {
6998 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7000 if (strequal(form_name, list[i].name)) {
7001 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7002 fill_form_1(&form_1, &list[i]);
7008 if (i == numofforms) {
7012 /* check the required size. */
7014 *needed=spoolss_size_form_1(&form_1);
7016 if (!alloc_buffer_size(buffer, buffer_size)){
7017 return WERR_INSUFFICIENT_BUFFER;
7020 if (*needed > offered) {
7021 return WERR_INSUFFICIENT_BUFFER;
7024 /* fill the buffer with the form structures */
7025 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7026 smb_io_form_1("", buffer, &form_1, 0);
7032 return WERR_UNKNOWN_LEVEL;
7036 /****************************************************************************
7037 ****************************************************************************/
7039 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7041 init_unistr(&port->port_name, name);
7044 /****************************************************************************
7045 ****************************************************************************/
7047 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7049 init_unistr(&port->port_name, name);
7050 init_unistr(&port->monitor_name, "Local Monitor");
7051 init_unistr(&port->description, "Local Port");
7052 #define PORT_TYPE_WRITE 1
7053 port->port_type=PORT_TYPE_WRITE;
7057 /****************************************************************************
7059 ****************************************************************************/
7061 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7063 PORT_INFO_1 *ports=NULL;
7066 if (*lp_enumports_cmd()) {
7067 char *cmd = lp_enumports_cmd();
7074 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7076 DEBUG(10,("Running [%s]\n", command));
7077 ret = smbrun(command, &fd);
7078 DEBUG(10,("Returned [%d]\n", ret));
7082 /* Is this the best error to return here? */
7083 return WERR_ACCESS_DENIED;
7087 qlines = fd_lines_load(fd, &numlines);
7088 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7092 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7093 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7094 dos_errstr(WERR_NOMEM)));
7095 file_lines_free(qlines);
7099 for (i=0; i<numlines; i++) {
7100 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7101 fill_port_1(&ports[i], qlines[i]);
7104 file_lines_free(qlines);
7107 *returned = numlines;
7110 *returned = 1; /* Sole Samba port returned. */
7112 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7115 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7117 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7120 /* check the required size. */
7121 for (i=0; i<*returned; i++) {
7122 DEBUGADD(6,("adding port [%d]'s size\n", i));
7123 *needed += spoolss_size_port_info_1(&ports[i]);
7126 if (!alloc_buffer_size(buffer, *needed)) {
7128 return WERR_INSUFFICIENT_BUFFER;
7131 /* fill the buffer with the ports structures */
7132 for (i=0; i<*returned; i++) {
7133 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7134 smb_io_port_1("", buffer, &ports[i], 0);
7139 if (*needed > offered) {
7141 return WERR_INSUFFICIENT_BUFFER;
7147 /****************************************************************************
7149 ****************************************************************************/
7151 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7153 PORT_INFO_2 *ports=NULL;
7156 if (*lp_enumports_cmd()) {
7157 char *cmd = lp_enumports_cmd();
7166 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7167 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7169 path = lp_lockdir();
7171 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7172 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7175 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7176 ret = smbrun(command, &fd);
7177 DEBUGADD(10,("returned [%d]\n", ret));
7181 /* Is this the best error to return here? */
7182 return WERR_ACCESS_DENIED;
7186 qlines = fd_lines_load(fd, &numlines);
7187 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7191 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7192 file_lines_free(qlines);
7196 for (i=0; i<numlines; i++) {
7197 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7198 fill_port_2(&(ports[i]), qlines[i]);
7201 file_lines_free(qlines);
7204 *returned = numlines;
7210 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7213 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7215 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7218 /* check the required size. */
7219 for (i=0; i<*returned; i++) {
7220 DEBUGADD(6,("adding port [%d]'s size\n", i));
7221 *needed += spoolss_size_port_info_2(&ports[i]);
7224 if (!alloc_buffer_size(buffer, *needed)) {
7226 return WERR_INSUFFICIENT_BUFFER;
7229 /* fill the buffer with the ports structures */
7230 for (i=0; i<*returned; i++) {
7231 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7232 smb_io_port_2("", buffer, &ports[i], 0);
7237 if (*needed > offered) {
7239 return WERR_INSUFFICIENT_BUFFER;
7245 /****************************************************************************
7247 ****************************************************************************/
7249 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7251 uint32 level = q_u->level;
7252 NEW_BUFFER *buffer = NULL;
7253 uint32 offered = q_u->offered;
7254 uint32 *needed = &r_u->needed;
7255 uint32 *returned = &r_u->returned;
7257 /* that's an [in out] buffer */
7258 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7259 buffer = r_u->buffer;
7261 DEBUG(4,("_spoolss_enumports\n"));
7268 return enumports_level_1(buffer, offered, needed, returned);
7270 return enumports_level_2(buffer, offered, needed, returned);
7272 return WERR_UNKNOWN_LEVEL;
7276 /****************************************************************************
7277 ****************************************************************************/
7279 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7280 const SPOOL_PRINTER_INFO_LEVEL *info,
7281 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7282 uint32 user_switch, const SPOOL_USER_CTR *user,
7285 NT_PRINTER_INFO_LEVEL *printer = NULL;
7288 WERROR err = WERR_OK;
7290 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7291 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7295 ZERO_STRUCTP(printer);
7297 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7298 if (!convert_printer_info(info, printer, 2)) {
7299 free_a_printer(&printer, 2);
7303 /* check to see if the printer already exists */
7305 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7306 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7307 printer->info_2->sharename));
7308 free_a_printer(&printer, 2);
7309 return WERR_PRINTER_ALREADY_EXISTS;
7312 /* FIXME!!! smbd should check to see if the driver is installed before
7313 trying to add a printer like this --jerry */
7315 if (*lp_addprinter_cmd() ) {
7316 if ( !add_printer_hook(printer) ) {
7317 free_a_printer(&printer,2);
7318 return WERR_ACCESS_DENIED;
7322 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7323 printer->info_2->sharename);
7326 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7327 free_a_printer(&printer,2);
7328 return WERR_ACCESS_DENIED;
7331 /* you must be a printer admin to add a new printer */
7332 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7333 free_a_printer(&printer,2);
7334 return WERR_ACCESS_DENIED;
7338 * Do sanity check on the requested changes for Samba.
7341 if (!check_printer_ok(printer->info_2, snum)) {
7342 free_a_printer(&printer,2);
7343 return WERR_INVALID_PARAM;
7347 * When a printer is created, the drivername bound to the printer is used
7348 * to lookup previously saved driver initialization info, which is then
7349 * bound to the new printer, simulating what happens in the Windows arch.
7354 set_driver_init(printer, 2);
7358 /* A valid devmode was included, convert and link it
7360 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7362 if (!convert_devicemode(printer->info_2->printername, devmode,
7363 &printer->info_2->devmode))
7367 /* write the ASCII on disk */
7368 err = mod_a_printer(*printer, 2);
7369 if (!W_ERROR_IS_OK(err)) {
7370 free_a_printer(&printer,2);
7374 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7375 /* Handle open failed - remove addition. */
7376 del_a_printer(printer->info_2->sharename);
7377 free_a_printer(&printer,2);
7378 return WERR_ACCESS_DENIED;
7381 update_c_setprinter(False);
7382 free_a_printer(&printer,2);
7387 /****************************************************************************
7388 ****************************************************************************/
7390 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7392 UNISTR2 *uni_srv_name = &q_u->server_name;
7393 uint32 level = q_u->level;
7394 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7395 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7396 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7397 uint32 user_switch = q_u->user_switch;
7398 SPOOL_USER_CTR *user = &q_u->user_ctr;
7399 POLICY_HND *handle = &r_u->handle;
7403 /* we don't handle yet */
7404 /* but I know what to do ... */
7405 return WERR_UNKNOWN_LEVEL;
7407 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7409 user_switch, user, handle);
7411 return WERR_UNKNOWN_LEVEL;
7415 /****************************************************************************
7416 ****************************************************************************/
7418 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7420 uint32 level = q_u->level;
7421 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7422 WERROR err = WERR_OK;
7423 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7424 struct current_user user;
7425 fstring driver_name;
7428 ZERO_STRUCT(driver);
7430 get_current_user(&user, p);
7432 if (!convert_printer_driver_info(info, &driver, level)) {
7437 DEBUG(5,("Cleaning driver's information\n"));
7438 err = clean_up_driver_struct(driver, level, &user);
7439 if (!W_ERROR_IS_OK(err))
7442 DEBUG(5,("Moving driver to final destination\n"));
7443 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7444 if (W_ERROR_IS_OK(err))
7445 err = WERR_ACCESS_DENIED;
7449 if (add_a_printer_driver(driver, level)!=0) {
7450 err = WERR_ACCESS_DENIED;
7454 /* BEGIN_ADMIN_LOG */
7457 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7458 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7459 fstrcpy(driver_name, driver.info_3->name);
7462 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7463 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7464 fstrcpy(driver_name, driver.info_6->name);
7470 * I think this is where he DrvUpgradePrinter() hook would be
7471 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7472 * server. Right now, we just need to send ourselves a message
7473 * to update each printer bound to this driver. --jerry
7476 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7477 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7482 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7483 * decide if the driver init data should be deleted. The rules are:
7484 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7485 * 2) delete init data only if there is no 2k/Xp driver
7486 * 3) always delete init data
7487 * The generalized rule is always use init data from the highest order driver.
7488 * It is necessary to follow the driver install by an initialization step to
7489 * finish off this process.
7492 version = driver.info_3->cversion;
7493 else if (level == 6)
7494 version = driver.info_6->version;
7499 * 9x printer driver - never delete init data
7502 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7507 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7508 * there is no 2k/Xp driver init data for this driver name.
7512 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7514 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7516 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7518 if (!del_driver_init(driver_name))
7519 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7522 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7524 free_a_printer_driver(driver1,3);
7525 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7532 * 2k or Xp printer driver - always delete init data
7535 if (!del_driver_init(driver_name))
7536 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7540 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7546 free_a_printer_driver(driver, level);
7550 /********************************************************************
7551 * spoolss_addprinterdriverex
7552 ********************************************************************/
7554 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7556 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7557 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7560 * we only support the semantics of AddPrinterDriver()
7561 * i.e. only copy files that are newer than existing ones
7564 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7565 return WERR_ACCESS_DENIED;
7567 ZERO_STRUCT(q_u_local);
7568 ZERO_STRUCT(r_u_local);
7570 /* just pass the information off to _spoolss_addprinterdriver() */
7571 q_u_local.server_name_ptr = q_u->server_name_ptr;
7572 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7573 q_u_local.level = q_u->level;
7574 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7576 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7579 /****************************************************************************
7580 ****************************************************************************/
7582 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7584 init_unistr(&info->name, name);
7587 /****************************************************************************
7588 ****************************************************************************/
7590 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7594 pstring short_archi;
7595 DRIVER_DIRECTORY_1 *info=NULL;
7597 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7599 if (get_short_archi(short_archi, long_archi)==False)
7600 return WERR_INVALID_ENVIRONMENT;
7602 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7605 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7607 DEBUG(4,("printer driver directory: [%s]\n", path));
7609 fill_driverdir_1(info, path);
7611 *needed += spoolss_size_driverdir_info_1(info);
7613 if (!alloc_buffer_size(buffer, *needed)) {
7615 return WERR_INSUFFICIENT_BUFFER;
7618 smb_io_driverdir_1("", buffer, info, 0);
7622 if (*needed > offered)
7623 return WERR_INSUFFICIENT_BUFFER;
7628 /****************************************************************************
7629 ****************************************************************************/
7631 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7633 UNISTR2 *name = &q_u->name;
7634 UNISTR2 *uni_environment = &q_u->environment;
7635 uint32 level = q_u->level;
7636 NEW_BUFFER *buffer = NULL;
7637 uint32 offered = q_u->offered;
7638 uint32 *needed = &r_u->needed;
7640 /* that's an [in out] buffer */
7641 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7642 buffer = r_u->buffer;
7644 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7650 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7652 return WERR_UNKNOWN_LEVEL;
7656 /****************************************************************************
7657 ****************************************************************************/
7659 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7661 POLICY_HND *handle = &q_u->handle;
7662 uint32 idx = q_u->index;
7663 uint32 in_value_len = q_u->valuesize;
7664 uint32 in_data_len = q_u->datasize;
7665 uint32 *out_max_value_len = &r_u->valuesize;
7666 uint16 **out_value = &r_u->value;
7667 uint32 *out_value_len = &r_u->realvaluesize;
7668 uint32 *out_type = &r_u->type;
7669 uint32 *out_max_data_len = &r_u->datasize;
7670 uint8 **data_out = &r_u->data;
7671 uint32 *out_data_len = &r_u->realdatasize;
7673 NT_PRINTER_INFO_LEVEL *printer = NULL;
7676 uint32 biggest_valuesize;
7677 uint32 biggest_datasize;
7679 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7682 REGISTRY_VALUE *val = NULL;
7683 NT_PRINTER_DATA *p_data;
7684 int i, key_index, num_values;
7687 ZERO_STRUCT( printer );
7691 *out_max_data_len = 0;
7695 DEBUG(5,("spoolss_enumprinterdata\n"));
7698 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7702 if (!get_printer_snum(p,handle, &snum))
7705 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7706 if (!W_ERROR_IS_OK(result))
7709 p_data = &printer->info_2->data;
7710 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7715 * The NT machine wants to know the biggest size of value and data
7717 * cf: MSDN EnumPrinterData remark section
7720 if ( !in_value_len && !in_data_len && (key_index != -1) )
7722 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7725 biggest_valuesize = 0;
7726 biggest_datasize = 0;
7728 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7730 for ( i=0; i<num_values; i++ )
7732 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7734 name_length = strlen(val->valuename);
7735 if ( strlen(val->valuename) > biggest_valuesize )
7736 biggest_valuesize = name_length;
7738 if ( val->size > biggest_datasize )
7739 biggest_datasize = val->size;
7741 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7745 /* the value is an UNICODE string but real_value_size is the length
7746 in bytes including the trailing 0 */
7748 *out_value_len = 2 * (1+biggest_valuesize);
7749 *out_data_len = biggest_datasize;
7751 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7757 * the value len is wrong in NT sp3
7758 * that's the number of bytes not the number of unicode chars
7761 if ( key_index != -1 )
7762 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7767 /* out_value should default to "" or else NT4 has
7768 problems unmarshalling the response */
7770 *out_max_value_len=(in_value_len/sizeof(uint16));
7772 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7774 result = WERR_NOMEM;
7778 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7780 /* the data is counted in bytes */
7782 *out_max_data_len = in_data_len;
7783 *out_data_len = in_data_len;
7785 /* only allocate when given a non-zero data_len */
7787 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7789 result = WERR_NOMEM;
7793 result = WERR_NO_MORE_ITEMS;
7799 * - counted in bytes in the request
7800 * - counted in UNICODE chars in the max reply
7801 * - counted in bytes in the real size
7803 * take a pause *before* coding not *during* coding
7807 *out_max_value_len=(in_value_len/sizeof(uint16));
7808 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7810 result = WERR_NOMEM;
7814 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7818 *out_type = regval_type( val );
7820 /* data - counted in bytes */
7822 *out_max_data_len = in_data_len;
7823 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7825 result = WERR_NOMEM;
7828 data_len = (size_t)regval_size(val);
7829 memcpy( *data_out, regval_data_p(val), data_len );
7830 *out_data_len = data_len;
7834 free_a_printer(&printer, 2);
7838 /****************************************************************************
7839 ****************************************************************************/
7841 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7843 POLICY_HND *handle = &q_u->handle;
7844 UNISTR2 *value = &q_u->value;
7845 uint32 type = q_u->type;
7846 uint8 *data = q_u->data;
7847 uint32 real_len = q_u->real_len;
7849 NT_PRINTER_INFO_LEVEL *printer = NULL;
7851 WERROR status = WERR_OK;
7852 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7855 DEBUG(5,("spoolss_setprinterdata\n"));
7858 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7862 if (!get_printer_snum(p,handle, &snum))
7866 * Access check : NT returns "access denied" if you make a
7867 * SetPrinterData call without the necessary privildge.
7868 * we were originally returning OK if nothing changed
7869 * which made Win2k issue **a lot** of SetPrinterData
7870 * when connecting to a printer --jerry
7873 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7875 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7876 status = WERR_ACCESS_DENIED;
7880 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7881 if (!W_ERROR_IS_OK(status))
7884 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7887 * When client side code sets a magic printer data key, detect it and save
7888 * the current printer data and the magic key's data (its the DEVMODE) for
7889 * future printer/driver initializations.
7891 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7893 /* Set devmode and printer initialization info */
7894 status = save_driver_init( printer, 2, data, real_len );
7896 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7900 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7901 type, data, real_len );
7902 if ( W_ERROR_IS_OK(status) )
7903 status = mod_a_printer(*printer, 2);
7907 free_a_printer(&printer, 2);
7912 /****************************************************************************
7913 ****************************************************************************/
7915 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7917 POLICY_HND *handle = &q_u->handle;
7918 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7921 DEBUG(5,("_spoolss_resetprinter\n"));
7924 * All we do is to check to see if the handle and queue is valid.
7925 * This call really doesn't mean anything to us because we only
7926 * support RAW printing. --jerry
7930 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7934 if (!get_printer_snum(p,handle, &snum))
7938 /* blindly return success */
7943 /****************************************************************************
7944 ****************************************************************************/
7946 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7948 POLICY_HND *handle = &q_u->handle;
7949 UNISTR2 *value = &q_u->valuename;
7951 NT_PRINTER_INFO_LEVEL *printer = NULL;
7953 WERROR status = WERR_OK;
7954 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7957 DEBUG(5,("spoolss_deleteprinterdata\n"));
7960 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7964 if (!get_printer_snum(p, handle, &snum))
7967 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7968 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7969 return WERR_ACCESS_DENIED;
7972 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7973 if (!W_ERROR_IS_OK(status))
7976 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7978 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7980 free_a_printer(&printer, 2);
7985 /****************************************************************************
7986 ****************************************************************************/
7988 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7990 POLICY_HND *handle = &q_u->handle;
7991 FORM *form = &q_u->form;
7992 nt_forms_struct tmpForm;
7994 WERROR status = WERR_OK;
7995 NT_PRINTER_INFO_LEVEL *printer = NULL;
7998 nt_forms_struct *list=NULL;
7999 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8001 DEBUG(5,("spoolss_addform\n"));
8004 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8009 /* forms can be added on printer of on the print server handle */
8011 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8013 if (!get_printer_snum(p,handle, &snum))
8016 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8017 if (!W_ERROR_IS_OK(status))
8021 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8022 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8023 status = WERR_ACCESS_DENIED;
8027 /* can't add if builtin */
8029 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8030 status = WERR_ALREADY_EXISTS;
8034 count = get_ntforms(&list);
8036 if(!add_a_form(&list, form, &count)) {
8037 status = WERR_NOMEM;
8041 write_ntforms(&list, count);
8044 * ChangeID must always be set if this is a printer
8047 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8048 status = mod_a_printer(*printer, 2);
8052 free_a_printer(&printer, 2);
8058 /****************************************************************************
8059 ****************************************************************************/
8061 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8063 POLICY_HND *handle = &q_u->handle;
8064 UNISTR2 *form_name = &q_u->name;
8065 nt_forms_struct tmpForm;
8067 nt_forms_struct *list=NULL;
8068 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8070 WERROR status = WERR_OK;
8071 NT_PRINTER_INFO_LEVEL *printer = NULL;
8073 DEBUG(5,("spoolss_deleteform\n"));
8076 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8080 /* forms can be deleted on printer of on the print server handle */
8082 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8084 if (!get_printer_snum(p,handle, &snum))
8087 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8088 if (!W_ERROR_IS_OK(status))
8092 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8093 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8094 status = WERR_ACCESS_DENIED;
8098 /* can't delete if builtin */
8100 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8101 status = WERR_INVALID_PARAM;
8105 count = get_ntforms(&list);
8107 if ( !delete_a_form(&list, form_name, &count, &status ))
8111 * ChangeID must always be set if this is a printer
8114 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8115 status = mod_a_printer(*printer, 2);
8119 free_a_printer(&printer, 2);
8125 /****************************************************************************
8126 ****************************************************************************/
8128 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8130 POLICY_HND *handle = &q_u->handle;
8131 FORM *form = &q_u->form;
8132 nt_forms_struct tmpForm;
8134 WERROR status = WERR_OK;
8135 NT_PRINTER_INFO_LEVEL *printer = NULL;
8138 nt_forms_struct *list=NULL;
8139 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8141 DEBUG(5,("spoolss_setform\n"));
8144 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8148 /* forms can be modified on printer of on the print server handle */
8150 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8152 if (!get_printer_snum(p,handle, &snum))
8155 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8156 if (!W_ERROR_IS_OK(status))
8160 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8161 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8162 status = WERR_ACCESS_DENIED;
8166 /* can't set if builtin */
8167 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8168 status = WERR_INVALID_PARAM;
8172 count = get_ntforms(&list);
8173 update_a_form(&list, form, count);
8174 write_ntforms(&list, count);
8177 * ChangeID must always be set if this is a printer
8180 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8181 status = mod_a_printer(*printer, 2);
8186 free_a_printer(&printer, 2);
8192 /****************************************************************************
8193 enumprintprocessors level 1.
8194 ****************************************************************************/
8196 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8198 PRINTPROCESSOR_1 *info_1=NULL;
8200 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8205 init_unistr(&info_1->name, "winprint");
8207 *needed += spoolss_size_printprocessor_info_1(info_1);
8209 if (!alloc_buffer_size(buffer, *needed))
8210 return WERR_INSUFFICIENT_BUFFER;
8212 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8216 if (*needed > offered) {
8218 return WERR_INSUFFICIENT_BUFFER;
8224 /****************************************************************************
8225 ****************************************************************************/
8227 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8229 uint32 level = q_u->level;
8230 NEW_BUFFER *buffer = NULL;
8231 uint32 offered = q_u->offered;
8232 uint32 *needed = &r_u->needed;
8233 uint32 *returned = &r_u->returned;
8235 /* that's an [in out] buffer */
8236 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8237 buffer = r_u->buffer;
8239 DEBUG(5,("spoolss_enumprintprocessors\n"));
8242 * Enumerate the print processors ...
8244 * Just reply with "winprint", to keep NT happy
8245 * and I can use my nice printer checker.
8253 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8255 return WERR_UNKNOWN_LEVEL;
8259 /****************************************************************************
8260 enumprintprocdatatypes level 1.
8261 ****************************************************************************/
8263 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8265 PRINTPROCDATATYPE_1 *info_1=NULL;
8267 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8272 init_unistr(&info_1->name, "RAW");
8274 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8276 if (!alloc_buffer_size(buffer, *needed))
8277 return WERR_INSUFFICIENT_BUFFER;
8279 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8283 if (*needed > offered) {
8285 return WERR_INSUFFICIENT_BUFFER;
8291 /****************************************************************************
8292 ****************************************************************************/
8294 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8296 uint32 level = q_u->level;
8297 NEW_BUFFER *buffer = NULL;
8298 uint32 offered = q_u->offered;
8299 uint32 *needed = &r_u->needed;
8300 uint32 *returned = &r_u->returned;
8302 /* that's an [in out] buffer */
8303 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8304 buffer = r_u->buffer;
8306 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8313 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8315 return WERR_UNKNOWN_LEVEL;
8319 /****************************************************************************
8320 enumprintmonitors level 1.
8321 ****************************************************************************/
8323 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8325 PRINTMONITOR_1 *info_1=NULL;
8327 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8332 init_unistr(&info_1->name, "Local Port");
8334 *needed += spoolss_size_printmonitor_info_1(info_1);
8336 if (!alloc_buffer_size(buffer, *needed))
8337 return WERR_INSUFFICIENT_BUFFER;
8339 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8343 if (*needed > offered) {
8345 return WERR_INSUFFICIENT_BUFFER;
8351 /****************************************************************************
8352 enumprintmonitors level 2.
8353 ****************************************************************************/
8355 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8357 PRINTMONITOR_2 *info_2=NULL;
8359 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8364 init_unistr(&info_2->name, "Local Port");
8365 init_unistr(&info_2->environment, "Windows NT X86");
8366 init_unistr(&info_2->dll_name, "localmon.dll");
8368 *needed += spoolss_size_printmonitor_info_2(info_2);
8370 if (!alloc_buffer_size(buffer, *needed))
8371 return WERR_INSUFFICIENT_BUFFER;
8373 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8377 if (*needed > offered) {
8379 return WERR_INSUFFICIENT_BUFFER;
8385 /****************************************************************************
8386 ****************************************************************************/
8388 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8390 uint32 level = q_u->level;
8391 NEW_BUFFER *buffer = NULL;
8392 uint32 offered = q_u->offered;
8393 uint32 *needed = &r_u->needed;
8394 uint32 *returned = &r_u->returned;
8396 /* that's an [in out] buffer */
8397 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8398 buffer = r_u->buffer;
8400 DEBUG(5,("spoolss_enumprintmonitors\n"));
8403 * Enumerate the print monitors ...
8405 * Just reply with "Local Port", to keep NT happy
8406 * and I can use my nice printer checker.
8414 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8416 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8418 return WERR_UNKNOWN_LEVEL;
8422 /****************************************************************************
8423 ****************************************************************************/
8425 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8429 JOB_INFO_1 *info_1=NULL;
8431 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8433 if (info_1 == NULL) {
8437 for (i=0; i<count && found==False; i++) {
8438 if (queue[i].job==(int)jobid)
8444 /* NT treats not found as bad param... yet another bad choice */
8445 return WERR_INVALID_PARAM;
8448 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8450 *needed += spoolss_size_job_info_1(info_1);
8452 if (!alloc_buffer_size(buffer, *needed)) {
8454 return WERR_INSUFFICIENT_BUFFER;
8457 smb_io_job_info_1("", buffer, info_1, 0);
8461 if (*needed > offered)
8462 return WERR_INSUFFICIENT_BUFFER;
8467 /****************************************************************************
8468 ****************************************************************************/
8470 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8475 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8477 DEVICEMODE *devmode = NULL;
8478 NT_DEVICEMODE *nt_devmode = NULL;
8480 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8482 ZERO_STRUCTP(info_2);
8484 if (info_2 == NULL) {
8489 for ( i=0; i<count && found==False; i++ )
8491 if (queue[i].job == (int)jobid)
8497 /* NT treats not found as bad param... yet another bad
8499 ret = WERR_INVALID_PARAM;
8503 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8504 if (!W_ERROR_IS_OK(ret))
8508 * if the print job does not have a DEVMODE associated with it,
8509 * just use the one for the printer. A NULL devicemode is not
8510 * a failure condition
8513 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8514 devmode = construct_dev_mode(snum);
8516 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8517 ZERO_STRUCTP( devmode );
8518 convert_nt_devicemode( devmode, nt_devmode );
8522 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8524 *needed += spoolss_size_job_info_2(info_2);
8526 if (!alloc_buffer_size(buffer, *needed)) {
8527 ret = WERR_INSUFFICIENT_BUFFER;
8531 smb_io_job_info_2("", buffer, info_2, 0);
8533 if (*needed > offered) {
8534 ret = WERR_INSUFFICIENT_BUFFER;
8541 /* Cleanup allocated memory */
8543 free_job_info_2(info_2); /* Also frees devmode */
8545 free_a_printer(&ntprinter, 2);
8550 /****************************************************************************
8551 ****************************************************************************/
8553 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8555 POLICY_HND *handle = &q_u->handle;
8556 uint32 jobid = q_u->jobid;
8557 uint32 level = q_u->level;
8558 NEW_BUFFER *buffer = NULL;
8559 uint32 offered = q_u->offered;
8560 uint32 *needed = &r_u->needed;
8561 WERROR wstatus = WERR_OK;
8565 print_queue_struct *queue = NULL;
8566 print_status_struct prt_status;
8568 /* that's an [in out] buffer */
8569 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8570 buffer = r_u->buffer;
8572 DEBUG(5,("spoolss_getjob\n"));
8576 if (!get_printer_snum(p, handle, &snum))
8579 count = print_queue_status(snum, &queue, &prt_status);
8581 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8582 count, prt_status.status, prt_status.message));
8586 wstatus = getjob_level_1(queue, count, snum, jobid,
8587 buffer, offered, needed);
8590 wstatus = getjob_level_2(queue, count, snum, jobid,
8591 buffer, offered, needed);
8594 wstatus = WERR_UNKNOWN_LEVEL;
8602 /********************************************************************
8603 spoolss_getprinterdataex
8605 From MSDN documentation of GetPrinterDataEx: pass request
8606 to GetPrinterData if key is "PrinterDriverData".
8607 ********************************************************************/
8609 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8611 POLICY_HND *handle = &q_u->handle;
8612 uint32 in_size = q_u->size;
8613 uint32 *type = &r_u->type;
8614 uint32 *out_size = &r_u->size;
8615 uint8 **data = &r_u->data;
8616 uint32 *needed = &r_u->needed;
8617 fstring keyname, valuename;
8619 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8621 NT_PRINTER_INFO_LEVEL *printer = NULL;
8623 WERROR status = WERR_OK;
8625 DEBUG(4,("_spoolss_getprinterdataex\n"));
8627 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8628 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8630 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8631 keyname, valuename));
8633 /* in case of problem, return some default values */
8637 *out_size = in_size;
8640 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8641 status = WERR_BADFID;
8645 /* Is the handle to a printer or to the server? */
8647 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8648 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8649 status = WERR_INVALID_PARAM;
8653 if ( !get_printer_snum(p,handle, &snum) )
8656 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8657 if ( !W_ERROR_IS_OK(status) )
8660 /* check to see if the keyname is valid */
8661 if ( !strlen(keyname) ) {
8662 status = WERR_INVALID_PARAM;
8666 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8667 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8668 free_a_printer( &printer, 2 );
8669 status = WERR_BADFILE;
8673 /* When given a new keyname, we should just create it */
8675 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8677 if (*needed > *out_size)
8678 status = WERR_MORE_DATA;
8681 if ( !W_ERROR_IS_OK(status) )
8683 DEBUG(5, ("error: allocating %d\n", *out_size));
8685 /* reply this param doesn't exist */
8689 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8690 status = WERR_NOMEM;
8700 free_a_printer( &printer, 2 );
8705 /********************************************************************
8706 * spoolss_setprinterdataex
8707 ********************************************************************/
8709 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8711 POLICY_HND *handle = &q_u->handle;
8712 uint32 type = q_u->type;
8713 uint8 *data = q_u->data;
8714 uint32 real_len = q_u->real_len;
8716 NT_PRINTER_INFO_LEVEL *printer = NULL;
8718 WERROR status = WERR_OK;
8719 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8724 DEBUG(4,("_spoolss_setprinterdataex\n"));
8726 /* From MSDN documentation of SetPrinterDataEx: pass request to
8727 SetPrinterData if key is "PrinterDriverData" */
8730 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8734 if ( !get_printer_snum(p,handle, &snum) )
8738 * Access check : NT returns "access denied" if you make a
8739 * SetPrinterData call without the necessary privildge.
8740 * we were originally returning OK if nothing changed
8741 * which made Win2k issue **a lot** of SetPrinterData
8742 * when connecting to a printer --jerry
8745 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8747 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8748 return WERR_ACCESS_DENIED;
8751 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8752 if (!W_ERROR_IS_OK(status))
8755 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8756 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8758 /* check for OID in valuename */
8760 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8766 /* save the registry data */
8768 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8770 if ( W_ERROR_IS_OK(status) )
8772 /* save the OID if one was specified */
8774 fstrcat( keyname, "\\" );
8775 fstrcat( keyname, SPOOL_OID_KEY );
8778 * I'm not checking the status here on purpose. Don't know
8779 * if this is right, but I'm returning the status from the
8780 * previous set_printer_dataex() call. I have no idea if
8781 * this is right. --jerry
8784 set_printer_dataex( printer, keyname, valuename,
8785 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8788 status = mod_a_printer(*printer, 2);
8791 free_a_printer(&printer, 2);
8797 /********************************************************************
8798 * spoolss_deleteprinterdataex
8799 ********************************************************************/
8801 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8803 POLICY_HND *handle = &q_u->handle;
8804 UNISTR2 *value = &q_u->valuename;
8805 UNISTR2 *key = &q_u->keyname;
8807 NT_PRINTER_INFO_LEVEL *printer = NULL;
8809 WERROR status = WERR_OK;
8810 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8811 pstring valuename, keyname;
8813 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8816 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8820 if (!get_printer_snum(p, handle, &snum))
8823 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8824 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8825 return WERR_ACCESS_DENIED;
8828 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8829 if (!W_ERROR_IS_OK(status))
8832 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8833 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8835 status = delete_printer_dataex( printer, keyname, valuename );
8837 free_a_printer(&printer, 2);
8842 /********************************************************************
8843 * spoolss_enumprinterkey
8844 ********************************************************************/
8847 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8850 fstring *keynames = NULL;
8851 uint16 *enumkeys = NULL;
8854 POLICY_HND *handle = &q_u->handle;
8855 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8856 NT_PRINTER_DATA *data;
8857 NT_PRINTER_INFO_LEVEL *printer = NULL;
8859 WERROR status = WERR_BADFILE;
8862 DEBUG(4,("_spoolss_enumprinterkey\n"));
8865 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8869 if ( !get_printer_snum(p,handle, &snum) )
8872 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8873 if (!W_ERROR_IS_OK(status))
8876 /* get the list of subkey names */
8878 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8879 data = &printer->info_2->data;
8881 num_keys = get_printer_subkeys( data, key, &keynames );
8883 if ( num_keys == -1 ) {
8884 status = WERR_BADFILE;
8888 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8890 r_u->needed = printerkey_len*2;
8892 if ( q_u->size < r_u->needed ) {
8893 status = WERR_MORE_DATA;
8897 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8898 status = WERR_NOMEM;
8904 if ( q_u->size < r_u->needed )
8905 status = WERR_MORE_DATA;
8908 free_a_printer( &printer, 2 );
8909 SAFE_FREE( keynames );
8914 /********************************************************************
8915 * spoolss_deleteprinterkey
8916 ********************************************************************/
8918 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8920 POLICY_HND *handle = &q_u->handle;
8921 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8923 NT_PRINTER_INFO_LEVEL *printer = NULL;
8927 DEBUG(5,("spoolss_deleteprinterkey\n"));
8930 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8934 /* if keyname == NULL, return error */
8936 if ( !q_u->keyname.buffer )
8937 return WERR_INVALID_PARAM;
8939 if (!get_printer_snum(p, handle, &snum))
8942 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8943 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8944 return WERR_ACCESS_DENIED;
8947 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8948 if (!W_ERROR_IS_OK(status))
8951 /* delete the key and all subneys */
8953 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8955 status = delete_all_printer_data( printer->info_2, key );
8957 if ( W_ERROR_IS_OK(status) )
8958 status = mod_a_printer(*printer, 2);
8960 free_a_printer( &printer, 2 );
8966 /********************************************************************
8967 * spoolss_enumprinterdataex
8968 ********************************************************************/
8970 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8972 POLICY_HND *handle = &q_u->handle;
8973 uint32 in_size = q_u->size;
8976 NT_PRINTER_INFO_LEVEL *printer = NULL;
8977 PRINTER_ENUM_VALUES *enum_values = NULL;
8978 NT_PRINTER_DATA *p_data;
8980 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8985 REGISTRY_VALUE *val;
8990 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8993 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8998 * first check for a keyname of NULL or "". Win2k seems to send
8999 * this a lot and we should send back WERR_INVALID_PARAM
9000 * no need to spend time looking up the printer in this case.
9004 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9005 if ( !strlen(key) ) {
9006 result = WERR_INVALID_PARAM;
9010 /* get the printer off of disk */
9012 if (!get_printer_snum(p,handle, &snum))
9015 ZERO_STRUCT(printer);
9016 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9017 if (!W_ERROR_IS_OK(result))
9020 /* now look for a match on the key name */
9022 p_data = &printer->info_2->data;
9024 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9025 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9027 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9028 result = WERR_INVALID_PARAM;
9035 /* allocate the memory for the array of pointers -- if necessary */
9037 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9040 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9042 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
9043 num_entries*sizeof(PRINTER_ENUM_VALUES)));
9044 result = WERR_NOMEM;
9048 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9052 * loop through all params and build the array to pass
9053 * back to the client
9056 for ( i=0; i<num_entries; i++ )
9058 /* lookup the registry value */
9060 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9061 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9065 value_name = regval_name( val );
9066 init_unistr( &enum_values[i].valuename, value_name );
9067 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9068 enum_values[i].type = regval_type( val );
9070 data_len = regval_size( val );
9072 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9074 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9076 result = WERR_NOMEM;
9080 enum_values[i].data_len = data_len;
9082 /* keep track of the size of the array in bytes */
9084 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9087 /* housekeeping information in the reply */
9089 r_u->needed = needed;
9090 r_u->returned = num_entries;
9092 if (needed > in_size) {
9093 result = WERR_MORE_DATA;
9097 /* copy data into the reply */
9099 r_u->ctr.size = r_u->needed;
9100 r_u->ctr.size_of_array = r_u->returned;
9101 r_u->ctr.values = enum_values;
9107 free_a_printer(&printer, 2);
9112 /****************************************************************************
9113 ****************************************************************************/
9115 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9117 init_unistr(&info->name, name);
9120 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9121 UNISTR2 *environment,
9128 pstring short_archi;
9129 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9131 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9133 if (get_short_archi(short_archi, long_archi)==False)
9134 return WERR_INVALID_ENVIRONMENT;
9136 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9139 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9141 fill_printprocessordirectory_1(info, path);
9143 *needed += spoolss_size_printprocessordirectory_info_1(info);
9145 if (!alloc_buffer_size(buffer, *needed)) {
9147 return WERR_INSUFFICIENT_BUFFER;
9150 smb_io_printprocessordirectory_1("", buffer, info, 0);
9154 if (*needed > offered)
9155 return WERR_INSUFFICIENT_BUFFER;
9160 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9162 uint32 level = q_u->level;
9163 NEW_BUFFER *buffer = NULL;
9164 uint32 offered = q_u->offered;
9165 uint32 *needed = &r_u->needed;
9168 /* that's an [in out] buffer */
9169 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9170 buffer = r_u->buffer;
9172 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9178 result = getprintprocessordirectory_level_1
9179 (&q_u->name, &q_u->environment, buffer, offered, needed);
9182 result = WERR_UNKNOWN_LEVEL;
9190 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9191 SPOOL_R_REPLYOPENPRINTER *r_u)
9193 DEBUG(5,("_spoolss_replyopenprinter\n"));
9195 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9200 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9201 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9203 DEBUG(5,("_spoolss_replycloseprinter\n"));