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, type %d, field 0x%02x, flags 0x%04x\n",
1057 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, const char *remote_machine)
2512 ZERO_STRUCTP(the_cli);
2513 if(cli_initialise(the_cli) == NULL) {
2514 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2518 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2519 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2520 cli_shutdown(the_cli);
2524 if (ismyip(the_cli->dest_ip)) {
2525 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2526 cli_shutdown(the_cli);
2530 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2531 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2532 cli_shutdown(the_cli);
2536 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2537 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2539 cli_shutdown(the_cli);
2543 the_cli->protocol = PROTOCOL_NT1;
2545 if (!cli_negprot(the_cli)) {
2546 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2547 cli_shutdown(the_cli);
2551 if (the_cli->protocol != PROTOCOL_NT1) {
2552 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2553 cli_shutdown(the_cli);
2558 * Do an anonymous session setup.
2561 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2562 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2563 cli_shutdown(the_cli);
2567 if (!(the_cli->sec_mode & 1)) {
2568 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2569 cli_shutdown(the_cli);
2573 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2574 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2575 cli_shutdown(the_cli);
2580 * Ok - we have an anonymous connection to the IPC$ share.
2581 * Now start the NT Domain stuff :-).
2584 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2585 DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2586 cli_nt_session_close(the_cli);
2587 cli_ulogoff(the_cli);
2588 cli_shutdown(the_cli);
2595 /***************************************************************************
2596 Connect to the client.
2597 ****************************************************************************/
2599 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2604 * If it's the first connection, contact the client
2605 * and connect to the IPC$ share anonumously
2607 if (smb_connections==0) {
2608 fstring unix_printer;
2610 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2612 if(!spoolss_connect_to_client(¬ify_cli, unix_printer))
2615 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2616 /* Tell the connections db we're now interested in printer
2617 * notify messages. */
2618 register_message_flags( True, FLAG_MSG_PRINTING );
2622 * Tell the specific printing tdb we want messages for this printer
2623 * by registering our PID.
2626 if (!print_notify_register_pid(snum))
2627 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2631 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2634 if (!W_ERROR_IS_OK(result))
2635 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2636 dos_errstr(result)));
2638 return (W_ERROR_IS_OK(result));
2641 /********************************************************************
2643 * ReplyFindFirstPrinterChangeNotifyEx
2645 * before replying OK: status=0 a rpc call is made to the workstation
2646 * asking ReplyOpenPrinter
2648 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2649 * called from api_spoolss_rffpcnex
2650 ********************************************************************/
2652 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2654 POLICY_HND *handle = &q_u->handle;
2655 uint32 flags = q_u->flags;
2656 uint32 options = q_u->options;
2657 UNISTR2 *localmachine = &q_u->localmachine;
2658 uint32 printerlocal = q_u->printerlocal;
2660 SPOOL_NOTIFY_OPTION *option = q_u->option;
2662 /* store the notify value in the printer struct */
2664 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2667 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2671 Printer->notify.flags=flags;
2672 Printer->notify.options=options;
2673 Printer->notify.printerlocal=printerlocal;
2675 if (Printer->notify.option)
2676 free_spool_notify_option(&Printer->notify.option);
2678 Printer->notify.option=dup_spool_notify_option(option);
2680 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2681 sizeof(Printer->notify.localmachine)-1);
2683 /* Connect to the client machine and send a ReplyOpenPrinter */
2685 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2687 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2688 !get_printer_snum(p, handle, &snum) )
2691 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2692 Printer->notify.printerlocal, 1,
2693 &Printer->notify.client_hnd))
2694 return WERR_SERVER_UNAVAILABLE;
2696 Printer->notify.client_connected=True;
2701 /*******************************************************************
2702 * fill a notify_info_data with the servername
2703 ********************************************************************/
2705 void spoolss_notify_server_name(int snum,
2706 SPOOL_NOTIFY_INFO_DATA *data,
2707 print_queue_struct *queue,
2708 NT_PRINTER_INFO_LEVEL *printer,
2709 TALLOC_CTX *mem_ctx)
2711 pstring temp_name, temp;
2714 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2716 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2718 data->notify_data.data.length = len;
2719 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2721 if (!data->notify_data.data.string) {
2722 data->notify_data.data.length = 0;
2726 memcpy(data->notify_data.data.string, temp, len);
2729 /*******************************************************************
2730 * fill a notify_info_data with the printername (not including the servername).
2731 ********************************************************************/
2733 void spoolss_notify_printer_name(int snum,
2734 SPOOL_NOTIFY_INFO_DATA *data,
2735 print_queue_struct *queue,
2736 NT_PRINTER_INFO_LEVEL *printer,
2737 TALLOC_CTX *mem_ctx)
2742 /* the notify name should not contain the \\server\ part */
2743 char *p = strrchr(printer->info_2->printername, '\\');
2746 p = printer->info_2->printername;
2751 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2753 data->notify_data.data.length = len;
2754 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2756 if (!data->notify_data.data.string) {
2757 data->notify_data.data.length = 0;
2761 memcpy(data->notify_data.data.string, temp, len);
2764 /*******************************************************************
2765 * fill a notify_info_data with the servicename
2766 ********************************************************************/
2768 void spoolss_notify_share_name(int snum,
2769 SPOOL_NOTIFY_INFO_DATA *data,
2770 print_queue_struct *queue,
2771 NT_PRINTER_INFO_LEVEL *printer,
2772 TALLOC_CTX *mem_ctx)
2777 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2779 data->notify_data.data.length = len;
2780 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2782 if (!data->notify_data.data.string) {
2783 data->notify_data.data.length = 0;
2787 memcpy(data->notify_data.data.string, temp, len);
2790 /*******************************************************************
2791 * fill a notify_info_data with the port name
2792 ********************************************************************/
2794 void spoolss_notify_port_name(int snum,
2795 SPOOL_NOTIFY_INFO_DATA *data,
2796 print_queue_struct *queue,
2797 NT_PRINTER_INFO_LEVEL *printer,
2798 TALLOC_CTX *mem_ctx)
2803 /* even if it's strange, that's consistant in all the code */
2805 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2807 data->notify_data.data.length = len;
2808 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2810 if (!data->notify_data.data.string) {
2811 data->notify_data.data.length = 0;
2815 memcpy(data->notify_data.data.string, temp, len);
2818 /*******************************************************************
2819 * fill a notify_info_data with the printername
2820 * but it doesn't exist, have to see what to do
2821 ********************************************************************/
2823 void spoolss_notify_driver_name(int snum,
2824 SPOOL_NOTIFY_INFO_DATA *data,
2825 print_queue_struct *queue,
2826 NT_PRINTER_INFO_LEVEL *printer,
2827 TALLOC_CTX *mem_ctx)
2832 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2834 data->notify_data.data.length = len;
2835 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2837 if (!data->notify_data.data.string) {
2838 data->notify_data.data.length = 0;
2842 memcpy(data->notify_data.data.string, temp, len);
2845 /*******************************************************************
2846 * fill a notify_info_data with the comment
2847 ********************************************************************/
2849 void spoolss_notify_comment(int snum,
2850 SPOOL_NOTIFY_INFO_DATA *data,
2851 print_queue_struct *queue,
2852 NT_PRINTER_INFO_LEVEL *printer,
2853 TALLOC_CTX *mem_ctx)
2858 if (*printer->info_2->comment == '\0')
2859 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2861 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2863 data->notify_data.data.length = len;
2864 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2866 if (!data->notify_data.data.string) {
2867 data->notify_data.data.length = 0;
2871 memcpy(data->notify_data.data.string, temp, len);
2874 /*******************************************************************
2875 * fill a notify_info_data with the comment
2876 * location = "Room 1, floor 2, building 3"
2877 ********************************************************************/
2879 void spoolss_notify_location(int snum,
2880 SPOOL_NOTIFY_INFO_DATA *data,
2881 print_queue_struct *queue,
2882 NT_PRINTER_INFO_LEVEL *printer,
2883 TALLOC_CTX *mem_ctx)
2888 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2890 data->notify_data.data.length = len;
2891 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2893 if (!data->notify_data.data.string) {
2894 data->notify_data.data.length = 0;
2898 memcpy(data->notify_data.data.string, temp, len);
2901 /*******************************************************************
2902 * fill a notify_info_data with the device mode
2903 * jfm:xxxx don't to it for know but that's a real problem !!!
2904 ********************************************************************/
2906 static void spoolss_notify_devmode(int snum,
2907 SPOOL_NOTIFY_INFO_DATA *data,
2908 print_queue_struct *queue,
2909 NT_PRINTER_INFO_LEVEL *printer,
2910 TALLOC_CTX *mem_ctx)
2914 /*******************************************************************
2915 * fill a notify_info_data with the separator file name
2916 ********************************************************************/
2918 void spoolss_notify_sepfile(int snum,
2919 SPOOL_NOTIFY_INFO_DATA *data,
2920 print_queue_struct *queue,
2921 NT_PRINTER_INFO_LEVEL *printer,
2922 TALLOC_CTX *mem_ctx)
2927 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2929 data->notify_data.data.length = len;
2930 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2932 if (!data->notify_data.data.string) {
2933 data->notify_data.data.length = 0;
2937 memcpy(data->notify_data.data.string, temp, len);
2940 /*******************************************************************
2941 * fill a notify_info_data with the print processor
2942 * jfm:xxxx return always winprint to indicate we don't do anything to it
2943 ********************************************************************/
2945 void spoolss_notify_print_processor(int snum,
2946 SPOOL_NOTIFY_INFO_DATA *data,
2947 print_queue_struct *queue,
2948 NT_PRINTER_INFO_LEVEL *printer,
2949 TALLOC_CTX *mem_ctx)
2954 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2956 data->notify_data.data.length = len;
2957 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2959 if (!data->notify_data.data.string) {
2960 data->notify_data.data.length = 0;
2964 memcpy(data->notify_data.data.string, temp, len);
2967 /*******************************************************************
2968 * fill a notify_info_data with the print processor options
2969 * jfm:xxxx send an empty string
2970 ********************************************************************/
2972 void spoolss_notify_parameters(int snum,
2973 SPOOL_NOTIFY_INFO_DATA *data,
2974 print_queue_struct *queue,
2975 NT_PRINTER_INFO_LEVEL *printer,
2976 TALLOC_CTX *mem_ctx)
2981 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2983 data->notify_data.data.length = len;
2984 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2986 if (!data->notify_data.data.string) {
2987 data->notify_data.data.length = 0;
2991 memcpy(data->notify_data.data.string, temp, len);
2994 /*******************************************************************
2995 * fill a notify_info_data with the data type
2996 * jfm:xxxx always send RAW as data type
2997 ********************************************************************/
2999 void spoolss_notify_datatype(int snum,
3000 SPOOL_NOTIFY_INFO_DATA *data,
3001 print_queue_struct *queue,
3002 NT_PRINTER_INFO_LEVEL *printer,
3003 TALLOC_CTX *mem_ctx)
3008 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3010 data->notify_data.data.length = len;
3011 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3013 if (!data->notify_data.data.string) {
3014 data->notify_data.data.length = 0;
3018 memcpy(data->notify_data.data.string, temp, len);
3021 /*******************************************************************
3022 * fill a notify_info_data with the security descriptor
3023 * jfm:xxxx send an null pointer to say no security desc
3024 * have to implement security before !
3025 ********************************************************************/
3027 static void spoolss_notify_security_desc(int snum,
3028 SPOOL_NOTIFY_INFO_DATA *data,
3029 print_queue_struct *queue,
3030 NT_PRINTER_INFO_LEVEL *printer,
3031 TALLOC_CTX *mem_ctx)
3033 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3034 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3037 /*******************************************************************
3038 * fill a notify_info_data with the attributes
3039 * jfm:xxxx a samba printer is always shared
3040 ********************************************************************/
3042 void spoolss_notify_attributes(int snum,
3043 SPOOL_NOTIFY_INFO_DATA *data,
3044 print_queue_struct *queue,
3045 NT_PRINTER_INFO_LEVEL *printer,
3046 TALLOC_CTX *mem_ctx)
3048 data->notify_data.value[0] = printer->info_2->attributes;
3049 data->notify_data.value[1] = 0;
3052 /*******************************************************************
3053 * fill a notify_info_data with the priority
3054 ********************************************************************/
3056 static void spoolss_notify_priority(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->priority;
3063 data->notify_data.value[1] = 0;
3066 /*******************************************************************
3067 * fill a notify_info_data with the default priority
3068 ********************************************************************/
3070 static void spoolss_notify_default_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->default_priority;
3077 data->notify_data.value[1] = 0;
3080 /*******************************************************************
3081 * fill a notify_info_data with the start time
3082 ********************************************************************/
3084 static void spoolss_notify_start_time(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->starttime;
3091 data->notify_data.value[1] = 0;
3094 /*******************************************************************
3095 * fill a notify_info_data with the until time
3096 ********************************************************************/
3098 static void spoolss_notify_until_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->untiltime;
3105 data->notify_data.value[1] = 0;
3108 /*******************************************************************
3109 * fill a notify_info_data with the status
3110 ********************************************************************/
3112 static void spoolss_notify_status(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 print_status_struct status;
3120 print_queue_length(snum, &status);
3121 data->notify_data.value[0]=(uint32) status.status;
3122 data->notify_data.value[1] = 0;
3125 /*******************************************************************
3126 * fill a notify_info_data with the number of jobs queued
3127 ********************************************************************/
3129 void spoolss_notify_cjobs(int snum,
3130 SPOOL_NOTIFY_INFO_DATA *data,
3131 print_queue_struct *queue,
3132 NT_PRINTER_INFO_LEVEL *printer,
3133 TALLOC_CTX *mem_ctx)
3135 data->notify_data.value[0] = print_queue_length(snum, NULL);
3136 data->notify_data.value[1] = 0;
3139 /*******************************************************************
3140 * fill a notify_info_data with the average ppm
3141 ********************************************************************/
3143 static void spoolss_notify_average_ppm(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 /* always respond 8 pages per minutes */
3150 /* a little hard ! */
3151 data->notify_data.value[0] = printer->info_2->averageppm;
3152 data->notify_data.value[1] = 0;
3155 /*******************************************************************
3156 * fill a notify_info_data with username
3157 ********************************************************************/
3159 static void spoolss_notify_username(int snum,
3160 SPOOL_NOTIFY_INFO_DATA *data,
3161 print_queue_struct *queue,
3162 NT_PRINTER_INFO_LEVEL *printer,
3163 TALLOC_CTX *mem_ctx)
3168 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3170 data->notify_data.data.length = len;
3171 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3173 if (!data->notify_data.data.string) {
3174 data->notify_data.data.length = 0;
3178 memcpy(data->notify_data.data.string, temp, len);
3181 /*******************************************************************
3182 * fill a notify_info_data with job status
3183 ********************************************************************/
3185 static void spoolss_notify_job_status(int snum,
3186 SPOOL_NOTIFY_INFO_DATA *data,
3187 print_queue_struct *queue,
3188 NT_PRINTER_INFO_LEVEL *printer,
3189 TALLOC_CTX *mem_ctx)
3191 data->notify_data.value[0]=nt_printj_status(queue->status);
3192 data->notify_data.value[1] = 0;
3195 /*******************************************************************
3196 * fill a notify_info_data with job name
3197 ********************************************************************/
3199 static void spoolss_notify_job_name(int snum,
3200 SPOOL_NOTIFY_INFO_DATA *data,
3201 print_queue_struct *queue,
3202 NT_PRINTER_INFO_LEVEL *printer,
3203 TALLOC_CTX *mem_ctx)
3208 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3210 data->notify_data.data.length = len;
3211 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3213 if (!data->notify_data.data.string) {
3214 data->notify_data.data.length = 0;
3218 memcpy(data->notify_data.data.string, temp, len);
3221 /*******************************************************************
3222 * fill a notify_info_data with job status
3223 ********************************************************************/
3225 static void spoolss_notify_job_status_string(int snum,
3226 SPOOL_NOTIFY_INFO_DATA *data,
3227 print_queue_struct *queue,
3228 NT_PRINTER_INFO_LEVEL *printer,
3229 TALLOC_CTX *mem_ctx)
3232 * Now we're returning job status codes we just return a "" here. JRA.
3239 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3242 switch (queue->status) {
3247 p = ""; /* NT provides the paused string */
3256 #endif /* NO LONGER NEEDED. */
3258 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3260 data->notify_data.data.length = len;
3261 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3263 if (!data->notify_data.data.string) {
3264 data->notify_data.data.length = 0;
3268 memcpy(data->notify_data.data.string, temp, len);
3271 /*******************************************************************
3272 * fill a notify_info_data with job time
3273 ********************************************************************/
3275 static void spoolss_notify_job_time(int snum,
3276 SPOOL_NOTIFY_INFO_DATA *data,
3277 print_queue_struct *queue,
3278 NT_PRINTER_INFO_LEVEL *printer,
3279 TALLOC_CTX *mem_ctx)
3281 data->notify_data.value[0]=0x0;
3282 data->notify_data.value[1]=0;
3285 /*******************************************************************
3286 * fill a notify_info_data with job size
3287 ********************************************************************/
3289 static void spoolss_notify_job_size(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]=queue->size;
3296 data->notify_data.value[1]=0;
3299 /*******************************************************************
3300 * fill a notify_info_data with page info
3301 ********************************************************************/
3302 static void spoolss_notify_total_pages(int snum,
3303 SPOOL_NOTIFY_INFO_DATA *data,
3304 print_queue_struct *queue,
3305 NT_PRINTER_INFO_LEVEL *printer,
3306 TALLOC_CTX *mem_ctx)
3308 data->notify_data.value[0]=queue->page_count;
3309 data->notify_data.value[1]=0;
3312 /*******************************************************************
3313 * fill a notify_info_data with pages printed info.
3314 ********************************************************************/
3315 static void spoolss_notify_pages_printed(int snum,
3316 SPOOL_NOTIFY_INFO_DATA *data,
3317 print_queue_struct *queue,
3318 NT_PRINTER_INFO_LEVEL *printer,
3319 TALLOC_CTX *mem_ctx)
3321 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3322 data->notify_data.value[1]=0;
3325 /*******************************************************************
3326 Fill a notify_info_data with job position.
3327 ********************************************************************/
3329 static void spoolss_notify_job_position(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]=queue->job;
3336 data->notify_data.value[1]=0;
3339 /*******************************************************************
3340 Fill a notify_info_data with submitted time.
3341 ********************************************************************/
3343 static void spoolss_notify_submitted_time(int snum,
3344 SPOOL_NOTIFY_INFO_DATA *data,
3345 print_queue_struct *queue,
3346 NT_PRINTER_INFO_LEVEL *printer,
3347 TALLOC_CTX *mem_ctx)
3354 t=gmtime(&queue->time);
3356 len = sizeof(SYSTEMTIME);
3358 data->notify_data.data.length = len;
3359 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3361 if (!data->notify_data.data.string) {
3362 data->notify_data.data.length = 0;
3366 make_systemtime(&st, t);
3369 * Systemtime must be linearized as a set of UINT16's.
3370 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3373 p = (char *)data->notify_data.data.string;
3374 SSVAL(p, 0, st.year);
3375 SSVAL(p, 2, st.month);
3376 SSVAL(p, 4, st.dayofweek);
3377 SSVAL(p, 6, st.day);
3378 SSVAL(p, 8, st.hour);
3379 SSVAL(p, 10, st.minute);
3380 SSVAL(p, 12, st.second);
3381 SSVAL(p, 14, st.milliseconds);
3384 struct s_notify_info_data_table
3390 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3391 print_queue_struct *queue,
3392 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3395 /* A table describing the various print notification constants and
3396 whether the notification data is a pointer to a variable sized
3397 buffer, a one value uint32 or a two value uint32. */
3399 static const struct s_notify_info_data_table notify_info_data_table[] =
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3445 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3446 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3447 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3448 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3449 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3452 /*******************************************************************
3453 Return the size of info_data structure.
3454 ********************************************************************/
3456 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3460 for (i = 0; i < sizeof(notify_info_data_table); i++)
3462 if ( (notify_info_data_table[i].type == type)
3463 && (notify_info_data_table[i].field == field) )
3465 switch(notify_info_data_table[i].size)
3467 case NOTIFY_ONE_VALUE:
3468 case NOTIFY_TWO_VALUE:
3473 /* The only pointer notify data I have seen on
3474 the wire is the submitted time and this has
3475 the notify size set to 4. -tpot */
3477 case NOTIFY_POINTER:
3480 case NOTIFY_SECDESC:
3486 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3491 /*******************************************************************
3492 Return the type of notify_info_data.
3493 ********************************************************************/
3495 static int type_of_notify_info_data(uint16 type, uint16 field)
3499 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3500 if (notify_info_data_table[i].type == type &&
3501 notify_info_data_table[i].field == field)
3502 return notify_info_data_table[i].size;
3508 /****************************************************************************
3509 ****************************************************************************/
3511 static int search_notify(uint16 type, uint16 field, int *value)
3515 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3516 if (notify_info_data_table[i].type == type &&
3517 notify_info_data_table[i].field == field &&
3518 notify_info_data_table[i].fn != NULL) {
3527 /****************************************************************************
3528 ****************************************************************************/
3530 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3532 info_data->type = type;
3533 info_data->field = field;
3534 info_data->reserved = 0;
3536 info_data->size = size_of_notify_info_data(type, field);
3537 info_data->enc_type = type_of_notify_info_data(type, field);
3544 /*******************************************************************
3546 * fill a notify_info struct with info asked
3548 ********************************************************************/
3550 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3551 snum, SPOOL_NOTIFY_OPTION_TYPE
3552 *option_type, uint32 id,
3553 TALLOC_CTX *mem_ctx)
3559 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3560 NT_PRINTER_INFO_LEVEL *printer = NULL;
3561 print_queue_struct *queue=NULL;
3563 type=option_type->type;
3565 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3566 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3567 option_type->count, lp_servicename(snum)));
3569 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3572 for(field_num=0; field_num<option_type->count; field_num++) {
3573 field = option_type->fields[field_num];
3575 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3577 if (!search_notify(type, field, &j) )
3580 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3581 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3586 current_data = &info->data[info->count];
3588 construct_info_data(current_data, type, field, id);
3590 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3591 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3593 notify_info_data_table[j].fn(snum, current_data, queue,
3599 free_a_printer(&printer, 2);
3603 /*******************************************************************
3605 * fill a notify_info struct with info asked
3607 ********************************************************************/
3609 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3610 SPOOL_NOTIFY_INFO *info,
3611 NT_PRINTER_INFO_LEVEL *printer,
3612 int snum, SPOOL_NOTIFY_OPTION_TYPE
3613 *option_type, uint32 id,
3614 TALLOC_CTX *mem_ctx)
3620 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3622 DEBUG(4,("construct_notify_jobs_info\n"));
3624 type = option_type->type;
3626 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3627 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3628 option_type->count));
3630 for(field_num=0; field_num<option_type->count; field_num++) {
3631 field = option_type->fields[field_num];
3633 if (!search_notify(type, field, &j) )
3636 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3637 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3640 else info->data = tid;
3642 current_data=&(info->data[info->count]);
3644 construct_info_data(current_data, type, field, id);
3645 notify_info_data_table[j].fn(snum, current_data, queue,
3654 * JFM: The enumeration is not that simple, it's even non obvious.
3656 * let's take an example: I want to monitor the PRINTER SERVER for
3657 * the printer's name and the number of jobs currently queued.
3658 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3659 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3661 * I have 3 printers on the back of my server.
3663 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3666 * 1 printer 1 name 1
3667 * 2 printer 1 cjob 1
3668 * 3 printer 2 name 2
3669 * 4 printer 2 cjob 2
3670 * 5 printer 3 name 3
3671 * 6 printer 3 name 3
3673 * that's the print server case, the printer case is even worse.
3676 /*******************************************************************
3678 * enumerate all printers on the printserver
3679 * fill a notify_info struct with info asked
3681 ********************************************************************/
3683 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3684 SPOOL_NOTIFY_INFO *info,
3685 TALLOC_CTX *mem_ctx)
3688 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3689 int n_services=lp_numservices();
3692 SPOOL_NOTIFY_OPTION *option;
3693 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3695 DEBUG(4,("printserver_notify_info\n"));
3700 option=Printer->notify.option;
3706 for (i=0; i<option->count; i++) {
3707 option_type=&(option->ctr.type[i]);
3709 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3712 for (snum=0; snum<n_services; snum++)
3714 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3715 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3721 * Debugging information, don't delete.
3724 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3725 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3726 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3728 for (i=0; i<info->count; i++) {
3729 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3730 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3731 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3738 /*******************************************************************
3740 * fill a notify_info struct with info asked
3742 ********************************************************************/
3744 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3745 TALLOC_CTX *mem_ctx)
3748 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3751 SPOOL_NOTIFY_OPTION *option;
3752 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3754 print_queue_struct *queue=NULL;
3755 print_status_struct status;
3757 DEBUG(4,("printer_notify_info\n"));
3762 option=Printer->notify.option;
3768 get_printer_snum(p, hnd, &snum);
3770 for (i=0; i<option->count; i++) {
3771 option_type=&option->ctr.type[i];
3773 switch ( option_type->type ) {
3774 case PRINTER_NOTIFY_TYPE:
3775 if(construct_notify_printer_info(Printer, info, snum,
3781 case JOB_NOTIFY_TYPE: {
3782 NT_PRINTER_INFO_LEVEL *printer = NULL;
3784 count = print_queue_status(snum, &queue, &status);
3786 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3789 for (j=0; j<count; j++) {
3790 construct_notify_jobs_info(&queue[j], info,
3797 free_a_printer(&printer, 2);
3807 * Debugging information, don't delete.
3810 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3811 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3812 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3814 for (i=0; i<info->count; i++) {
3815 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3816 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3817 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3823 /********************************************************************
3825 ********************************************************************/
3827 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3829 POLICY_HND *handle = &q_u->handle;
3830 SPOOL_NOTIFY_INFO *info = &r_u->info;
3832 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3833 WERROR result = WERR_BADFID;
3835 /* we always have a NOTIFY_INFO struct */
3839 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3840 OUR_HANDLE(handle)));
3844 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3847 * We are now using the change value, and
3848 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3849 * I don't have a global notification system, I'm sending back all the
3850 * informations even when _NOTHING_ has changed.
3853 /* We need to keep track of the change value to send back in
3854 RRPCN replies otherwise our updates are ignored. */
3856 Printer->notify.fnpcn = True;
3858 if (Printer->notify.client_connected) {
3859 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3860 Printer->notify.change = q_u->change;
3863 /* just ignore the SPOOL_NOTIFY_OPTION */
3865 switch (Printer->printer_type) {
3866 case PRINTER_HANDLE_IS_PRINTSERVER:
3867 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3870 case PRINTER_HANDLE_IS_PRINTER:
3871 result = printer_notify_info(p, handle, info, p->mem_ctx);
3875 Printer->notify.fnpcn = False;
3881 /********************************************************************
3882 * construct_printer_info_0
3883 * fill a printer_info_0 struct
3884 ********************************************************************/
3886 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3890 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3891 counter_printer_0 *session_counter;
3892 uint32 global_counter;
3895 print_status_struct status;
3897 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3900 count = print_queue_length(snum, &status);
3902 /* check if we already have a counter for this printer */
3903 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3905 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3906 if (session_counter->snum == snum)
3910 /* it's the first time, add it to the list */
3911 if (session_counter==NULL) {
3912 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3913 free_a_printer(&ntprinter, 2);
3916 ZERO_STRUCTP(session_counter);
3917 session_counter->snum=snum;
3918 session_counter->counter=0;
3919 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3923 session_counter->counter++;
3926 * the global_counter should be stored in a TDB as it's common to all the clients
3927 * and should be zeroed on samba startup
3929 global_counter=session_counter->counter;
3931 pstrcpy(chaine,ntprinter->info_2->printername);
3933 init_unistr(&printer->printername, chaine);
3935 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3936 init_unistr(&printer->servername, chaine);
3938 printer->cjobs = count;
3939 printer->total_jobs = 0;
3940 printer->total_bytes = 0;
3942 setuptime = (time_t)ntprinter->info_2->setuptime;
3943 t=gmtime(&setuptime);
3945 printer->year = t->tm_year+1900;
3946 printer->month = t->tm_mon+1;
3947 printer->dayofweek = t->tm_wday;
3948 printer->day = t->tm_mday;
3949 printer->hour = t->tm_hour;
3950 printer->minute = t->tm_min;
3951 printer->second = t->tm_sec;
3952 printer->milliseconds = 0;
3954 printer->global_counter = global_counter;
3955 printer->total_pages = 0;
3957 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3958 printer->major_version = 0x0005; /* NT 5 */
3959 printer->build_version = 0x0893; /* build 2195 */
3961 printer->unknown7 = 0x1;
3962 printer->unknown8 = 0x0;
3963 printer->unknown9 = 0x0;
3964 printer->session_counter = session_counter->counter;
3965 printer->unknown11 = 0x0;
3966 printer->printer_errors = 0x0; /* number of print failure */
3967 printer->unknown13 = 0x0;
3968 printer->unknown14 = 0x1;
3969 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3970 printer->unknown16 = 0x0;
3971 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3972 printer->unknown18 = 0x0;
3973 printer->status = nt_printq_status(status.status);
3974 printer->unknown20 = 0x0;
3975 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3976 printer->unknown22 = 0x0;
3977 printer->unknown23 = 0x6; /* 6 ???*/
3978 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3979 printer->unknown25 = 0;
3980 printer->unknown26 = 0;
3981 printer->unknown27 = 0;
3982 printer->unknown28 = 0;
3983 printer->unknown29 = 0;
3985 free_a_printer(&ntprinter,2);
3989 /********************************************************************
3990 * construct_printer_info_1
3991 * fill a printer_info_1 struct
3992 ********************************************************************/
3993 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3997 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3999 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4002 printer->flags=flags;
4004 if (*ntprinter->info_2->comment == '\0') {
4005 init_unistr(&printer->comment, lp_comment(snum));
4006 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4007 ntprinter->info_2->drivername, lp_comment(snum));
4010 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4011 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4012 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4015 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4017 init_unistr(&printer->description, chaine);
4018 init_unistr(&printer->name, chaine2);
4020 free_a_printer(&ntprinter,2);
4025 /****************************************************************************
4026 Free a DEVMODE struct.
4027 ****************************************************************************/
4029 static void free_dev_mode(DEVICEMODE *dev)
4034 SAFE_FREE(dev->private);
4039 /****************************************************************************
4040 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4041 should be valid upon entry
4042 ****************************************************************************/
4044 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4046 if ( !devmode || !ntdevmode )
4049 init_unistr(&devmode->devicename, ntdevmode->devicename);
4051 init_unistr(&devmode->formname, ntdevmode->formname);
4053 devmode->specversion = ntdevmode->specversion;
4054 devmode->driverversion = ntdevmode->driverversion;
4055 devmode->size = ntdevmode->size;
4056 devmode->driverextra = ntdevmode->driverextra;
4057 devmode->fields = ntdevmode->fields;
4059 devmode->orientation = ntdevmode->orientation;
4060 devmode->papersize = ntdevmode->papersize;
4061 devmode->paperlength = ntdevmode->paperlength;
4062 devmode->paperwidth = ntdevmode->paperwidth;
4063 devmode->scale = ntdevmode->scale;
4064 devmode->copies = ntdevmode->copies;
4065 devmode->defaultsource = ntdevmode->defaultsource;
4066 devmode->printquality = ntdevmode->printquality;
4067 devmode->color = ntdevmode->color;
4068 devmode->duplex = ntdevmode->duplex;
4069 devmode->yresolution = ntdevmode->yresolution;
4070 devmode->ttoption = ntdevmode->ttoption;
4071 devmode->collate = ntdevmode->collate;
4072 devmode->icmmethod = ntdevmode->icmmethod;
4073 devmode->icmintent = ntdevmode->icmintent;
4074 devmode->mediatype = ntdevmode->mediatype;
4075 devmode->dithertype = ntdevmode->dithertype;
4077 if (ntdevmode->private != NULL) {
4078 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4085 /****************************************************************************
4086 Create a DEVMODE struct. Returns malloced memory.
4087 ****************************************************************************/
4089 DEVICEMODE *construct_dev_mode(int snum)
4091 NT_PRINTER_INFO_LEVEL *printer = NULL;
4092 DEVICEMODE *devmode = NULL;
4094 DEBUG(7,("construct_dev_mode\n"));
4096 DEBUGADD(8,("getting printer characteristics\n"));
4098 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4101 if ( !printer->info_2->devmode ) {
4102 DEBUG(5, ("BONG! There was no device mode!\n"));
4106 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4107 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4111 ZERO_STRUCTP(devmode);
4113 DEBUGADD(8,("loading DEVICEMODE\n"));
4115 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4116 free_dev_mode( devmode );
4121 free_a_printer(&printer,2);
4126 /********************************************************************
4127 * construct_printer_info_2
4128 * fill a printer_info_2 struct
4129 ********************************************************************/
4131 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4134 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4136 print_status_struct status;
4138 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4141 count = print_queue_length(snum, &status);
4143 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4144 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4145 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4146 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4147 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4149 if (*ntprinter->info_2->comment == '\0')
4150 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4152 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4154 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4155 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4156 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4157 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4158 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4160 printer->attributes = ntprinter->info_2->attributes;
4162 printer->priority = ntprinter->info_2->priority; /* priority */
4163 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4164 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4165 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4166 printer->status = nt_printq_status(status.status); /* status */
4167 printer->cjobs = count; /* jobs */
4168 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4170 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4171 DEBUG(8, ("Returning NULL Devicemode!\n"));
4174 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4175 /* steal the printer info sec_desc structure. [badly done]. */
4176 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4177 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4178 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4179 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4182 printer->secdesc = NULL;
4185 free_a_printer(&ntprinter, 2);
4189 /********************************************************************
4190 * construct_printer_info_3
4191 * fill a printer_info_3 struct
4192 ********************************************************************/
4194 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4196 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4197 PRINTER_INFO_3 *printer = NULL;
4199 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4203 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4204 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4208 ZERO_STRUCTP(printer);
4210 printer->flags = 4; /* These are the components of the SD we are returning. */
4211 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4212 /* steal the printer info sec_desc structure. [badly done]. */
4213 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4217 * Set the flags for the components we are returning.
4220 if (printer->secdesc->owner_sid)
4221 printer->flags |= OWNER_SECURITY_INFORMATION;
4223 if (printer->secdesc->grp_sid)
4224 printer->flags |= GROUP_SECURITY_INFORMATION;
4226 if (printer->secdesc->dacl)
4227 printer->flags |= DACL_SECURITY_INFORMATION;
4229 if (printer->secdesc->sacl)
4230 printer->flags |= SACL_SECURITY_INFORMATION;
4233 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4234 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4235 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4238 free_a_printer(&ntprinter, 2);
4240 *pp_printer = printer;
4244 /********************************************************************
4245 * construct_printer_info_4
4246 * fill a printer_info_4 struct
4247 ********************************************************************/
4249 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4251 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4253 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4256 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4257 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4258 printer->attributes = ntprinter->info_2->attributes;
4260 free_a_printer(&ntprinter, 2);
4264 /********************************************************************
4265 * construct_printer_info_5
4266 * fill a printer_info_5 struct
4267 ********************************************************************/
4269 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4271 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4273 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4276 init_unistr(&printer->printername, ntprinter->info_2->printername);
4277 init_unistr(&printer->portname, ntprinter->info_2->portname);
4278 printer->attributes = ntprinter->info_2->attributes;
4280 /* these two are not used by NT+ according to MSDN */
4282 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4283 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4285 free_a_printer(&ntprinter, 2);
4290 /********************************************************************
4291 * construct_printer_info_7
4292 * fill a printer_info_7 struct
4293 ********************************************************************/
4295 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4297 char *guid_str = NULL;
4300 if (is_printer_published(print_hnd, snum, &guid)) {
4301 asprintf(&guid_str, "{%s}", uuid_string_static(guid));
4303 init_unistr(&printer->guid, guid_str);
4304 printer->action = SPOOL_DS_PUBLISH;
4306 init_unistr(&printer->guid, "");
4307 printer->action = SPOOL_DS_UNPUBLISH;
4313 /********************************************************************
4314 Spoolss_enumprinters.
4315 ********************************************************************/
4317 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4321 int n_services=lp_numservices();
4322 PRINTER_INFO_1 *tp, *printers=NULL;
4323 PRINTER_INFO_1 current_prt;
4325 DEBUG(4,("enum_all_printers_info_1\n"));
4327 for (snum=0; snum<n_services; snum++) {
4328 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4329 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4331 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4332 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4333 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4334 SAFE_FREE(printers);
4339 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4341 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4347 /* check the required size. */
4348 for (i=0; i<*returned; i++)
4349 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4351 if (!alloc_buffer_size(buffer, *needed))
4352 return WERR_INSUFFICIENT_BUFFER;
4354 /* fill the buffer with the structures */
4355 for (i=0; i<*returned; i++)
4356 smb_io_printer_info_1("", buffer, &printers[i], 0);
4359 SAFE_FREE(printers);
4361 if (*needed > offered) {
4363 return WERR_INSUFFICIENT_BUFFER;
4369 /********************************************************************
4370 enum_all_printers_info_1_local.
4371 *********************************************************************/
4373 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4375 DEBUG(4,("enum_all_printers_info_1_local\n"));
4377 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4380 /********************************************************************
4381 enum_all_printers_info_1_name.
4382 *********************************************************************/
4384 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4388 DEBUG(4,("enum_all_printers_info_1_name\n"));
4390 if ((name[0] == '\\') && (name[1] == '\\'))
4393 if (is_myname_or_ipaddr(s)) {
4394 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4397 return WERR_INVALID_NAME;
4400 /********************************************************************
4401 enum_all_printers_info_1_remote.
4402 *********************************************************************/
4404 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4406 PRINTER_INFO_1 *printer;
4407 fstring printername;
4410 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4412 /* JFM: currently it's more a place holder than anything else.
4413 * In the spooler world there is a notion of server registration.
4414 * the print servers are registring (sp ?) on the PDC (in the same domain)
4416 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4419 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4424 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4425 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4426 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4428 init_unistr(&printer->description, desc);
4429 init_unistr(&printer->name, printername);
4430 init_unistr(&printer->comment, comment);
4431 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4433 /* check the required size. */
4434 *needed += spoolss_size_printer_info_1(printer);
4436 if (!alloc_buffer_size(buffer, *needed)) {
4438 return WERR_INSUFFICIENT_BUFFER;
4441 /* fill the buffer with the structures */
4442 smb_io_printer_info_1("", buffer, printer, 0);
4447 if (*needed > offered) {
4449 return WERR_INSUFFICIENT_BUFFER;
4455 /********************************************************************
4456 enum_all_printers_info_1_network.
4457 *********************************************************************/
4459 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4463 DEBUG(4,("enum_all_printers_info_1_network\n"));
4465 /* If we respond to a enum_printers level 1 on our name with flags
4466 set to PRINTER_ENUM_REMOTE with a list of printers then these
4467 printers incorrectly appear in the APW browse list.
4468 Specifically the printers for the server appear at the workgroup
4469 level where all the other servers in the domain are
4470 listed. Windows responds to this call with a
4471 WERR_CAN_NOT_COMPLETE so we should do the same. */
4473 if (name[0] == '\\' && name[1] == '\\')
4476 if (is_myname_or_ipaddr(s))
4477 return WERR_CAN_NOT_COMPLETE;
4479 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4482 /********************************************************************
4483 * api_spoolss_enumprinters
4485 * called from api_spoolss_enumprinters (see this to understand)
4486 ********************************************************************/
4488 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4492 int n_services=lp_numservices();
4493 PRINTER_INFO_2 *tp, *printers=NULL;
4494 PRINTER_INFO_2 current_prt;
4496 for (snum=0; snum<n_services; snum++) {
4497 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4498 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4500 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4501 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4502 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4503 SAFE_FREE(printers);
4508 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4509 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4515 /* check the required size. */
4516 for (i=0; i<*returned; i++)
4517 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4519 if (!alloc_buffer_size(buffer, *needed)) {
4520 for (i=0; i<*returned; i++) {
4521 free_devmode(printers[i].devmode);
4523 SAFE_FREE(printers);
4524 return WERR_INSUFFICIENT_BUFFER;
4527 /* fill the buffer with the structures */
4528 for (i=0; i<*returned; i++)
4529 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4532 for (i=0; i<*returned; i++) {
4533 free_devmode(printers[i].devmode);
4535 SAFE_FREE(printers);
4537 if (*needed > offered) {
4539 return WERR_INSUFFICIENT_BUFFER;
4545 /********************************************************************
4546 * handle enumeration of printers at level 1
4547 ********************************************************************/
4549 static WERROR enumprinters_level1( uint32 flags, fstring name,
4550 NEW_BUFFER *buffer, uint32 offered,
4551 uint32 *needed, uint32 *returned)
4553 /* Not all the flags are equals */
4555 if (flags & PRINTER_ENUM_LOCAL)
4556 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4558 if (flags & PRINTER_ENUM_NAME)
4559 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4561 if (flags & PRINTER_ENUM_REMOTE)
4562 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4564 if (flags & PRINTER_ENUM_NETWORK)
4565 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4567 return WERR_OK; /* NT4sp5 does that */
4570 /********************************************************************
4571 * handle enumeration of printers at level 2
4572 ********************************************************************/
4574 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4575 NEW_BUFFER *buffer, uint32 offered,
4576 uint32 *needed, uint32 *returned)
4578 char *s = servername;
4580 if (flags & PRINTER_ENUM_LOCAL) {
4581 return enum_all_printers_info_2(buffer, offered, needed, returned);
4584 if (flags & PRINTER_ENUM_NAME) {
4585 if ((servername[0] == '\\') && (servername[1] == '\\'))
4587 if (is_myname_or_ipaddr(s))
4588 return enum_all_printers_info_2(buffer, offered, needed, returned);
4590 return WERR_INVALID_NAME;
4593 if (flags & PRINTER_ENUM_REMOTE)
4594 return WERR_UNKNOWN_LEVEL;
4599 /********************************************************************
4600 * handle enumeration of printers at level 5
4601 ********************************************************************/
4603 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4604 NEW_BUFFER *buffer, uint32 offered,
4605 uint32 *needed, uint32 *returned)
4607 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4611 /********************************************************************
4612 * api_spoolss_enumprinters
4614 * called from api_spoolss_enumprinters (see this to understand)
4615 ********************************************************************/
4617 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4619 uint32 flags = q_u->flags;
4620 UNISTR2 *servername = &q_u->servername;
4621 uint32 level = q_u->level;
4622 NEW_BUFFER *buffer = NULL;
4623 uint32 offered = q_u->offered;
4624 uint32 *needed = &r_u->needed;
4625 uint32 *returned = &r_u->returned;
4629 /* that's an [in out] buffer */
4630 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4631 buffer = r_u->buffer;
4633 DEBUG(4,("_spoolss_enumprinters\n"));
4640 * flags==PRINTER_ENUM_NAME
4641 * if name=="" then enumerates all printers
4642 * if name!="" then enumerate the printer
4643 * flags==PRINTER_ENUM_REMOTE
4644 * name is NULL, enumerate printers
4645 * Level 2: name!="" enumerates printers, name can't be NULL
4646 * Level 3: doesn't exist
4647 * Level 4: does a local registry lookup
4648 * Level 5: same as Level 2
4651 unistr2_to_ascii(name, servername, sizeof(name)-1);
4656 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4658 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4660 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4665 return WERR_UNKNOWN_LEVEL;
4668 /****************************************************************************
4669 ****************************************************************************/
4671 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4673 PRINTER_INFO_0 *printer=NULL;
4675 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4678 construct_printer_info_0(print_hnd, printer, snum);
4680 /* check the required size. */
4681 *needed += spoolss_size_printer_info_0(printer);
4683 if (!alloc_buffer_size(buffer, *needed)) {
4685 return WERR_INSUFFICIENT_BUFFER;
4688 /* fill the buffer with the structures */
4689 smb_io_printer_info_0("", buffer, printer, 0);
4694 if (*needed > offered) {
4695 return WERR_INSUFFICIENT_BUFFER;
4701 /****************************************************************************
4702 ****************************************************************************/
4704 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4706 PRINTER_INFO_1 *printer=NULL;
4708 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4711 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4713 /* check the required size. */
4714 *needed += spoolss_size_printer_info_1(printer);
4716 if (!alloc_buffer_size(buffer, *needed)) {
4718 return WERR_INSUFFICIENT_BUFFER;
4721 /* fill the buffer with the structures */
4722 smb_io_printer_info_1("", buffer, printer, 0);
4727 if (*needed > offered) {
4728 return WERR_INSUFFICIENT_BUFFER;
4734 /****************************************************************************
4735 ****************************************************************************/
4737 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4739 PRINTER_INFO_2 *printer=NULL;
4741 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4744 construct_printer_info_2(print_hnd, printer, snum);
4746 /* check the required size. */
4747 *needed += spoolss_size_printer_info_2(printer);
4749 if (!alloc_buffer_size(buffer, *needed)) {
4750 free_printer_info_2(printer);
4751 return WERR_INSUFFICIENT_BUFFER;
4754 /* fill the buffer with the structures */
4755 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4756 free_printer_info_2(printer);
4761 free_printer_info_2(printer);
4763 if (*needed > offered) {
4764 return WERR_INSUFFICIENT_BUFFER;
4770 /****************************************************************************
4771 ****************************************************************************/
4773 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4775 PRINTER_INFO_3 *printer=NULL;
4777 if (!construct_printer_info_3(print_hnd, &printer, snum))
4780 /* check the required size. */
4781 *needed += spoolss_size_printer_info_3(printer);
4783 if (!alloc_buffer_size(buffer, *needed)) {
4784 free_printer_info_3(printer);
4785 return WERR_INSUFFICIENT_BUFFER;
4788 /* fill the buffer with the structures */
4789 smb_io_printer_info_3("", buffer, printer, 0);
4792 free_printer_info_3(printer);
4794 if (*needed > offered) {
4795 return WERR_INSUFFICIENT_BUFFER;
4801 /****************************************************************************
4802 ****************************************************************************/
4804 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4806 PRINTER_INFO_4 *printer=NULL;
4808 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4811 if (!construct_printer_info_4(print_hnd, printer, snum))
4814 /* check the required size. */
4815 *needed += spoolss_size_printer_info_4(printer);
4817 if (!alloc_buffer_size(buffer, *needed)) {
4818 free_printer_info_4(printer);
4819 return WERR_INSUFFICIENT_BUFFER;
4822 /* fill the buffer with the structures */
4823 smb_io_printer_info_4("", buffer, printer, 0);
4826 free_printer_info_4(printer);
4828 if (*needed > offered) {
4829 return WERR_INSUFFICIENT_BUFFER;
4835 /****************************************************************************
4836 ****************************************************************************/
4838 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4840 PRINTER_INFO_5 *printer=NULL;
4842 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4845 if (!construct_printer_info_5(print_hnd, printer, snum))
4848 /* check the required size. */
4849 *needed += spoolss_size_printer_info_5(printer);
4851 if (!alloc_buffer_size(buffer, *needed)) {
4852 free_printer_info_5(printer);
4853 return WERR_INSUFFICIENT_BUFFER;
4856 /* fill the buffer with the structures */
4857 smb_io_printer_info_5("", buffer, printer, 0);
4860 free_printer_info_5(printer);
4862 if (*needed > offered) {
4863 return WERR_INSUFFICIENT_BUFFER;
4869 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4871 PRINTER_INFO_7 *printer=NULL;
4873 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4876 if (!construct_printer_info_7(print_hnd, printer, snum))
4879 /* check the required size. */
4880 *needed += spoolss_size_printer_info_7(printer);
4882 if (!alloc_buffer_size(buffer, *needed)) {
4883 free_printer_info_7(printer);
4884 return WERR_INSUFFICIENT_BUFFER;
4887 /* fill the buffer with the structures */
4888 smb_io_printer_info_7("", buffer, printer, 0);
4891 free_printer_info_7(printer);
4893 if (*needed > offered) {
4894 return WERR_INSUFFICIENT_BUFFER;
4900 /****************************************************************************
4901 ****************************************************************************/
4903 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4905 POLICY_HND *handle = &q_u->handle;
4906 uint32 level = q_u->level;
4907 NEW_BUFFER *buffer = NULL;
4908 uint32 offered = q_u->offered;
4909 uint32 *needed = &r_u->needed;
4910 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4914 /* that's an [in out] buffer */
4915 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4916 buffer = r_u->buffer;
4920 if (!get_printer_snum(p, handle, &snum))
4925 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4927 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4929 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4931 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4933 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4935 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4937 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4939 return WERR_UNKNOWN_LEVEL;
4942 /********************************************************************
4943 * fill a DRIVER_INFO_1 struct
4944 ********************************************************************/
4946 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4948 init_unistr( &info->name, driver.info_3->name);
4951 /********************************************************************
4952 * construct_printer_driver_info_1
4953 ********************************************************************/
4955 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4957 NT_PRINTER_INFO_LEVEL *printer = NULL;
4958 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4960 ZERO_STRUCT(driver);
4962 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4963 return WERR_INVALID_PRINTER_NAME;
4965 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4966 return WERR_UNKNOWN_PRINTER_DRIVER;
4968 fill_printer_driver_info_1(info, driver, servername, architecture);
4970 free_a_printer(&printer,2);
4975 /********************************************************************
4976 * construct_printer_driver_info_2
4977 * fill a printer_info_2 struct
4978 ********************************************************************/
4980 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4984 info->version=driver.info_3->cversion;
4986 init_unistr( &info->name, driver.info_3->name );
4987 init_unistr( &info->architecture, driver.info_3->environment );
4990 if (strlen(driver.info_3->driverpath)) {
4991 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4992 init_unistr( &info->driverpath, temp );
4994 init_unistr( &info->driverpath, "" );
4996 if (strlen(driver.info_3->datafile)) {
4997 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4998 init_unistr( &info->datafile, temp );
5000 init_unistr( &info->datafile, "" );
5002 if (strlen(driver.info_3->configfile)) {
5003 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5004 init_unistr( &info->configfile, temp );
5006 init_unistr( &info->configfile, "" );
5009 /********************************************************************
5010 * construct_printer_driver_info_2
5011 * fill a printer_info_2 struct
5012 ********************************************************************/
5014 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5016 NT_PRINTER_INFO_LEVEL *printer = NULL;
5017 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5019 ZERO_STRUCT(printer);
5020 ZERO_STRUCT(driver);
5022 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5023 return WERR_INVALID_PRINTER_NAME;
5025 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5026 return WERR_UNKNOWN_PRINTER_DRIVER;
5028 fill_printer_driver_info_2(info, driver, servername);
5030 free_a_printer(&printer,2);
5035 /********************************************************************
5036 * copy a strings array and convert to UNICODE
5038 * convert an array of ascii string to a UNICODE string
5039 ********************************************************************/
5041 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5049 DEBUG(6,("init_unistr_array\n"));
5060 v = ""; /* hack to handle null lists */
5063 /* hack to allow this to be used in places other than when generating
5064 the list of dependent files */
5067 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5071 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
5073 /* add one extra unit16 for the second terminating NULL */
5075 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5076 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5084 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5089 /* special case for ""; we need to add both NULL's here */
5091 (*uni_array)[j++]=0x0000;
5092 (*uni_array)[j]=0x0000;
5095 DEBUGADD(6,("last one:done\n"));
5097 /* return size of array in uint16's */
5102 /********************************************************************
5103 * construct_printer_info_3
5104 * fill a printer_info_3 struct
5105 ********************************************************************/
5107 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5113 info->version=driver.info_3->cversion;
5115 init_unistr( &info->name, driver.info_3->name );
5116 init_unistr( &info->architecture, driver.info_3->environment );
5118 if (strlen(driver.info_3->driverpath)) {
5119 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5120 init_unistr( &info->driverpath, temp );
5122 init_unistr( &info->driverpath, "" );
5124 if (strlen(driver.info_3->datafile)) {
5125 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5126 init_unistr( &info->datafile, temp );
5128 init_unistr( &info->datafile, "" );
5130 if (strlen(driver.info_3->configfile)) {
5131 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5132 init_unistr( &info->configfile, temp );
5134 init_unistr( &info->configfile, "" );
5136 if (strlen(driver.info_3->helpfile)) {
5137 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5138 init_unistr( &info->helpfile, temp );
5140 init_unistr( &info->helpfile, "" );
5142 init_unistr( &info->monitorname, driver.info_3->monitorname );
5143 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5145 info->dependentfiles=NULL;
5146 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5149 /********************************************************************
5150 * construct_printer_info_3
5151 * fill a printer_info_3 struct
5152 ********************************************************************/
5154 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5156 NT_PRINTER_INFO_LEVEL *printer = NULL;
5157 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5159 ZERO_STRUCT(driver);
5161 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5162 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5163 if (!W_ERROR_IS_OK(status))
5164 return WERR_INVALID_PRINTER_NAME;
5166 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5167 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5172 * I put this code in during testing. Helpful when commenting out the
5173 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5174 * as win2k always queries the driver using an infor level of 6.
5175 * I've left it in (but ifdef'd out) because I'll probably
5176 * use it in experimentation again in the future. --jerry 22/01/2002
5179 if (!W_ERROR_IS_OK(status)) {
5181 * Is this a W2k client ?
5184 /* Yes - try again with a WinNT driver. */
5186 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5187 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5191 if (!W_ERROR_IS_OK(status)) {
5192 free_a_printer(&printer,2);
5193 return WERR_UNKNOWN_PRINTER_DRIVER;
5201 fill_printer_driver_info_3(info, driver, servername);
5203 free_a_printer(&printer,2);
5208 /********************************************************************
5209 * construct_printer_info_6
5210 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5211 ********************************************************************/
5213 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5219 memset(&nullstr, '\0', sizeof(fstring));
5221 info->version=driver.info_3->cversion;
5223 init_unistr( &info->name, driver.info_3->name );
5224 init_unistr( &info->architecture, driver.info_3->environment );
5226 if (strlen(driver.info_3->driverpath)) {
5227 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5228 init_unistr( &info->driverpath, temp );
5230 init_unistr( &info->driverpath, "" );
5232 if (strlen(driver.info_3->datafile)) {
5233 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5234 init_unistr( &info->datafile, temp );
5236 init_unistr( &info->datafile, "" );
5238 if (strlen(driver.info_3->configfile)) {
5239 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5240 init_unistr( &info->configfile, temp );
5242 init_unistr( &info->configfile, "" );
5244 if (strlen(driver.info_3->helpfile)) {
5245 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5246 init_unistr( &info->helpfile, temp );
5248 init_unistr( &info->helpfile, "" );
5250 init_unistr( &info->monitorname, driver.info_3->monitorname );
5251 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5253 info->dependentfiles = NULL;
5254 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5256 info->previousdrivernames=NULL;
5257 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5259 info->driver_date.low=0;
5260 info->driver_date.high=0;
5263 info->driver_version_low=0;
5264 info->driver_version_high=0;
5266 init_unistr( &info->mfgname, "");
5267 init_unistr( &info->oem_url, "");
5268 init_unistr( &info->hardware_id, "");
5269 init_unistr( &info->provider, "");
5272 /********************************************************************
5273 * construct_printer_info_6
5274 * fill a printer_info_6 struct
5275 ********************************************************************/
5277 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5278 fstring servername, fstring architecture, uint32 version)
5280 NT_PRINTER_INFO_LEVEL *printer = NULL;
5281 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5284 ZERO_STRUCT(driver);
5286 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5288 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5290 if (!W_ERROR_IS_OK(status))
5291 return WERR_INVALID_PRINTER_NAME;
5293 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5295 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5297 if (!W_ERROR_IS_OK(status))
5300 * Is this a W2k client ?
5304 free_a_printer(&printer,2);
5305 return WERR_UNKNOWN_PRINTER_DRIVER;
5308 /* Yes - try again with a WinNT driver. */
5310 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5311 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5312 if (!W_ERROR_IS_OK(status)) {
5313 free_a_printer(&printer,2);
5314 return WERR_UNKNOWN_PRINTER_DRIVER;
5318 fill_printer_driver_info_6(info, driver, servername);
5320 free_a_printer(&printer,2);
5321 free_a_printer_driver(driver, 3);
5326 /****************************************************************************
5327 ****************************************************************************/
5329 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5331 SAFE_FREE(info->dependentfiles);
5334 /****************************************************************************
5335 ****************************************************************************/
5337 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5339 SAFE_FREE(info->dependentfiles);
5343 /****************************************************************************
5344 ****************************************************************************/
5346 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5348 DRIVER_INFO_1 *info=NULL;
5351 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5354 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5355 if (!W_ERROR_IS_OK(status)) {
5360 /* check the required size. */
5361 *needed += spoolss_size_printer_driver_info_1(info);
5363 if (!alloc_buffer_size(buffer, *needed)) {
5365 return WERR_INSUFFICIENT_BUFFER;
5368 /* fill the buffer with the structures */
5369 smb_io_printer_driver_info_1("", buffer, info, 0);
5374 if (*needed > offered)
5375 return WERR_INSUFFICIENT_BUFFER;
5380 /****************************************************************************
5381 ****************************************************************************/
5383 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5385 DRIVER_INFO_2 *info=NULL;
5388 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5391 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5392 if (!W_ERROR_IS_OK(status)) {
5397 /* check the required size. */
5398 *needed += spoolss_size_printer_driver_info_2(info);
5400 if (!alloc_buffer_size(buffer, *needed)) {
5402 return WERR_INSUFFICIENT_BUFFER;
5405 /* fill the buffer with the structures */
5406 smb_io_printer_driver_info_2("", buffer, info, 0);
5411 if (*needed > offered)
5412 return WERR_INSUFFICIENT_BUFFER;
5417 /****************************************************************************
5418 ****************************************************************************/
5420 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5427 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5428 if (!W_ERROR_IS_OK(status)) {
5432 /* check the required size. */
5433 *needed += spoolss_size_printer_driver_info_3(&info);
5435 if (!alloc_buffer_size(buffer, *needed)) {
5436 free_printer_driver_info_3(&info);
5437 return WERR_INSUFFICIENT_BUFFER;
5440 /* fill the buffer with the structures */
5441 smb_io_printer_driver_info_3("", buffer, &info, 0);
5443 free_printer_driver_info_3(&info);
5445 if (*needed > offered)
5446 return WERR_INSUFFICIENT_BUFFER;
5451 /****************************************************************************
5452 ****************************************************************************/
5454 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5461 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5462 if (!W_ERROR_IS_OK(status)) {
5466 /* check the required size. */
5467 *needed += spoolss_size_printer_driver_info_6(&info);
5469 if (!alloc_buffer_size(buffer, *needed)) {
5470 free_printer_driver_info_6(&info);
5471 return WERR_INSUFFICIENT_BUFFER;
5474 /* fill the buffer with the structures */
5475 smb_io_printer_driver_info_6("", buffer, &info, 0);
5477 free_printer_driver_info_6(&info);
5479 if (*needed > offered)
5480 return WERR_INSUFFICIENT_BUFFER;
5485 /****************************************************************************
5486 ****************************************************************************/
5488 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5490 POLICY_HND *handle = &q_u->handle;
5491 UNISTR2 *uni_arch = &q_u->architecture;
5492 uint32 level = q_u->level;
5493 uint32 clientmajorversion = q_u->clientmajorversion;
5494 NEW_BUFFER *buffer = NULL;
5495 uint32 offered = q_u->offered;
5496 uint32 *needed = &r_u->needed;
5497 uint32 *servermajorversion = &r_u->servermajorversion;
5498 uint32 *serverminorversion = &r_u->serverminorversion;
5501 fstring architecture;
5504 /* that's an [in out] buffer */
5505 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5506 buffer = r_u->buffer;
5508 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5511 *servermajorversion = 0;
5512 *serverminorversion = 0;
5514 fstrcpy(servername, get_called_name());
5515 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5517 if (!get_printer_snum(p, handle, &snum))
5522 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5524 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5526 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5528 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5531 return WERR_UNKNOWN_LEVEL;
5534 /****************************************************************************
5535 ****************************************************************************/
5537 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5539 POLICY_HND *handle = &q_u->handle;
5541 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5544 DEBUG(3,("Error in startpageprinter printer handle\n"));
5548 Printer->page_started=True;
5552 /****************************************************************************
5553 ****************************************************************************/
5555 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5557 POLICY_HND *handle = &q_u->handle;
5560 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5563 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5567 if (!get_printer_snum(p, handle, &snum))
5570 Printer->page_started=False;
5571 print_job_endpage(snum, Printer->jobid);
5576 /********************************************************************
5577 * api_spoolss_getprinter
5578 * called from the spoolss dispatcher
5580 ********************************************************************/
5582 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5584 POLICY_HND *handle = &q_u->handle;
5585 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5586 uint32 *jobid = &r_u->jobid;
5588 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5592 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5593 struct current_user user;
5596 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5600 get_current_user(&user, p);
5603 * a nice thing with NT is it doesn't listen to what you tell it.
5604 * when asked to send _only_ RAW datas, it tries to send datas
5607 * So I add checks like in NT Server ...
5610 if (info_1->p_datatype != 0) {
5611 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5612 if (strcmp(datatype, "RAW") != 0) {
5614 return WERR_INVALID_DATATYPE;
5618 /* get the share number of the printer */
5619 if (!get_printer_snum(p, handle, &snum)) {
5623 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5625 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5627 /* An error occured in print_job_start() so return an appropriate
5630 if (Printer->jobid == -1) {
5631 return map_werror_from_unix(errno);
5634 Printer->document_started=True;
5635 (*jobid) = Printer->jobid;
5640 /********************************************************************
5641 * api_spoolss_getprinter
5642 * called from the spoolss dispatcher
5644 ********************************************************************/
5646 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5648 POLICY_HND *handle = &q_u->handle;
5650 return _spoolss_enddocprinter_internal(p, handle);
5653 /****************************************************************************
5654 ****************************************************************************/
5656 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5658 POLICY_HND *handle = &q_u->handle;
5659 uint32 buffer_size = q_u->buffer_size;
5660 uint8 *buffer = q_u->buffer;
5661 uint32 *buffer_written = &q_u->buffer_size2;
5663 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5666 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5667 r_u->buffer_written = q_u->buffer_size2;
5671 if (!get_printer_snum(p, handle, &snum))
5674 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5675 if (*buffer_written == -1) {
5676 r_u->buffer_written = 0;
5677 if (errno == ENOSPC)
5678 return WERR_NO_SPOOL_SPACE;
5680 return WERR_ACCESS_DENIED;
5683 r_u->buffer_written = q_u->buffer_size2;
5688 /********************************************************************
5689 * api_spoolss_getprinter
5690 * called from the spoolss dispatcher
5692 ********************************************************************/
5694 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5697 struct current_user user;
5699 WERROR errcode = WERR_BADFUNC;
5700 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5702 get_current_user(&user, p);
5705 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5709 if (!get_printer_snum(p, handle, &snum))
5713 case PRINTER_CONTROL_PAUSE:
5714 if (print_queue_pause(&user, snum, &errcode)) {
5718 case PRINTER_CONTROL_RESUME:
5719 case PRINTER_CONTROL_UNPAUSE:
5720 if (print_queue_resume(&user, snum, &errcode)) {
5724 case PRINTER_CONTROL_PURGE:
5725 if (print_queue_purge(&user, snum, &errcode)) {
5730 return WERR_UNKNOWN_LEVEL;
5736 /********************************************************************
5737 * api_spoolss_abortprinter
5738 * From MSDN: "Deletes printer's spool file if printer is configured
5740 ********************************************************************/
5742 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5744 POLICY_HND *handle = &q_u->handle;
5745 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5747 struct current_user user;
5748 WERROR errcode = WERR_OK;
5751 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5755 if (!get_printer_snum(p, handle, &snum))
5758 get_current_user( &user, p );
5760 print_job_delete( &user, snum, Printer->jobid, &errcode );
5765 /********************************************************************
5766 * called by spoolss_api_setprinter
5767 * when updating a printer description
5768 ********************************************************************/
5770 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5771 const SPOOL_PRINTER_INFO_LEVEL *info,
5772 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5774 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5775 struct current_user user;
5779 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5781 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5782 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5783 OUR_HANDLE(handle)));
5785 result = WERR_BADFID;
5789 /* NT seems to like setting the security descriptor even though
5790 nothing may have actually changed. This causes annoying
5791 dialog boxes when the user doesn't have permission to change
5792 the security descriptor. */
5794 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5796 if (DEBUGLEVEL >= 10) {
5800 the_acl = old_secdesc_ctr->sec->dacl;
5801 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5802 PRINTERNAME(snum), the_acl->num_aces));
5804 for (i = 0; i < the_acl->num_aces; i++) {
5807 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5809 DEBUG(10, ("%s 0x%08x\n", sid_str,
5810 the_acl->ace[i].info.mask));
5813 the_acl = secdesc_ctr->sec->dacl;
5816 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5817 PRINTERNAME(snum), the_acl->num_aces));
5819 for (i = 0; i < the_acl->num_aces; i++) {
5822 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5824 DEBUG(10, ("%s 0x%08x\n", sid_str,
5825 the_acl->ace[i].info.mask));
5828 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5832 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5834 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5839 /* Work out which user is performing the operation */
5841 get_current_user(&user, p);
5843 /* Check the user has permissions to change the security
5844 descriptor. By experimentation with two NT machines, the user
5845 requires Full Access to the printer to change security
5848 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5849 result = WERR_ACCESS_DENIED;
5853 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5860 /********************************************************************
5861 Do Samba sanity checks on a printer info struct.
5862 this has changed purpose: it now "canonicalises" printer
5863 info from a client rather than just checking it is correct
5864 ********************************************************************/
5866 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5868 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5869 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5871 /* we force some elements to "correct" values */
5872 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5873 fstrcpy(info->sharename, lp_servicename(snum));
5874 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5875 get_called_name(), info->sharename);
5876 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5882 /****************************************************************************
5883 ****************************************************************************/
5885 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5887 extern userdom_struct current_user_info;
5888 char *cmd = lp_addprinter_cmd();
5894 fstring remote_machine = "%m";
5896 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5898 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5899 cmd, printer->info_2->printername, printer->info_2->sharename,
5900 printer->info_2->portname, printer->info_2->drivername,
5901 printer->info_2->location, printer->info_2->comment, remote_machine);
5903 DEBUG(10,("Running [%s]\n", command));
5904 ret = smbrun(command, &fd);
5905 DEBUGADD(10,("returned [%d]\n", ret));
5914 /* Get lines and convert them back to dos-codepage */
5915 qlines = fd_lines_load(fd, &numlines);
5916 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5920 /* Set the portname to what the script says the portname should be. */
5921 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5922 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5924 /* Send SIGHUP to process group... is there a better way? */
5927 /* reload our services immediately */
5928 reload_services( False );
5931 file_lines_free(qlines);
5935 /********************************************************************
5936 * Called by spoolss_api_setprinter
5937 * when updating a printer description.
5938 ********************************************************************/
5940 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5941 const SPOOL_PRINTER_INFO_LEVEL *info,
5942 DEVICEMODE *devmode)
5945 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5946 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5951 DEBUG(8,("update_printer\n"));
5956 result = WERR_BADFID;
5960 if (!get_printer_snum(p, handle, &snum)) {
5961 result = WERR_BADFID;
5965 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5966 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5967 result = WERR_BADFID;
5971 DEBUGADD(8,("Converting info_2 struct\n"));
5974 * convert_printer_info converts the incoming
5975 * info from the client and overwrites the info
5976 * just read from the tdb in the pointer 'printer'.
5979 if (!convert_printer_info(info, printer, level)) {
5980 result = WERR_NOMEM;
5985 /* we have a valid devmode
5986 convert it and link it*/
5988 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5989 if (!convert_devicemode(printer->info_2->printername, devmode,
5990 &printer->info_2->devmode)) {
5991 result = WERR_NOMEM;
5996 /* Do sanity check on the requested changes for Samba */
5998 if (!check_printer_ok(printer->info_2, snum)) {
5999 result = WERR_INVALID_PARAM;
6003 /* FIXME!!! If the driver has changed we really should verify that
6004 it is installed before doing much else --jerry */
6006 /* Check calling user has permission to update printer description */
6008 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6009 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6010 result = WERR_ACCESS_DENIED;
6014 /* Call addprinter hook */
6015 /* Check changes to see if this is really needed */
6017 if ( *lp_addprinter_cmd()
6018 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6019 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6020 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6021 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6023 if ( !add_printer_hook(printer) ) {
6024 result = WERR_ACCESS_DENIED;
6029 * make sure we actually reload the services after
6030 * this as smb.conf could have a new section in it
6031 * .... shouldn't .... but could
6033 reload_services(False);
6037 * When a *new* driver is bound to a printer, the drivername is used to
6038 * lookup previously saved driver initialization info, which is then
6039 * bound to the printer, simulating what happens in the Windows arch.
6041 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6043 if (!set_driver_init(printer, 2))
6045 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6046 printer->info_2->drivername));
6049 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6050 printer->info_2->drivername));
6052 notify_printer_driver(snum, printer->info_2->drivername);
6056 * flag which changes actually occured. This is a small subset of
6057 * all the possible changes. We also have to update things in the
6061 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6062 init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 );
6063 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6064 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6066 notify_printer_comment(snum, printer->info_2->comment);
6069 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6070 init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 );
6071 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6072 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6073 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6074 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6076 notify_printer_sharename(snum, printer->info_2->sharename);
6079 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6080 init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 );
6081 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6082 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6084 notify_printer_port(snum, printer->info_2->portname);
6087 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6088 init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 );
6089 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6090 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6092 notify_printer_location(snum, printer->info_2->location);
6095 /* here we need to update some more DsSpooler keys */
6096 /* uNCName, serverName, shortServerName */
6098 init_unistr2( &buffer, global_myname(), strlen(global_myname())+1 );
6099 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6100 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6101 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6102 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6104 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6105 global_myname(), printer->info_2->sharename );
6106 init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 );
6107 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6108 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6110 /* Update printer info */
6111 result = mod_a_printer(*printer, 2);
6114 free_a_printer(&printer, 2);
6115 free_a_printer(&old_printer, 2);
6121 /****************************************************************************
6122 ****************************************************************************/
6123 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6124 const SPOOL_PRINTER_INFO_LEVEL *info)
6127 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6129 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6132 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6139 if (!get_printer_snum(p, handle, &snum))
6142 nt_printer_publish(Printer, snum, info7->action);
6146 return WERR_UNKNOWN_LEVEL;
6149 /****************************************************************************
6150 ****************************************************************************/
6152 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6154 POLICY_HND *handle = &q_u->handle;
6155 uint32 level = q_u->level;
6156 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6157 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6158 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6159 uint32 command = q_u->command;
6161 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6164 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6168 /* check the level */
6171 return control_printer(handle, command, p);
6173 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6175 return update_printer_sec(handle, level, info, p,
6178 return publish_or_unpublish_printer(p, handle, info);
6180 return WERR_UNKNOWN_LEVEL;
6184 /****************************************************************************
6185 ****************************************************************************/
6187 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6189 POLICY_HND *handle = &q_u->handle;
6190 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6193 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6197 if (Printer->notify.client_connected==True) {
6200 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6202 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6203 !get_printer_snum(p, handle, &snum) )
6206 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6209 Printer->notify.flags=0;
6210 Printer->notify.options=0;
6211 Printer->notify.localmachine[0]='\0';
6212 Printer->notify.printerlocal=0;
6213 if (Printer->notify.option)
6214 free_spool_notify_option(&Printer->notify.option);
6215 Printer->notify.client_connected=False;
6220 /****************************************************************************
6221 ****************************************************************************/
6223 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6225 /* that's an [in out] buffer (despite appearences to the contrary) */
6226 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6229 return WERR_INVALID_PARAM; /* this is what a NT server
6230 returns for AddJob. AddJob
6231 must fail on non-local
6235 /****************************************************************************
6236 ****************************************************************************/
6238 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6239 int position, int snum)
6245 t=gmtime(&queue->time);
6246 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6248 job_info->jobid=queue->job;
6249 init_unistr(&job_info->printername, lp_servicename(snum));
6250 init_unistr(&job_info->machinename, temp_name);
6251 init_unistr(&job_info->username, queue->fs_user);
6252 init_unistr(&job_info->document, queue->fs_file);
6253 init_unistr(&job_info->datatype, "RAW");
6254 init_unistr(&job_info->text_status, "");
6255 job_info->status=nt_printj_status(queue->status);
6256 job_info->priority=queue->priority;
6257 job_info->position=position;
6258 job_info->totalpages=queue->page_count;
6259 job_info->pagesprinted=0;
6261 make_systemtime(&job_info->submitted, t);
6264 /****************************************************************************
6265 ****************************************************************************/
6267 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6268 int position, int snum,
6269 NT_PRINTER_INFO_LEVEL *ntprinter,
6270 DEVICEMODE *devmode)
6275 t=gmtime(&queue->time);
6276 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6278 job_info->jobid=queue->job;
6280 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6282 init_unistr(&job_info->machinename, temp_name);
6283 init_unistr(&job_info->username, queue->fs_user);
6284 init_unistr(&job_info->document, queue->fs_file);
6285 init_unistr(&job_info->notifyname, queue->fs_user);
6286 init_unistr(&job_info->datatype, "RAW");
6287 init_unistr(&job_info->printprocessor, "winprint");
6288 init_unistr(&job_info->parameters, "");
6289 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6290 init_unistr(&job_info->text_status, "");
6292 /* and here the security descriptor */
6294 job_info->status=nt_printj_status(queue->status);
6295 job_info->priority=queue->priority;
6296 job_info->position=position;
6297 job_info->starttime=0;
6298 job_info->untiltime=0;
6299 job_info->totalpages=queue->page_count;
6300 job_info->size=queue->size;
6301 make_systemtime(&(job_info->submitted), t);
6302 job_info->timeelapsed=0;
6303 job_info->pagesprinted=0;
6305 job_info->devmode = devmode;
6310 /****************************************************************************
6311 Enumjobs at level 1.
6312 ****************************************************************************/
6314 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6315 NEW_BUFFER *buffer, uint32 offered,
6316 uint32 *needed, uint32 *returned)
6321 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6328 for (i=0; i<*returned; i++)
6329 fill_job_info_1(&info[i], &queue[i], i, snum);
6333 /* check the required size. */
6334 for (i=0; i<*returned; i++)
6335 (*needed) += spoolss_size_job_info_1(&info[i]);
6337 if (!alloc_buffer_size(buffer, *needed)) {
6339 return WERR_INSUFFICIENT_BUFFER;
6342 /* fill the buffer with the structures */
6343 for (i=0; i<*returned; i++)
6344 smb_io_job_info_1("", buffer, &info[i], 0);
6349 if (*needed > offered) {
6351 return WERR_INSUFFICIENT_BUFFER;
6357 /****************************************************************************
6358 Enumjobs at level 2.
6359 ****************************************************************************/
6361 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6362 NEW_BUFFER *buffer, uint32 offered,
6363 uint32 *needed, uint32 *returned)
6365 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6366 JOB_INFO_2 *info = NULL;
6369 DEVICEMODE *devmode = NULL;
6371 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6374 result = WERR_NOMEM;
6378 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6379 if (!W_ERROR_IS_OK(result)) {
6384 /* this should not be a failure condition if the devmode is NULL */
6386 devmode = construct_dev_mode(snum);
6388 for (i=0; i<*returned; i++)
6389 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6392 free_a_printer(&ntprinter, 2);
6395 /* check the required size. */
6396 for (i=0; i<*returned; i++)
6397 (*needed) += spoolss_size_job_info_2(&info[i]);
6399 if (*needed > offered) {
6401 result = WERR_INSUFFICIENT_BUFFER;
6405 if (!alloc_buffer_size(buffer, *needed)) {
6407 result = WERR_INSUFFICIENT_BUFFER;
6411 /* fill the buffer with the structures */
6412 for (i=0; i<*returned; i++)
6413 smb_io_job_info_2("", buffer, &info[i], 0);
6418 free_a_printer(&ntprinter, 2);
6419 free_devmode(devmode);
6427 /****************************************************************************
6429 ****************************************************************************/
6431 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6433 POLICY_HND *handle = &q_u->handle;
6434 uint32 level = q_u->level;
6435 NEW_BUFFER *buffer = NULL;
6436 uint32 offered = q_u->offered;
6437 uint32 *needed = &r_u->needed;
6438 uint32 *returned = &r_u->returned;
6442 print_status_struct prt_status;
6443 print_queue_struct *queue=NULL;
6445 /* that's an [in out] buffer */
6446 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6447 buffer = r_u->buffer;
6449 DEBUG(4,("_spoolss_enumjobs\n"));
6454 if (!get_printer_snum(p, handle, &snum))
6457 *returned = print_queue_status(snum, &queue, &prt_status);
6458 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6460 if (*returned == 0) {
6461 set_enumjobs_timestamp(snum);
6468 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6469 set_enumjobs_timestamp(snum);
6472 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6473 set_enumjobs_timestamp(snum);
6478 return WERR_UNKNOWN_LEVEL;
6482 /****************************************************************************
6483 ****************************************************************************/
6485 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6490 /****************************************************************************
6491 ****************************************************************************/
6493 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6495 POLICY_HND *handle = &q_u->handle;
6496 uint32 jobid = q_u->jobid;
6497 uint32 command = q_u->command;
6499 struct current_user user;
6501 WERROR errcode = WERR_BADFUNC;
6503 if (!get_printer_snum(p, handle, &snum)) {
6507 if (!print_job_exists(snum, jobid)) {
6508 return WERR_INVALID_PRINTER_NAME;
6511 get_current_user(&user, p);
6514 case JOB_CONTROL_CANCEL:
6515 case JOB_CONTROL_DELETE:
6516 if (print_job_delete(&user, snum, jobid, &errcode)) {
6520 case JOB_CONTROL_PAUSE:
6521 if (print_job_pause(&user, snum, jobid, &errcode)) {
6525 case JOB_CONTROL_RESTART:
6526 case JOB_CONTROL_RESUME:
6527 if (print_job_resume(&user, snum, jobid, &errcode)) {
6532 return WERR_UNKNOWN_LEVEL;
6538 /****************************************************************************
6539 Enumerates all printer drivers at level 1.
6540 ****************************************************************************/
6542 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6547 fstring *list = NULL;
6549 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6550 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6554 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6556 ndrivers=get_ntdrivers(&list, architecture, version);
6557 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6563 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6564 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6565 SAFE_FREE(driver_info_1);
6569 else driver_info_1 = tdi1;
6572 for (i=0; i<ndrivers; i++) {
6574 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6575 ZERO_STRUCT(driver);
6576 status = get_a_printer_driver(&driver, 3, list[i],
6577 architecture, version);
6578 if (!W_ERROR_IS_OK(status)) {
6582 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6583 free_a_printer_driver(driver, 3);
6586 *returned+=ndrivers;
6590 /* check the required size. */
6591 for (i=0; i<*returned; i++) {
6592 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6593 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6596 if (!alloc_buffer_size(buffer, *needed)) {
6597 SAFE_FREE(driver_info_1);
6598 return WERR_INSUFFICIENT_BUFFER;
6601 /* fill the buffer with the driver structures */
6602 for (i=0; i<*returned; i++) {
6603 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6604 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6607 SAFE_FREE(driver_info_1);
6609 if (*needed > offered) {
6611 return WERR_INSUFFICIENT_BUFFER;
6617 /****************************************************************************
6618 Enumerates all printer drivers at level 2.
6619 ****************************************************************************/
6621 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6626 fstring *list = NULL;
6628 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6629 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6633 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6635 ndrivers=get_ntdrivers(&list, architecture, version);
6636 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6642 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6643 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6644 SAFE_FREE(driver_info_2);
6648 else driver_info_2 = tdi2;
6651 for (i=0; i<ndrivers; i++) {
6654 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6655 ZERO_STRUCT(driver);
6656 status = get_a_printer_driver(&driver, 3, list[i],
6657 architecture, version);
6658 if (!W_ERROR_IS_OK(status)) {
6662 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6663 free_a_printer_driver(driver, 3);
6666 *returned+=ndrivers;
6670 /* check the required size. */
6671 for (i=0; i<*returned; i++) {
6672 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6673 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6676 if (!alloc_buffer_size(buffer, *needed)) {
6677 SAFE_FREE(driver_info_2);
6678 return WERR_INSUFFICIENT_BUFFER;
6681 /* fill the buffer with the form structures */
6682 for (i=0; i<*returned; i++) {
6683 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6684 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6687 SAFE_FREE(driver_info_2);
6689 if (*needed > offered) {
6691 return WERR_INSUFFICIENT_BUFFER;
6697 /****************************************************************************
6698 Enumerates all printer drivers at level 3.
6699 ****************************************************************************/
6701 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6706 fstring *list = NULL;
6708 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6709 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6713 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6715 ndrivers=get_ntdrivers(&list, architecture, version);
6716 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6722 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6723 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6724 SAFE_FREE(driver_info_3);
6728 else driver_info_3 = tdi3;
6731 for (i=0; i<ndrivers; i++) {
6734 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6735 ZERO_STRUCT(driver);
6736 status = get_a_printer_driver(&driver, 3, list[i],
6737 architecture, version);
6738 if (!W_ERROR_IS_OK(status)) {
6742 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6743 free_a_printer_driver(driver, 3);
6746 *returned+=ndrivers;
6750 /* check the required size. */
6751 for (i=0; i<*returned; i++) {
6752 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6753 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6756 if (!alloc_buffer_size(buffer, *needed)) {
6757 SAFE_FREE(driver_info_3);
6758 return WERR_INSUFFICIENT_BUFFER;
6761 /* fill the buffer with the driver structures */
6762 for (i=0; i<*returned; i++) {
6763 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6764 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6767 for (i=0; i<*returned; i++)
6768 SAFE_FREE(driver_info_3[i].dependentfiles);
6770 SAFE_FREE(driver_info_3);
6772 if (*needed > offered) {
6774 return WERR_INSUFFICIENT_BUFFER;
6780 /****************************************************************************
6781 Enumerates all printer drivers.
6782 ****************************************************************************/
6784 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6786 UNISTR2 *environment = &q_u->environment;
6787 uint32 level = q_u->level;
6788 NEW_BUFFER *buffer = NULL;
6789 uint32 offered = q_u->offered;
6790 uint32 *needed = &r_u->needed;
6791 uint32 *returned = &r_u->returned;
6793 fstring *list = NULL;
6795 fstring architecture;
6797 /* that's an [in out] buffer */
6798 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6799 buffer = r_u->buffer;
6801 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6802 fstrcpy(servername, get_called_name());
6806 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6810 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6812 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6814 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6818 return WERR_UNKNOWN_LEVEL;
6822 /****************************************************************************
6823 ****************************************************************************/
6825 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6827 form->flag=list->flag;
6828 init_unistr(&form->name, list->name);
6829 form->width=list->width;
6830 form->length=list->length;
6831 form->left=list->left;
6832 form->top=list->top;
6833 form->right=list->right;
6834 form->bottom=list->bottom;
6837 /****************************************************************************
6838 ****************************************************************************/
6840 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6842 uint32 level = q_u->level;
6843 NEW_BUFFER *buffer = NULL;
6844 uint32 offered = q_u->offered;
6845 uint32 *needed = &r_u->needed;
6846 uint32 *numofforms = &r_u->numofforms;
6847 uint32 numbuiltinforms;
6849 nt_forms_struct *list=NULL;
6850 nt_forms_struct *builtinlist=NULL;
6855 /* that's an [in out] buffer */
6856 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6857 buffer = r_u->buffer;
6859 DEBUG(4,("_spoolss_enumforms\n"));
6860 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6861 DEBUGADD(5,("Info level [%d]\n", level));
6863 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6864 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6865 *numofforms = get_ntforms(&list);
6866 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6867 *numofforms += numbuiltinforms;
6869 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6873 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6878 /* construct the list of form structures */
6879 for (i=0; i<numbuiltinforms; i++) {
6880 DEBUGADD(6,("Filling form number [%d]\n",i));
6881 fill_form_1(&forms_1[i], &builtinlist[i]);
6884 SAFE_FREE(builtinlist);
6886 for (; i<*numofforms; i++) {
6887 DEBUGADD(6,("Filling form number [%d]\n",i));
6888 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6893 /* check the required size. */
6894 for (i=0; i<numbuiltinforms; i++) {
6895 DEBUGADD(6,("adding form [%d]'s size\n",i));
6896 buffer_size += spoolss_size_form_1(&forms_1[i]);
6898 for (; i<*numofforms; i++) {
6899 DEBUGADD(6,("adding form [%d]'s size\n",i));
6900 buffer_size += spoolss_size_form_1(&forms_1[i]);
6903 *needed=buffer_size;
6905 if (!alloc_buffer_size(buffer, buffer_size)){
6907 return WERR_INSUFFICIENT_BUFFER;
6910 /* fill the buffer with the form structures */
6911 for (i=0; i<numbuiltinforms; i++) {
6912 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6913 smb_io_form_1("", buffer, &forms_1[i], 0);
6915 for (; i<*numofforms; i++) {
6916 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6917 smb_io_form_1("", buffer, &forms_1[i], 0);
6922 if (*needed > offered) {
6924 return WERR_INSUFFICIENT_BUFFER;
6931 SAFE_FREE(builtinlist);
6932 return WERR_UNKNOWN_LEVEL;
6937 /****************************************************************************
6938 ****************************************************************************/
6940 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6942 uint32 level = q_u->level;
6943 UNISTR2 *uni_formname = &q_u->formname;
6944 NEW_BUFFER *buffer = NULL;
6945 uint32 offered = q_u->offered;
6946 uint32 *needed = &r_u->needed;
6948 nt_forms_struct *list=NULL;
6949 nt_forms_struct builtin_form;
6954 int numofforms=0, i=0;
6956 /* that's an [in out] buffer */
6957 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6958 buffer = r_u->buffer;
6960 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6962 DEBUG(4,("_spoolss_getform\n"));
6963 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6964 DEBUGADD(5,("Info level [%d]\n", level));
6966 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6967 if (!foundBuiltin) {
6968 numofforms = get_ntforms(&list);
6969 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6971 if (numofforms == 0)
6978 fill_form_1(&form_1, &builtin_form);
6981 /* Check if the requested name is in the list of form structures */
6982 for (i=0; i<numofforms; i++) {
6984 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6986 if (strequal(form_name, list[i].name)) {
6987 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6988 fill_form_1(&form_1, &list[i]);
6994 if (i == numofforms) {
6998 /* check the required size. */
7000 *needed=spoolss_size_form_1(&form_1);
7002 if (!alloc_buffer_size(buffer, buffer_size)){
7003 return WERR_INSUFFICIENT_BUFFER;
7006 if (*needed > offered) {
7007 return WERR_INSUFFICIENT_BUFFER;
7010 /* fill the buffer with the form structures */
7011 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7012 smb_io_form_1("", buffer, &form_1, 0);
7018 return WERR_UNKNOWN_LEVEL;
7022 /****************************************************************************
7023 ****************************************************************************/
7025 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7027 init_unistr(&port->port_name, name);
7030 /****************************************************************************
7031 ****************************************************************************/
7033 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7035 init_unistr(&port->port_name, name);
7036 init_unistr(&port->monitor_name, "Local Monitor");
7037 init_unistr(&port->description, "Local Port");
7038 #define PORT_TYPE_WRITE 1
7039 port->port_type=PORT_TYPE_WRITE;
7043 /****************************************************************************
7045 ****************************************************************************/
7047 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7049 PORT_INFO_1 *ports=NULL;
7052 if (*lp_enumports_cmd()) {
7053 char *cmd = lp_enumports_cmd();
7060 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7062 DEBUG(10,("Running [%s]\n", command));
7063 ret = smbrun(command, &fd);
7064 DEBUG(10,("Returned [%d]\n", ret));
7068 /* Is this the best error to return here? */
7069 return WERR_ACCESS_DENIED;
7073 qlines = fd_lines_load(fd, &numlines);
7074 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7078 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7079 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7080 dos_errstr(WERR_NOMEM)));
7081 file_lines_free(qlines);
7085 for (i=0; i<numlines; i++) {
7086 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7087 fill_port_1(&ports[i], qlines[i]);
7090 file_lines_free(qlines);
7093 *returned = numlines;
7096 *returned = 1; /* Sole Samba port returned. */
7098 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7101 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7103 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7106 /* check the required size. */
7107 for (i=0; i<*returned; i++) {
7108 DEBUGADD(6,("adding port [%d]'s size\n", i));
7109 *needed += spoolss_size_port_info_1(&ports[i]);
7112 if (!alloc_buffer_size(buffer, *needed)) {
7114 return WERR_INSUFFICIENT_BUFFER;
7117 /* fill the buffer with the ports structures */
7118 for (i=0; i<*returned; i++) {
7119 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7120 smb_io_port_1("", buffer, &ports[i], 0);
7125 if (*needed > offered) {
7127 return WERR_INSUFFICIENT_BUFFER;
7133 /****************************************************************************
7135 ****************************************************************************/
7137 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7139 PORT_INFO_2 *ports=NULL;
7142 if (*lp_enumports_cmd()) {
7143 char *cmd = lp_enumports_cmd();
7152 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7153 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7155 path = lp_lockdir();
7157 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7158 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7161 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7162 ret = smbrun(command, &fd);
7163 DEBUGADD(10,("returned [%d]\n", ret));
7167 /* Is this the best error to return here? */
7168 return WERR_ACCESS_DENIED;
7172 qlines = fd_lines_load(fd, &numlines);
7173 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7177 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7178 file_lines_free(qlines);
7182 for (i=0; i<numlines; i++) {
7183 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7184 fill_port_2(&(ports[i]), qlines[i]);
7187 file_lines_free(qlines);
7190 *returned = numlines;
7196 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7199 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7201 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7204 /* check the required size. */
7205 for (i=0; i<*returned; i++) {
7206 DEBUGADD(6,("adding port [%d]'s size\n", i));
7207 *needed += spoolss_size_port_info_2(&ports[i]);
7210 if (!alloc_buffer_size(buffer, *needed)) {
7212 return WERR_INSUFFICIENT_BUFFER;
7215 /* fill the buffer with the ports structures */
7216 for (i=0; i<*returned; i++) {
7217 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7218 smb_io_port_2("", buffer, &ports[i], 0);
7223 if (*needed > offered) {
7225 return WERR_INSUFFICIENT_BUFFER;
7231 /****************************************************************************
7233 ****************************************************************************/
7235 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7237 uint32 level = q_u->level;
7238 NEW_BUFFER *buffer = NULL;
7239 uint32 offered = q_u->offered;
7240 uint32 *needed = &r_u->needed;
7241 uint32 *returned = &r_u->returned;
7243 /* that's an [in out] buffer */
7244 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7245 buffer = r_u->buffer;
7247 DEBUG(4,("_spoolss_enumports\n"));
7254 return enumports_level_1(buffer, offered, needed, returned);
7256 return enumports_level_2(buffer, offered, needed, returned);
7258 return WERR_UNKNOWN_LEVEL;
7262 /****************************************************************************
7263 ****************************************************************************/
7265 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7266 const SPOOL_PRINTER_INFO_LEVEL *info,
7267 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7268 uint32 user_switch, const SPOOL_USER_CTR *user,
7271 NT_PRINTER_INFO_LEVEL *printer = NULL;
7274 WERROR err = WERR_OK;
7276 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7277 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7281 ZERO_STRUCTP(printer);
7283 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7284 if (!convert_printer_info(info, printer, 2)) {
7285 free_a_printer(&printer, 2);
7289 /* check to see if the printer already exists */
7291 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7292 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7293 printer->info_2->sharename));
7294 free_a_printer(&printer, 2);
7295 return WERR_PRINTER_ALREADY_EXISTS;
7298 /* FIXME!!! smbd should check to see if the driver is installed before
7299 trying to add a printer like this --jerry */
7301 if (*lp_addprinter_cmd() ) {
7302 if ( !add_printer_hook(printer) ) {
7303 free_a_printer(&printer,2);
7304 return WERR_ACCESS_DENIED;
7308 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7309 printer->info_2->sharename);
7312 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7313 free_a_printer(&printer,2);
7314 return WERR_ACCESS_DENIED;
7317 /* you must be a printer admin to add a new printer */
7318 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7319 free_a_printer(&printer,2);
7320 return WERR_ACCESS_DENIED;
7324 * Do sanity check on the requested changes for Samba.
7327 if (!check_printer_ok(printer->info_2, snum)) {
7328 free_a_printer(&printer,2);
7329 return WERR_INVALID_PARAM;
7333 * When a printer is created, the drivername bound to the printer is used
7334 * to lookup previously saved driver initialization info, which is then
7335 * bound to the new printer, simulating what happens in the Windows arch.
7340 set_driver_init(printer, 2);
7344 /* A valid devmode was included, convert and link it
7346 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7348 if (!convert_devicemode(printer->info_2->printername, devmode,
7349 &printer->info_2->devmode))
7353 /* write the ASCII on disk */
7354 err = mod_a_printer(*printer, 2);
7355 if (!W_ERROR_IS_OK(err)) {
7356 free_a_printer(&printer,2);
7360 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7361 /* Handle open failed - remove addition. */
7362 del_a_printer(printer->info_2->sharename);
7363 free_a_printer(&printer,2);
7364 return WERR_ACCESS_DENIED;
7367 update_c_setprinter(False);
7368 free_a_printer(&printer,2);
7373 /****************************************************************************
7374 ****************************************************************************/
7376 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7378 UNISTR2 *uni_srv_name = &q_u->server_name;
7379 uint32 level = q_u->level;
7380 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7381 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7382 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7383 uint32 user_switch = q_u->user_switch;
7384 SPOOL_USER_CTR *user = &q_u->user_ctr;
7385 POLICY_HND *handle = &r_u->handle;
7389 /* we don't handle yet */
7390 /* but I know what to do ... */
7391 return WERR_UNKNOWN_LEVEL;
7393 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7395 user_switch, user, handle);
7397 return WERR_UNKNOWN_LEVEL;
7401 /****************************************************************************
7402 ****************************************************************************/
7404 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7406 uint32 level = q_u->level;
7407 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7408 WERROR err = WERR_OK;
7409 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7410 struct current_user user;
7411 fstring driver_name;
7414 ZERO_STRUCT(driver);
7416 get_current_user(&user, p);
7418 if (!convert_printer_driver_info(info, &driver, level)) {
7423 DEBUG(5,("Cleaning driver's information\n"));
7424 err = clean_up_driver_struct(driver, level, &user);
7425 if (!W_ERROR_IS_OK(err))
7428 DEBUG(5,("Moving driver to final destination\n"));
7429 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7430 if (W_ERROR_IS_OK(err))
7431 err = WERR_ACCESS_DENIED;
7435 if (add_a_printer_driver(driver, level)!=0) {
7436 err = WERR_ACCESS_DENIED;
7440 /* BEGIN_ADMIN_LOG */
7443 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7444 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7445 fstrcpy(driver_name, driver.info_3->name);
7448 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7449 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7450 fstrcpy(driver_name, driver.info_6->name);
7456 * I think this is where he DrvUpgradePrinter() hook would be
7457 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7458 * server. Right now, we just need to send ourselves a message
7459 * to update each printer bound to this driver. --jerry
7462 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7463 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7468 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7469 * decide if the driver init data should be deleted. The rules are:
7470 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7471 * 2) delete init data only if there is no 2k/Xp driver
7472 * 3) always delete init data
7473 * The generalized rule is always use init data from the highest order driver.
7474 * It is necessary to follow the driver install by an initialization step to
7475 * finish off this process.
7478 version = driver.info_3->cversion;
7479 else if (level == 6)
7480 version = driver.info_6->version;
7485 * 9x printer driver - never delete init data
7488 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7493 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7494 * there is no 2k/Xp driver init data for this driver name.
7498 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7500 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7502 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7504 if (!del_driver_init(driver_name))
7505 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7508 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7510 free_a_printer_driver(driver1,3);
7511 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7518 * 2k or Xp printer driver - always delete init data
7521 if (!del_driver_init(driver_name))
7522 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7526 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7532 free_a_printer_driver(driver, level);
7536 /********************************************************************
7537 * spoolss_addprinterdriverex
7538 ********************************************************************/
7540 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7542 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7543 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7546 * we only support the semantics of AddPrinterDriver()
7547 * i.e. only copy files that are newer than existing ones
7550 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7551 return WERR_ACCESS_DENIED;
7553 ZERO_STRUCT(q_u_local);
7554 ZERO_STRUCT(r_u_local);
7556 /* just pass the information off to _spoolss_addprinterdriver() */
7557 q_u_local.server_name_ptr = q_u->server_name_ptr;
7558 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7559 q_u_local.level = q_u->level;
7560 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7562 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7565 /****************************************************************************
7566 ****************************************************************************/
7568 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7570 init_unistr(&info->name, name);
7573 /****************************************************************************
7574 ****************************************************************************/
7576 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7580 pstring short_archi;
7581 DRIVER_DIRECTORY_1 *info=NULL;
7583 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7585 if (get_short_archi(short_archi, long_archi)==False)
7586 return WERR_INVALID_ENVIRONMENT;
7588 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7591 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7593 DEBUG(4,("printer driver directory: [%s]\n", path));
7595 fill_driverdir_1(info, path);
7597 *needed += spoolss_size_driverdir_info_1(info);
7599 if (!alloc_buffer_size(buffer, *needed)) {
7601 return WERR_INSUFFICIENT_BUFFER;
7604 smb_io_driverdir_1("", buffer, info, 0);
7608 if (*needed > offered)
7609 return WERR_INSUFFICIENT_BUFFER;
7614 /****************************************************************************
7615 ****************************************************************************/
7617 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7619 UNISTR2 *name = &q_u->name;
7620 UNISTR2 *uni_environment = &q_u->environment;
7621 uint32 level = q_u->level;
7622 NEW_BUFFER *buffer = NULL;
7623 uint32 offered = q_u->offered;
7624 uint32 *needed = &r_u->needed;
7626 /* that's an [in out] buffer */
7627 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7628 buffer = r_u->buffer;
7630 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7636 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7638 return WERR_UNKNOWN_LEVEL;
7642 /****************************************************************************
7643 ****************************************************************************/
7645 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7647 POLICY_HND *handle = &q_u->handle;
7648 uint32 idx = q_u->index;
7649 uint32 in_value_len = q_u->valuesize;
7650 uint32 in_data_len = q_u->datasize;
7651 uint32 *out_max_value_len = &r_u->valuesize;
7652 uint16 **out_value = &r_u->value;
7653 uint32 *out_value_len = &r_u->realvaluesize;
7654 uint32 *out_type = &r_u->type;
7655 uint32 *out_max_data_len = &r_u->datasize;
7656 uint8 **data_out = &r_u->data;
7657 uint32 *out_data_len = &r_u->realdatasize;
7659 NT_PRINTER_INFO_LEVEL *printer = NULL;
7662 uint32 biggest_valuesize;
7663 uint32 biggest_datasize;
7665 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7668 REGISTRY_VALUE *val = NULL;
7669 NT_PRINTER_DATA *p_data;
7670 int i, key_index, num_values;
7673 ZERO_STRUCT( printer );
7677 *out_max_data_len = 0;
7681 DEBUG(5,("spoolss_enumprinterdata\n"));
7684 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7688 if (!get_printer_snum(p,handle, &snum))
7691 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7692 if (!W_ERROR_IS_OK(result))
7695 p_data = &printer->info_2->data;
7696 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7701 * The NT machine wants to know the biggest size of value and data
7703 * cf: MSDN EnumPrinterData remark section
7706 if ( !in_value_len && !in_data_len && (key_index != -1) )
7708 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7711 biggest_valuesize = 0;
7712 biggest_datasize = 0;
7714 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7716 for ( i=0; i<num_values; i++ )
7718 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7720 name_length = strlen(val->valuename);
7721 if ( strlen(val->valuename) > biggest_valuesize )
7722 biggest_valuesize = name_length;
7724 if ( val->size > biggest_datasize )
7725 biggest_datasize = val->size;
7727 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7731 /* the value is an UNICODE string but real_value_size is the length
7732 in bytes including the trailing 0 */
7734 *out_value_len = 2 * (1+biggest_valuesize);
7735 *out_data_len = biggest_datasize;
7737 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7743 * the value len is wrong in NT sp3
7744 * that's the number of bytes not the number of unicode chars
7747 if ( key_index != -1 )
7748 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7753 /* out_value should default to "" or else NT4 has
7754 problems unmarshalling the response */
7756 *out_max_value_len=(in_value_len/sizeof(uint16));
7758 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7760 result = WERR_NOMEM;
7764 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7766 /* the data is counted in bytes */
7768 *out_max_data_len = in_data_len;
7769 *out_data_len = in_data_len;
7771 /* only allocate when given a non-zero data_len */
7773 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7775 result = WERR_NOMEM;
7779 result = WERR_NO_MORE_ITEMS;
7785 * - counted in bytes in the request
7786 * - counted in UNICODE chars in the max reply
7787 * - counted in bytes in the real size
7789 * take a pause *before* coding not *during* coding
7793 *out_max_value_len=(in_value_len/sizeof(uint16));
7794 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7796 result = WERR_NOMEM;
7800 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7804 *out_type = regval_type( val );
7806 /* data - counted in bytes */
7808 *out_max_data_len = in_data_len;
7809 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7811 result = WERR_NOMEM;
7814 data_len = (size_t)regval_size(val);
7815 memcpy( *data_out, regval_data_p(val), data_len );
7816 *out_data_len = data_len;
7820 free_a_printer(&printer, 2);
7824 /****************************************************************************
7825 ****************************************************************************/
7827 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7829 POLICY_HND *handle = &q_u->handle;
7830 UNISTR2 *value = &q_u->value;
7831 uint32 type = q_u->type;
7832 uint8 *data = q_u->data;
7833 uint32 real_len = q_u->real_len;
7835 NT_PRINTER_INFO_LEVEL *printer = NULL;
7837 WERROR status = WERR_OK;
7838 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7841 DEBUG(5,("spoolss_setprinterdata\n"));
7844 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7848 if (!get_printer_snum(p,handle, &snum))
7852 * Access check : NT returns "access denied" if you make a
7853 * SetPrinterData call without the necessary privildge.
7854 * we were originally returning OK if nothing changed
7855 * which made Win2k issue **a lot** of SetPrinterData
7856 * when connecting to a printer --jerry
7859 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7861 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7862 status = WERR_ACCESS_DENIED;
7866 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7867 if (!W_ERROR_IS_OK(status))
7870 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7873 * When client side code sets a magic printer data key, detect it and save
7874 * the current printer data and the magic key's data (its the DEVMODE) for
7875 * future printer/driver initializations.
7877 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7879 /* Set devmode and printer initialization info */
7880 status = save_driver_init( printer, 2, data, real_len );
7882 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7886 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7887 type, data, real_len );
7888 if ( W_ERROR_IS_OK(status) )
7889 status = mod_a_printer(*printer, 2);
7893 free_a_printer(&printer, 2);
7898 /****************************************************************************
7899 ****************************************************************************/
7901 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7903 POLICY_HND *handle = &q_u->handle;
7904 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7907 DEBUG(5,("_spoolss_resetprinter\n"));
7910 * All we do is to check to see if the handle and queue is valid.
7911 * This call really doesn't mean anything to us because we only
7912 * support RAW printing. --jerry
7916 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7920 if (!get_printer_snum(p,handle, &snum))
7924 /* blindly return success */
7929 /****************************************************************************
7930 ****************************************************************************/
7932 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7934 POLICY_HND *handle = &q_u->handle;
7935 UNISTR2 *value = &q_u->valuename;
7937 NT_PRINTER_INFO_LEVEL *printer = NULL;
7939 WERROR status = WERR_OK;
7940 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7943 DEBUG(5,("spoolss_deleteprinterdata\n"));
7946 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7950 if (!get_printer_snum(p, handle, &snum))
7953 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7954 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7955 return WERR_ACCESS_DENIED;
7958 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7959 if (!W_ERROR_IS_OK(status))
7962 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7964 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7966 free_a_printer(&printer, 2);
7971 /****************************************************************************
7972 ****************************************************************************/
7974 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7976 POLICY_HND *handle = &q_u->handle;
7977 FORM *form = &q_u->form;
7978 nt_forms_struct tmpForm;
7980 WERROR status = WERR_OK;
7981 NT_PRINTER_INFO_LEVEL *printer = NULL;
7984 nt_forms_struct *list=NULL;
7985 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7987 DEBUG(5,("spoolss_addform\n"));
7990 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7995 /* forms can be added on printer of on the print server handle */
7997 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7999 if (!get_printer_snum(p,handle, &snum))
8002 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8003 if (!W_ERROR_IS_OK(status))
8007 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8008 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8009 status = WERR_ACCESS_DENIED;
8013 /* can't add if builtin */
8015 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8016 status = WERR_ALREADY_EXISTS;
8020 count = get_ntforms(&list);
8022 if(!add_a_form(&list, form, &count)) {
8023 status = WERR_NOMEM;
8027 write_ntforms(&list, count);
8030 * ChangeID must always be set if this is a printer
8033 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8034 status = mod_a_printer(*printer, 2);
8038 free_a_printer(&printer, 2);
8044 /****************************************************************************
8045 ****************************************************************************/
8047 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8049 POLICY_HND *handle = &q_u->handle;
8050 UNISTR2 *form_name = &q_u->name;
8051 nt_forms_struct tmpForm;
8053 nt_forms_struct *list=NULL;
8054 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8056 WERROR status = WERR_OK;
8057 NT_PRINTER_INFO_LEVEL *printer = NULL;
8059 DEBUG(5,("spoolss_deleteform\n"));
8062 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8066 /* forms can be deleted on printer of on the print server handle */
8068 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8070 if (!get_printer_snum(p,handle, &snum))
8073 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8074 if (!W_ERROR_IS_OK(status))
8078 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8079 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8080 status = WERR_ACCESS_DENIED;
8084 /* can't delete if builtin */
8086 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8087 status = WERR_INVALID_PARAM;
8091 count = get_ntforms(&list);
8093 if ( !delete_a_form(&list, form_name, &count, &status ))
8097 * ChangeID must always be set if this is a printer
8100 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8101 status = mod_a_printer(*printer, 2);
8105 free_a_printer(&printer, 2);
8111 /****************************************************************************
8112 ****************************************************************************/
8114 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8116 POLICY_HND *handle = &q_u->handle;
8117 FORM *form = &q_u->form;
8118 nt_forms_struct tmpForm;
8120 WERROR status = WERR_OK;
8121 NT_PRINTER_INFO_LEVEL *printer = NULL;
8124 nt_forms_struct *list=NULL;
8125 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8127 DEBUG(5,("spoolss_setform\n"));
8130 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8134 /* forms can be modified on printer of on the print server handle */
8136 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8138 if (!get_printer_snum(p,handle, &snum))
8141 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8142 if (!W_ERROR_IS_OK(status))
8146 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8147 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8148 status = WERR_ACCESS_DENIED;
8152 /* can't set if builtin */
8153 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8154 status = WERR_INVALID_PARAM;
8158 count = get_ntforms(&list);
8159 update_a_form(&list, form, count);
8160 write_ntforms(&list, count);
8163 * ChangeID must always be set if this is a printer
8166 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8167 status = mod_a_printer(*printer, 2);
8172 free_a_printer(&printer, 2);
8178 /****************************************************************************
8179 enumprintprocessors level 1.
8180 ****************************************************************************/
8182 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8184 PRINTPROCESSOR_1 *info_1=NULL;
8186 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8191 init_unistr(&info_1->name, "winprint");
8193 *needed += spoolss_size_printprocessor_info_1(info_1);
8195 if (!alloc_buffer_size(buffer, *needed))
8196 return WERR_INSUFFICIENT_BUFFER;
8198 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8202 if (*needed > offered) {
8204 return WERR_INSUFFICIENT_BUFFER;
8210 /****************************************************************************
8211 ****************************************************************************/
8213 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8215 uint32 level = q_u->level;
8216 NEW_BUFFER *buffer = NULL;
8217 uint32 offered = q_u->offered;
8218 uint32 *needed = &r_u->needed;
8219 uint32 *returned = &r_u->returned;
8221 /* that's an [in out] buffer */
8222 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8223 buffer = r_u->buffer;
8225 DEBUG(5,("spoolss_enumprintprocessors\n"));
8228 * Enumerate the print processors ...
8230 * Just reply with "winprint", to keep NT happy
8231 * and I can use my nice printer checker.
8239 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8241 return WERR_UNKNOWN_LEVEL;
8245 /****************************************************************************
8246 enumprintprocdatatypes level 1.
8247 ****************************************************************************/
8249 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8251 PRINTPROCDATATYPE_1 *info_1=NULL;
8253 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8258 init_unistr(&info_1->name, "RAW");
8260 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8262 if (!alloc_buffer_size(buffer, *needed))
8263 return WERR_INSUFFICIENT_BUFFER;
8265 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8269 if (*needed > offered) {
8271 return WERR_INSUFFICIENT_BUFFER;
8277 /****************************************************************************
8278 ****************************************************************************/
8280 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8282 uint32 level = q_u->level;
8283 NEW_BUFFER *buffer = NULL;
8284 uint32 offered = q_u->offered;
8285 uint32 *needed = &r_u->needed;
8286 uint32 *returned = &r_u->returned;
8288 /* that's an [in out] buffer */
8289 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8290 buffer = r_u->buffer;
8292 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8299 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8301 return WERR_UNKNOWN_LEVEL;
8305 /****************************************************************************
8306 enumprintmonitors level 1.
8307 ****************************************************************************/
8309 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8311 PRINTMONITOR_1 *info_1=NULL;
8313 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8318 init_unistr(&info_1->name, "Local Port");
8320 *needed += spoolss_size_printmonitor_info_1(info_1);
8322 if (!alloc_buffer_size(buffer, *needed))
8323 return WERR_INSUFFICIENT_BUFFER;
8325 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8329 if (*needed > offered) {
8331 return WERR_INSUFFICIENT_BUFFER;
8337 /****************************************************************************
8338 enumprintmonitors level 2.
8339 ****************************************************************************/
8341 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8343 PRINTMONITOR_2 *info_2=NULL;
8345 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8350 init_unistr(&info_2->name, "Local Port");
8351 init_unistr(&info_2->environment, "Windows NT X86");
8352 init_unistr(&info_2->dll_name, "localmon.dll");
8354 *needed += spoolss_size_printmonitor_info_2(info_2);
8356 if (!alloc_buffer_size(buffer, *needed))
8357 return WERR_INSUFFICIENT_BUFFER;
8359 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8363 if (*needed > offered) {
8365 return WERR_INSUFFICIENT_BUFFER;
8371 /****************************************************************************
8372 ****************************************************************************/
8374 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8376 uint32 level = q_u->level;
8377 NEW_BUFFER *buffer = NULL;
8378 uint32 offered = q_u->offered;
8379 uint32 *needed = &r_u->needed;
8380 uint32 *returned = &r_u->returned;
8382 /* that's an [in out] buffer */
8383 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8384 buffer = r_u->buffer;
8386 DEBUG(5,("spoolss_enumprintmonitors\n"));
8389 * Enumerate the print monitors ...
8391 * Just reply with "Local Port", to keep NT happy
8392 * and I can use my nice printer checker.
8400 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8402 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8404 return WERR_UNKNOWN_LEVEL;
8408 /****************************************************************************
8409 ****************************************************************************/
8411 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8415 JOB_INFO_1 *info_1=NULL;
8417 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8419 if (info_1 == NULL) {
8423 for (i=0; i<count && found==False; i++) {
8424 if (queue[i].job==(int)jobid)
8430 /* NT treats not found as bad param... yet another bad choice */
8431 return WERR_INVALID_PARAM;
8434 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8436 *needed += spoolss_size_job_info_1(info_1);
8438 if (!alloc_buffer_size(buffer, *needed)) {
8440 return WERR_INSUFFICIENT_BUFFER;
8443 smb_io_job_info_1("", buffer, info_1, 0);
8447 if (*needed > offered)
8448 return WERR_INSUFFICIENT_BUFFER;
8453 /****************************************************************************
8454 ****************************************************************************/
8456 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8461 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8463 DEVICEMODE *devmode = NULL;
8464 NT_DEVICEMODE *nt_devmode = NULL;
8466 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8468 ZERO_STRUCTP(info_2);
8470 if (info_2 == NULL) {
8475 for ( i=0; i<count && found==False; i++ )
8477 if (queue[i].job == (int)jobid)
8483 /* NT treats not found as bad param... yet another bad
8485 ret = WERR_INVALID_PARAM;
8489 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8490 if (!W_ERROR_IS_OK(ret))
8494 * if the print job does not have a DEVMODE associated with it,
8495 * just use the one for the printer. A NULL devicemode is not
8496 * a failure condition
8499 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8500 devmode = construct_dev_mode(snum);
8502 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8503 ZERO_STRUCTP( devmode );
8504 convert_nt_devicemode( devmode, nt_devmode );
8508 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8510 *needed += spoolss_size_job_info_2(info_2);
8512 if (!alloc_buffer_size(buffer, *needed)) {
8513 ret = WERR_INSUFFICIENT_BUFFER;
8517 smb_io_job_info_2("", buffer, info_2, 0);
8519 if (*needed > offered) {
8520 ret = WERR_INSUFFICIENT_BUFFER;
8527 /* Cleanup allocated memory */
8529 free_job_info_2(info_2); /* Also frees devmode */
8531 free_a_printer(&ntprinter, 2);
8536 /****************************************************************************
8537 ****************************************************************************/
8539 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8541 POLICY_HND *handle = &q_u->handle;
8542 uint32 jobid = q_u->jobid;
8543 uint32 level = q_u->level;
8544 NEW_BUFFER *buffer = NULL;
8545 uint32 offered = q_u->offered;
8546 uint32 *needed = &r_u->needed;
8547 WERROR wstatus = WERR_OK;
8551 print_queue_struct *queue = NULL;
8552 print_status_struct prt_status;
8554 /* that's an [in out] buffer */
8555 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8556 buffer = r_u->buffer;
8558 DEBUG(5,("spoolss_getjob\n"));
8562 if (!get_printer_snum(p, handle, &snum))
8565 count = print_queue_status(snum, &queue, &prt_status);
8567 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8568 count, prt_status.status, prt_status.message));
8572 wstatus = getjob_level_1(queue, count, snum, jobid,
8573 buffer, offered, needed);
8576 wstatus = getjob_level_2(queue, count, snum, jobid,
8577 buffer, offered, needed);
8580 wstatus = WERR_UNKNOWN_LEVEL;
8588 /********************************************************************
8589 spoolss_getprinterdataex
8591 From MSDN documentation of GetPrinterDataEx: pass request
8592 to GetPrinterData if key is "PrinterDriverData".
8593 ********************************************************************/
8595 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8597 POLICY_HND *handle = &q_u->handle;
8598 uint32 in_size = q_u->size;
8599 uint32 *type = &r_u->type;
8600 uint32 *out_size = &r_u->size;
8601 uint8 **data = &r_u->data;
8602 uint32 *needed = &r_u->needed;
8603 fstring keyname, valuename;
8605 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8607 NT_PRINTER_INFO_LEVEL *printer = NULL;
8609 WERROR status = WERR_OK;
8611 DEBUG(4,("_spoolss_getprinterdataex\n"));
8613 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8614 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8616 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8617 keyname, valuename));
8619 /* in case of problem, return some default values */
8623 *out_size = in_size;
8626 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8627 status = WERR_BADFID;
8631 /* Is the handle to a printer or to the server? */
8633 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8634 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8635 status = WERR_INVALID_PARAM;
8639 if ( !get_printer_snum(p,handle, &snum) )
8642 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8643 if ( !W_ERROR_IS_OK(status) )
8646 /* check to see if the keyname is valid */
8647 if ( !strlen(keyname) ) {
8648 status = WERR_INVALID_PARAM;
8652 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8653 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8654 free_a_printer( &printer, 2 );
8655 status = WERR_BADFILE;
8659 /* When given a new keyname, we should just create it */
8661 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8663 if (*needed > *out_size)
8664 status = WERR_MORE_DATA;
8667 if ( !W_ERROR_IS_OK(status) )
8669 DEBUG(5, ("error: allocating %d\n", *out_size));
8671 /* reply this param doesn't exist */
8675 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8676 status = WERR_NOMEM;
8686 free_a_printer( &printer, 2 );
8691 /********************************************************************
8692 * spoolss_setprinterdataex
8693 ********************************************************************/
8695 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8697 POLICY_HND *handle = &q_u->handle;
8698 uint32 type = q_u->type;
8699 uint8 *data = q_u->data;
8700 uint32 real_len = q_u->real_len;
8702 NT_PRINTER_INFO_LEVEL *printer = NULL;
8704 WERROR status = WERR_OK;
8705 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8710 DEBUG(4,("_spoolss_setprinterdataex\n"));
8712 /* From MSDN documentation of SetPrinterDataEx: pass request to
8713 SetPrinterData if key is "PrinterDriverData" */
8716 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8720 if ( !get_printer_snum(p,handle, &snum) )
8724 * Access check : NT returns "access denied" if you make a
8725 * SetPrinterData call without the necessary privildge.
8726 * we were originally returning OK if nothing changed
8727 * which made Win2k issue **a lot** of SetPrinterData
8728 * when connecting to a printer --jerry
8731 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8733 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8734 return WERR_ACCESS_DENIED;
8737 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8738 if (!W_ERROR_IS_OK(status))
8741 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8742 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8744 /* check for OID in valuename */
8746 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8752 /* save the registry data */
8754 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8756 if ( W_ERROR_IS_OK(status) )
8758 /* save the OID if one was specified */
8760 fstrcat( keyname, "\\" );
8761 fstrcat( keyname, SPOOL_OID_KEY );
8764 * I'm not checking the status here on purpose. Don't know
8765 * if this is right, but I'm returning the status from the
8766 * previous set_printer_dataex() call. I have no idea if
8767 * this is right. --jerry
8770 set_printer_dataex( printer, keyname, valuename,
8771 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8774 status = mod_a_printer(*printer, 2);
8777 free_a_printer(&printer, 2);
8783 /********************************************************************
8784 * spoolss_deleteprinterdataex
8785 ********************************************************************/
8787 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8789 POLICY_HND *handle = &q_u->handle;
8790 UNISTR2 *value = &q_u->valuename;
8791 UNISTR2 *key = &q_u->keyname;
8793 NT_PRINTER_INFO_LEVEL *printer = NULL;
8795 WERROR status = WERR_OK;
8796 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8797 pstring valuename, keyname;
8799 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8802 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8806 if (!get_printer_snum(p, handle, &snum))
8809 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8810 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8811 return WERR_ACCESS_DENIED;
8814 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8815 if (!W_ERROR_IS_OK(status))
8818 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8819 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8821 status = delete_printer_dataex( printer, keyname, valuename );
8823 free_a_printer(&printer, 2);
8828 /********************************************************************
8829 * spoolss_enumprinterkey
8830 ********************************************************************/
8833 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8836 fstring *keynames = NULL;
8837 uint16 *enumkeys = NULL;
8840 POLICY_HND *handle = &q_u->handle;
8841 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8842 NT_PRINTER_DATA *data;
8843 NT_PRINTER_INFO_LEVEL *printer = NULL;
8845 WERROR status = WERR_BADFILE;
8848 DEBUG(4,("_spoolss_enumprinterkey\n"));
8851 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8855 if ( !get_printer_snum(p,handle, &snum) )
8858 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8859 if (!W_ERROR_IS_OK(status))
8862 /* get the list of subkey names */
8864 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8865 data = &printer->info_2->data;
8867 num_keys = get_printer_subkeys( data, key, &keynames );
8869 if ( num_keys == -1 ) {
8870 status = WERR_BADFILE;
8874 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8876 r_u->needed = printerkey_len*2;
8878 if ( q_u->size < r_u->needed ) {
8879 status = WERR_MORE_DATA;
8883 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8884 status = WERR_NOMEM;
8890 if ( q_u->size < r_u->needed )
8891 status = WERR_MORE_DATA;
8894 free_a_printer( &printer, 2 );
8895 SAFE_FREE( keynames );
8900 /********************************************************************
8901 * spoolss_deleteprinterkey
8902 ********************************************************************/
8904 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8906 POLICY_HND *handle = &q_u->handle;
8907 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8909 NT_PRINTER_INFO_LEVEL *printer = NULL;
8913 DEBUG(5,("spoolss_deleteprinterkey\n"));
8916 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8920 /* if keyname == NULL, return error */
8922 if ( !q_u->keyname.buffer )
8923 return WERR_INVALID_PARAM;
8925 if (!get_printer_snum(p, handle, &snum))
8928 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8929 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8930 return WERR_ACCESS_DENIED;
8933 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8934 if (!W_ERROR_IS_OK(status))
8937 /* delete the key and all subneys */
8939 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8941 status = delete_all_printer_data( printer->info_2, key );
8943 if ( W_ERROR_IS_OK(status) )
8944 status = mod_a_printer(*printer, 2);
8946 free_a_printer( &printer, 2 );
8952 /********************************************************************
8953 * spoolss_enumprinterdataex
8954 ********************************************************************/
8956 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8958 POLICY_HND *handle = &q_u->handle;
8959 uint32 in_size = q_u->size;
8962 NT_PRINTER_INFO_LEVEL *printer = NULL;
8963 PRINTER_ENUM_VALUES *enum_values = NULL;
8964 NT_PRINTER_DATA *p_data;
8966 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8971 REGISTRY_VALUE *val;
8976 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8979 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8984 * first check for a keyname of NULL or "". Win2k seems to send
8985 * this a lot and we should send back WERR_INVALID_PARAM
8986 * no need to spend time looking up the printer in this case.
8990 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8991 if ( !strlen(key) ) {
8992 result = WERR_INVALID_PARAM;
8996 /* get the printer off of disk */
8998 if (!get_printer_snum(p,handle, &snum))
9001 ZERO_STRUCT(printer);
9002 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9003 if (!W_ERROR_IS_OK(result))
9006 /* now look for a match on the key name */
9008 p_data = &printer->info_2->data;
9010 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9011 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9013 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9014 result = WERR_INVALID_PARAM;
9021 /* allocate the memory for the array of pointers -- if necessary */
9023 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9026 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9028 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
9029 num_entries*sizeof(PRINTER_ENUM_VALUES)));
9030 result = WERR_NOMEM;
9034 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9038 * loop through all params and build the array to pass
9039 * back to the client
9042 for ( i=0; i<num_entries; i++ )
9044 /* lookup the registry value */
9046 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9047 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9051 value_name = regval_name( val );
9052 init_unistr( &enum_values[i].valuename, value_name );
9053 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9054 enum_values[i].type = regval_type( val );
9056 data_len = regval_size( val );
9058 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9060 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9062 result = WERR_NOMEM;
9066 enum_values[i].data_len = data_len;
9068 /* keep track of the size of the array in bytes */
9070 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9073 /* housekeeping information in the reply */
9075 r_u->needed = needed;
9076 r_u->returned = num_entries;
9078 if (needed > in_size) {
9079 result = WERR_MORE_DATA;
9083 /* copy data into the reply */
9085 r_u->ctr.size = r_u->needed;
9086 r_u->ctr.size_of_array = r_u->returned;
9087 r_u->ctr.values = enum_values;
9093 free_a_printer(&printer, 2);
9098 /****************************************************************************
9099 ****************************************************************************/
9101 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9103 init_unistr(&info->name, name);
9106 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9107 UNISTR2 *environment,
9114 pstring short_archi;
9115 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9117 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9119 if (get_short_archi(short_archi, long_archi)==False)
9120 return WERR_INVALID_ENVIRONMENT;
9122 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9125 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9127 fill_printprocessordirectory_1(info, path);
9129 *needed += spoolss_size_printprocessordirectory_info_1(info);
9131 if (!alloc_buffer_size(buffer, *needed)) {
9133 return WERR_INSUFFICIENT_BUFFER;
9136 smb_io_printprocessordirectory_1("", buffer, info, 0);
9140 if (*needed > offered)
9141 return WERR_INSUFFICIENT_BUFFER;
9146 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9148 uint32 level = q_u->level;
9149 NEW_BUFFER *buffer = NULL;
9150 uint32 offered = q_u->offered;
9151 uint32 *needed = &r_u->needed;
9154 /* that's an [in out] buffer */
9155 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9156 buffer = r_u->buffer;
9158 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9164 result = getprintprocessordirectory_level_1
9165 (&q_u->name, &q_u->environment, buffer, offered, needed);
9168 result = WERR_UNKNOWN_LEVEL;
9176 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9177 SPOOL_R_REPLYOPENPRINTER *r_u)
9179 DEBUG(5,("_spoolss_replyopenprinter\n"));
9181 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9186 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9187 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9189 DEBUG(5,("_spoolss_replycloseprinter\n"));