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, void *buf, size_t len )
1039 /* Unpack message */
1041 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1044 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
1045 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1048 tdb_unpack((char *)buf + offset, len - offset, "dd",
1049 &msg->notify.value[0], &msg->notify.value[1]);
1051 tdb_unpack((char *)buf + offset, len - offset, "B",
1052 &msg->len, &msg->notify.data);
1054 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1055 msg->type, msg->field, msg->flags));
1058 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1059 msg->notify.value[1]));
1061 dump_data(3, msg->notify.data, msg->len);
1066 /********************************************************************
1067 Receive a notify2 message list
1068 ********************************************************************/
1070 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1072 size_t msg_count, i;
1073 char *buf = (char *)msg;
1076 SPOOLSS_NOTIFY_MSG notify;
1077 SPOOLSS_NOTIFY_MSG_CTR messages;
1081 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1085 msg_count = IVAL(buf, 0);
1088 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1090 if (msg_count == 0) {
1091 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1095 /* initialize the container */
1097 ZERO_STRUCT( messages );
1098 notify_msg_ctr_init( &messages );
1101 * build message groups for each printer identified
1102 * in a change_notify msg. Remember that a PCN message
1103 * includes the handle returned for the srv_spoolss_replyopenprinter()
1104 * call. Therefore messages are grouped according to printer handle.
1107 for ( i=0; i<msg_count; i++ )
1109 if (msg_ptr + 4 - buf > len) {
1110 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1114 msg_len = IVAL(msg_ptr,0);
1117 if (msg_ptr + msg_len - buf > len) {
1118 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1122 /* unpack messages */
1124 ZERO_STRUCT( notify );
1125 notify2_unpack_msg( ¬ify, msg_ptr, msg_len );
1128 /* add to correct list in container */
1130 notify_msg_ctr_addmsg( &messages, ¬ify );
1132 /* free memory that might have been allocated by notify2_unpack_msg() */
1134 if ( notify.len != 0 )
1135 SAFE_FREE( notify.notify.data );
1138 /* process each group of messages */
1140 num_groups = notify_msg_ctr_numgroups( &messages );
1141 for ( i=0; i<num_groups; i++ )
1142 send_notify2_changes( &messages, i );
1147 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1149 notify_msg_ctr_destroy( &messages );
1154 /********************************************************************
1155 Send a message to ourself about new driver being installed
1156 so we can upgrade the information for each printer bound to this
1158 ********************************************************************/
1160 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1162 int len = strlen(drivername);
1167 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1170 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1175 /**********************************************************************
1176 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1177 over all printers, upgrading ones as neessary
1178 **********************************************************************/
1180 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1184 int n_services = lp_numservices();
1186 len = MIN(len,sizeof(drivername)-1);
1187 strncpy(drivername, buf, len);
1189 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1191 /* Iterate the printer list */
1193 for (snum=0; snum<n_services; snum++)
1195 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1198 NT_PRINTER_INFO_LEVEL *printer = NULL;
1200 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1201 if (!W_ERROR_IS_OK(result))
1204 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1206 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1208 /* all we care about currently is the change_id */
1210 result = mod_a_printer(*printer, 2);
1211 if (!W_ERROR_IS_OK(result)) {
1212 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1213 dos_errstr(result)));
1217 free_a_printer(&printer, 2);
1224 /********************************************************************
1225 Update the cahce for all printq's with a registered client
1227 ********************************************************************/
1229 void update_monitored_printq_cache( void )
1231 Printer_entry *printer = printers_list;
1234 /* loop through all printers and update the cache where
1235 client_connected == True */
1238 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1239 && printer->notify.client_connected )
1241 snum = print_queue_snum(printer->dev.handlename);
1242 print_queue_status( snum, NULL, NULL );
1245 printer = printer->next;
1250 /********************************************************************
1251 Send a message to ourself about new driver being installed
1252 so we can upgrade the information for each printer bound to this
1254 ********************************************************************/
1256 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1258 int len = strlen(drivername);
1263 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1266 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1271 /**********************************************************************
1272 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1273 over all printers, resetting printer data as neessary
1274 **********************************************************************/
1276 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1280 int n_services = lp_numservices();
1282 len = MIN( len, sizeof(drivername)-1 );
1283 strncpy( drivername, buf, len );
1285 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1287 /* Iterate the printer list */
1289 for ( snum=0; snum<n_services; snum++ )
1291 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1294 NT_PRINTER_INFO_LEVEL *printer = NULL;
1296 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1297 if ( !W_ERROR_IS_OK(result) )
1301 * if the printer is bound to the driver,
1302 * then reset to the new driver initdata
1305 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1307 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1309 if ( !set_driver_init(printer, 2) ) {
1310 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1311 printer->info_2->printername, printer->info_2->drivername));
1314 result = mod_a_printer( *printer, 2 );
1315 if ( !W_ERROR_IS_OK(result) ) {
1316 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1317 get_dos_error_msg(result)));
1321 free_a_printer( &printer, 2 );
1330 /********************************************************************
1331 Copy routines used by convert_to_openprinterex()
1332 *******************************************************************/
1334 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1342 DEBUG (8,("dup_devmode\n"));
1344 /* bulk copy first */
1346 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1350 /* dup the pointer members separately */
1352 len = unistrlen(devmode->devicename.buffer);
1354 d->devicename.buffer = talloc(ctx, len*2);
1355 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1360 len = unistrlen(devmode->formname.buffer);
1362 d->devicename.buffer = talloc(ctx, len*2);
1363 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1367 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1372 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1374 if (!new_ctr || !ctr)
1377 DEBUG(8,("copy_devmode_ctr\n"));
1379 new_ctr->size = ctr->size;
1380 new_ctr->devmode_ptr = ctr->devmode_ptr;
1382 if(ctr->devmode_ptr)
1383 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1386 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1388 if (!new_def || !def)
1391 DEBUG(8,("copy_printer_defaults\n"));
1393 new_def->datatype_ptr = def->datatype_ptr;
1395 if (def->datatype_ptr)
1396 copy_unistr2(&new_def->datatype, &def->datatype);
1398 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1400 new_def->access_required = def->access_required;
1403 /********************************************************************
1404 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1405 * SPOOL_Q_OPEN_PRINTER_EX structure
1406 ********************************************************************/
1408 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1410 if (!q_u_ex || !q_u)
1413 DEBUG(8,("convert_to_openprinterex\n"));
1415 q_u_ex->printername_ptr = q_u->printername_ptr;
1417 if (q_u->printername_ptr)
1418 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1420 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1423 /********************************************************************
1424 * spoolss_open_printer
1426 * called from the spoolss dispatcher
1427 ********************************************************************/
1429 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1431 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1432 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1437 ZERO_STRUCT(q_u_ex);
1438 ZERO_STRUCT(r_u_ex);
1440 /* convert the OpenPrinter() call to OpenPrinterEx() */
1442 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1444 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1446 /* convert back to OpenPrinter() */
1448 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1453 /********************************************************************
1454 * spoolss_open_printer
1456 * If the openprinterex rpc call contains a devmode,
1457 * it's a per-user one. This per-user devmode is derivated
1458 * from the global devmode. Openprinterex() contains a per-user
1459 * devmode for when you do EMF printing and spooling.
1460 * In the EMF case, the NT workstation is only doing half the job
1461 * of rendering the page. The other half is done by running the printer
1462 * driver on the server.
1463 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1464 * The EMF file only contains what is to be printed on the page.
1465 * So in order for the server to know how to print, the NT client sends
1466 * a devicemode attached to the openprinterex call.
1467 * But this devicemode is short lived, it's only valid for the current print job.
1469 * If Samba would have supported EMF spooling, this devicemode would
1470 * have been attached to the handle, to sent it to the driver to correctly
1471 * rasterize the EMF file.
1473 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1474 * we just act as a pass-thru between windows and the printer.
1476 * In order to know that Samba supports only RAW spooling, NT has to call
1477 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1478 * and until NT sends a RAW job, we refuse it.
1480 * But to call getprinter() or startdoc(), you first need a valid handle,
1481 * and to get an handle you have to call openprintex(). Hence why you have
1482 * a devicemode in the openprinterex() call.
1485 * Differences between NT4 and NT 2000.
1488 * On NT4, you only have a global devicemode. This global devicemode can be changed
1489 * by the administrator (or by a user with enough privs). Everytime a user
1490 * wants to print, the devicemode is resetted to the default. In Word, everytime
1491 * you print, the printer's characteristics are always reset to the global devicemode.
1495 * In W2K, there is the notion of per-user devicemode. The first time you use
1496 * a printer, a per-user devicemode is build from the global devicemode.
1497 * If you change your per-user devicemode, it is saved in the registry, under the
1498 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1499 * printer preferences available.
1501 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1502 * on the General Tab of the printer properties windows.
1504 * To change the global devicemode: it's the "Printing Defaults..." button
1505 * on the Advanced Tab of the printer properties window.
1508 ********************************************************************/
1510 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1512 UNISTR2 *printername = NULL;
1513 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1514 POLICY_HND *handle = &r_u->handle;
1518 struct current_user user;
1519 Printer_entry *Printer=NULL;
1521 if (q_u->printername_ptr != 0)
1522 printername = &q_u->printername;
1524 if (printername == NULL)
1525 return WERR_INVALID_PRINTER_NAME;
1527 /* some sanity check because you can open a printer or a print server */
1528 /* aka: \\server\printer or \\server */
1529 unistr2_to_ascii(name, printername, sizeof(name)-1);
1531 DEBUGADD(3,("checking name: %s\n",name));
1533 if (!open_printer_hnd(p, handle, name, 0))
1534 return WERR_INVALID_PRINTER_NAME;
1536 Printer=find_printer_index_by_hnd(p, handle);
1538 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1539 Can't find printer handle we created for printer %s\n", name ));
1540 close_printer_handle(p,handle);
1541 return WERR_INVALID_PRINTER_NAME;
1544 get_current_user(&user, p);
1547 * First case: the user is opening the print server:
1549 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1550 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1552 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1553 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1554 * or if the user is listed in the smb.conf printer admin parameter.
1556 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1557 * client view printer folder, but does not show the MSAPW.
1559 * Note: this test needs code to check access rights here too. Jeremy
1560 * could you look at this?
1562 * Second case: the user is opening a printer:
1563 * NT doesn't let us connect to a printer if the connecting user
1564 * doesn't have print permission.
1567 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1569 /* Printserver handles use global struct... */
1573 /* Map standard access rights to object specific access rights */
1575 se_map_standard(&printer_default->access_required,
1576 &printserver_std_mapping);
1578 /* Deny any object specific bits that don't apply to print
1579 servers (i.e printer and job specific bits) */
1581 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1583 if (printer_default->access_required &
1584 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1585 DEBUG(3, ("access DENIED for non-printserver bits"));
1586 close_printer_handle(p, handle);
1587 return WERR_ACCESS_DENIED;
1590 /* Allow admin access */
1592 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1594 if (!lp_ms_add_printer_wizard()) {
1595 close_printer_handle(p, handle);
1596 return WERR_ACCESS_DENIED;
1599 /* if the user is not root and not a printer admin, then fail */
1602 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1604 close_printer_handle(p, handle);
1605 return WERR_ACCESS_DENIED;
1608 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1612 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1615 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1616 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1618 /* We fall through to return WERR_OK */
1623 /* NT doesn't let us connect to a printer if the connecting user
1624 doesn't have print permission. */
1626 if (!get_printer_snum(p, handle, &snum))
1629 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1631 /* map an empty access mask to the minimum access mask */
1632 if (printer_default->access_required == 0x0)
1633 printer_default->access_required = PRINTER_ACCESS_USE;
1636 * If we are not serving the printer driver for this printer,
1637 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1638 * will keep NT clients happy --jerry
1641 if (lp_use_client_driver(snum)
1642 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1644 printer_default->access_required = PRINTER_ACCESS_USE;
1647 /* check smb.conf parameters and the the sec_desc */
1649 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1650 DEBUG(3, ("access DENIED for printer open\n"));
1651 close_printer_handle(p, handle);
1652 return WERR_ACCESS_DENIED;
1655 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1656 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1657 close_printer_handle(p, handle);
1658 return WERR_ACCESS_DENIED;
1661 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1662 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1664 printer_default->access_required = PRINTER_ACCESS_USE;
1666 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1667 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1671 Printer->access_granted = printer_default->access_required;
1674 * If the client sent a devmode in the OpenPrinter() call, then
1675 * save it here in case we get a job submission on this handle
1678 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1679 && q_u->printer_default.devmode_cont.devmode_ptr )
1681 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1682 &Printer->nt_devmode );
1685 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1686 optimization in Windows 2000 clients --jerry */
1688 if ( RA_WIN2K == get_remote_arch() )
1694 /****************************************************************************
1695 ****************************************************************************/
1697 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1698 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1704 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1713 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1714 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1720 printer->info_3=NULL;
1721 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1725 printer->info_6=NULL;
1726 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1736 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1737 NT_DEVICEMODE **pp_nt_devmode)
1739 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1742 * Ensure nt_devmode is a valid pointer
1743 * as we will be overwriting it.
1746 if (nt_devmode == NULL) {
1747 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1748 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1752 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1753 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1755 nt_devmode->specversion=devmode->specversion;
1756 nt_devmode->driverversion=devmode->driverversion;
1757 nt_devmode->size=devmode->size;
1758 nt_devmode->fields=devmode->fields;
1759 nt_devmode->orientation=devmode->orientation;
1760 nt_devmode->papersize=devmode->papersize;
1761 nt_devmode->paperlength=devmode->paperlength;
1762 nt_devmode->paperwidth=devmode->paperwidth;
1763 nt_devmode->scale=devmode->scale;
1764 nt_devmode->copies=devmode->copies;
1765 nt_devmode->defaultsource=devmode->defaultsource;
1766 nt_devmode->printquality=devmode->printquality;
1767 nt_devmode->color=devmode->color;
1768 nt_devmode->duplex=devmode->duplex;
1769 nt_devmode->yresolution=devmode->yresolution;
1770 nt_devmode->ttoption=devmode->ttoption;
1771 nt_devmode->collate=devmode->collate;
1773 nt_devmode->logpixels=devmode->logpixels;
1774 nt_devmode->bitsperpel=devmode->bitsperpel;
1775 nt_devmode->pelswidth=devmode->pelswidth;
1776 nt_devmode->pelsheight=devmode->pelsheight;
1777 nt_devmode->displayflags=devmode->displayflags;
1778 nt_devmode->displayfrequency=devmode->displayfrequency;
1779 nt_devmode->icmmethod=devmode->icmmethod;
1780 nt_devmode->icmintent=devmode->icmintent;
1781 nt_devmode->mediatype=devmode->mediatype;
1782 nt_devmode->dithertype=devmode->dithertype;
1783 nt_devmode->reserved1=devmode->reserved1;
1784 nt_devmode->reserved2=devmode->reserved2;
1785 nt_devmode->panningwidth=devmode->panningwidth;
1786 nt_devmode->panningheight=devmode->panningheight;
1789 * Only change private and driverextra if the incoming devmode
1790 * has a new one. JRA.
1793 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1794 SAFE_FREE(nt_devmode->private);
1795 nt_devmode->driverextra=devmode->driverextra;
1796 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1798 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1801 *pp_nt_devmode = nt_devmode;
1806 /********************************************************************
1807 * _spoolss_enddocprinter_internal.
1808 ********************************************************************/
1810 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1812 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1816 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1820 if (!get_printer_snum(p, handle, &snum))
1823 Printer->document_started=False;
1824 print_job_end(snum, Printer->jobid,True);
1825 /* error codes unhandled so far ... */
1830 /********************************************************************
1831 * api_spoolss_closeprinter
1832 ********************************************************************/
1834 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1836 POLICY_HND *handle = &q_u->handle;
1838 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1840 if (Printer && Printer->document_started)
1841 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1843 if (!close_printer_handle(p, handle))
1846 /* clear the returned printer handle. Observed behavior
1847 from Win2k server. Don't think this really matters.
1848 Previous code just copied the value of the closed
1851 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1856 /********************************************************************
1857 * api_spoolss_deleteprinter
1859 ********************************************************************/
1861 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1863 POLICY_HND *handle = &q_u->handle;
1864 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1867 if (Printer && Printer->document_started)
1868 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1870 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1872 result = delete_printer_handle(p, handle);
1874 update_c_setprinter(False);
1879 /*******************************************************************
1880 * static function to lookup the version id corresponding to an
1881 * long architecture string
1882 ******************************************************************/
1884 static int get_version_id (char * arch)
1887 struct table_node archi_table[]= {
1889 {"Windows 4.0", "WIN40", 0 },
1890 {"Windows NT x86", "W32X86", 2 },
1891 {"Windows NT R4000", "W32MIPS", 2 },
1892 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1893 {"Windows NT PowerPC", "W32PPC", 2 },
1897 for (i=0; archi_table[i].long_archi != NULL; i++)
1899 if (strcmp(arch, archi_table[i].long_archi) == 0)
1900 return (archi_table[i].version);
1906 /********************************************************************
1907 * _spoolss_deleteprinterdriver
1908 ********************************************************************/
1910 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1914 NT_PRINTER_DRIVER_INFO_LEVEL info;
1915 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1917 struct current_user user;
1919 WERROR status_win2k = WERR_ACCESS_DENIED;
1921 get_current_user(&user, p);
1923 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1924 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1926 /* check that we have a valid driver name first */
1928 if ((version=get_version_id(arch)) == -1)
1929 return WERR_INVALID_ENVIRONMENT;
1932 ZERO_STRUCT(info_win2k);
1934 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1936 /* try for Win2k driver if "Windows NT x86" */
1938 if ( version == 2 ) {
1940 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1941 status = WERR_UNKNOWN_PRINTER_DRIVER;
1945 /* otherwise it was a failure */
1947 status = WERR_UNKNOWN_PRINTER_DRIVER;
1953 if (printer_driver_in_use(info.info_3)) {
1954 status = WERR_PRINTER_DRIVER_IN_USE;
1960 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1962 /* if we get to here, we now have 2 driver info structures to remove */
1963 /* remove the Win2k driver first*/
1965 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1966 free_a_printer_driver( info_win2k, 3 );
1968 /* this should not have failed---if it did, report to client */
1969 if ( !W_ERROR_IS_OK(status_win2k) )
1974 status = delete_printer_driver(info.info_3, &user, version, False);
1976 /* if at least one of the deletes succeeded return OK */
1978 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1982 free_a_printer_driver( info, 3 );
1987 /********************************************************************
1988 * spoolss_deleteprinterdriverex
1989 ********************************************************************/
1991 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1995 NT_PRINTER_DRIVER_INFO_LEVEL info;
1996 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1998 uint32 flags = q_u->delete_flags;
2000 struct current_user user;
2002 WERROR status_win2k = WERR_ACCESS_DENIED;
2004 get_current_user(&user, p);
2006 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2007 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2009 /* check that we have a valid driver name first */
2010 if ((version=get_version_id(arch)) == -1) {
2011 /* this is what NT returns */
2012 return WERR_INVALID_ENVIRONMENT;
2015 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2016 version = q_u->version;
2019 ZERO_STRUCT(info_win2k);
2021 status = get_a_printer_driver(&info, 3, driver, arch, version);
2023 if ( !W_ERROR_IS_OK(status) )
2026 * if the client asked for a specific version,
2027 * or this is something other than Windows NT x86,
2031 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2034 /* try for Win2k driver if "Windows NT x86" */
2037 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2038 status = WERR_UNKNOWN_PRINTER_DRIVER;
2043 if ( printer_driver_in_use(info.info_3) ) {
2044 status = WERR_PRINTER_DRIVER_IN_USE;
2049 * we have a couple of cases to consider.
2050 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2051 * then the delete should fail if **any** files overlap with
2053 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2054 * non-overlapping files
2055 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2056 * is set, the do not delete any files
2057 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2060 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2062 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2064 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2065 /* no idea of the correct error here */
2066 status = WERR_ACCESS_DENIED;
2071 /* also check for W32X86/3 if necessary; maybe we already have? */
2073 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2074 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2077 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2078 /* no idea of the correct error here */
2079 free_a_printer_driver( info_win2k, 3 );
2080 status = WERR_ACCESS_DENIED;
2084 /* if we get to here, we now have 2 driver info structures to remove */
2085 /* remove the Win2k driver first*/
2087 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2088 free_a_printer_driver( info_win2k, 3 );
2090 /* this should not have failed---if it did, report to client */
2092 if ( !W_ERROR_IS_OK(status_win2k) )
2097 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2099 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2102 free_a_printer_driver( info, 3 );
2108 /****************************************************************************
2109 Internal routine for retreiving printerdata
2110 ***************************************************************************/
2112 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2113 const char *key, const char *value, uint32 *type, uint8 **data,
2114 uint32 *needed, uint32 in_size )
2116 REGISTRY_VALUE *val;
2119 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2120 return WERR_BADFILE;
2122 *type = regval_type( val );
2124 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2126 size = regval_size( val );
2128 /* copy the min(in_size, len) */
2131 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2133 /* special case for 0 length values */
2135 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2139 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2148 DEBUG(5,("get_printer_dataex: copy done\n"));
2153 /****************************************************************************
2154 Internal routine for removing printerdata
2155 ***************************************************************************/
2157 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2159 return delete_printer_data( printer->info_2, key, value );
2162 /****************************************************************************
2163 Internal routine for storing printerdata
2164 ***************************************************************************/
2166 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2167 uint32 type, uint8 *data, int real_len )
2169 delete_printer_data( printer->info_2, key, value );
2171 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2174 /********************************************************************
2175 GetPrinterData on a printer server Handle.
2176 ********************************************************************/
2178 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2182 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2184 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2186 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2192 if (!StrCaseCmp(value, "BeepEnabled")) {
2194 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2196 SIVAL(*data, 0, 0x00);
2201 if (!StrCaseCmp(value, "EventLog")) {
2203 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2205 /* formally was 0x1b */
2206 SIVAL(*data, 0, 0x0);
2211 if (!StrCaseCmp(value, "NetPopup")) {
2213 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2215 SIVAL(*data, 0, 0x00);
2220 if (!StrCaseCmp(value, "MajorVersion")) {
2222 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2229 if (!StrCaseCmp(value, "MinorVersion")) {
2231 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2240 * uint32 size = 0x114
2242 * uint32 minor = [0|1]
2243 * uint32 build = [2195|2600]
2244 * extra unicode string = e.g. "Service Pack 3"
2246 if (!StrCaseCmp(value, "OSVersion")) {
2248 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2256 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2259 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2261 *needed = 2*(strlen(string)+1);
2262 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2264 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2266 /* it's done by hand ready to go on the wire */
2267 for (i=0; i<strlen(string); i++) {
2268 (*data)[2*i]=string[i];
2269 (*data)[2*i+1]='\0';
2274 if (!StrCaseCmp(value, "Architecture")) {
2275 pstring string="Windows NT x86";
2277 *needed = 2*(strlen(string)+1);
2278 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2280 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2281 for (i=0; i<strlen(string); i++) {
2282 (*data)[2*i]=string[i];
2283 (*data)[2*i+1]='\0';
2288 if (!StrCaseCmp(value, "DsPresent")) {
2290 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2292 SIVAL(*data, 0, 0x01);
2297 if (!StrCaseCmp(value, "DNSMachineName")) {
2300 if (!get_myfullname(hostname))
2301 return WERR_BADFILE;
2303 *needed = 2*(strlen(hostname)+1);
2304 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2306 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2307 for (i=0; i<strlen(hostname); i++) {
2308 (*data)[2*i]=hostname[i];
2309 (*data)[2*i+1]='\0';
2315 return WERR_BADFILE;
2318 /********************************************************************
2319 * spoolss_getprinterdata
2320 ********************************************************************/
2322 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2324 POLICY_HND *handle = &q_u->handle;
2325 UNISTR2 *valuename = &q_u->valuename;
2326 uint32 in_size = q_u->size;
2327 uint32 *type = &r_u->type;
2328 uint32 *out_size = &r_u->size;
2329 uint8 **data = &r_u->data;
2330 uint32 *needed = &r_u->needed;
2333 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2334 NT_PRINTER_INFO_LEVEL *printer = NULL;
2338 * Reminder: when it's a string, the length is in BYTES
2339 * even if UNICODE is negociated.
2344 *out_size = in_size;
2346 /* in case of problem, return some default values */
2351 DEBUG(4,("_spoolss_getprinterdata\n"));
2354 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2355 status = WERR_BADFID;
2359 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2361 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2362 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2365 if ( !get_printer_snum(p,handle, &snum) ) {
2366 status = WERR_BADFID;
2370 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2371 if ( !W_ERROR_IS_OK(status) )
2374 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2376 if ( strequal(value, "ChangeId") ) {
2378 *needed = sizeof(uint32);
2379 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2380 status = WERR_NOMEM;
2383 **data = printer->info_2->changeid;
2387 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2390 if (*needed > *out_size)
2391 status = WERR_MORE_DATA;
2394 if ( !W_ERROR_IS_OK(status) )
2396 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2398 /* reply this param doesn't exist */
2401 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2403 free_a_printer( &printer, 2 );
2412 /* cleanup & exit */
2415 free_a_printer( &printer, 2 );
2420 /*********************************************************
2421 Connect to the client machine.
2422 **********************************************************/
2424 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, const char *remote_machine)
2426 ZERO_STRUCTP(the_cli);
2427 if(cli_initialise(the_cli) == NULL) {
2428 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2432 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2433 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2434 cli_shutdown(the_cli);
2438 if (ismyip(the_cli->dest_ip)) {
2439 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2440 cli_shutdown(the_cli);
2444 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2445 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2446 cli_shutdown(the_cli);
2450 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2451 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2453 cli_shutdown(the_cli);
2457 the_cli->protocol = PROTOCOL_NT1;
2459 if (!cli_negprot(the_cli)) {
2460 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2461 cli_shutdown(the_cli);
2465 if (the_cli->protocol != PROTOCOL_NT1) {
2466 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2467 cli_shutdown(the_cli);
2472 * Do an anonymous session setup.
2475 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2476 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2477 cli_shutdown(the_cli);
2481 if (!(the_cli->sec_mode & 1)) {
2482 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2483 cli_shutdown(the_cli);
2487 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2488 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2489 cli_shutdown(the_cli);
2494 * Ok - we have an anonymous connection to the IPC$ share.
2495 * Now start the NT Domain stuff :-).
2498 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2499 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)));
2500 cli_nt_session_close(the_cli);
2501 cli_ulogoff(the_cli);
2502 cli_shutdown(the_cli);
2509 /***************************************************************************
2510 Connect to the client.
2511 ****************************************************************************/
2513 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2518 * If it's the first connection, contact the client
2519 * and connect to the IPC$ share anonumously
2521 if (smb_connections==0) {
2522 fstring unix_printer;
2524 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2526 if(!spoolss_connect_to_client(¬ify_cli, unix_printer))
2529 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2530 /* Tell the connections db we're now interested in printer
2531 * notify messages. */
2532 register_message_flags( True, FLAG_MSG_PRINTING );
2536 * Tell the specific printing tdb we want messages for this printer
2537 * by registering our PID.
2540 if (!print_notify_register_pid(snum))
2541 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2545 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2548 if (!W_ERROR_IS_OK(result))
2549 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2550 dos_errstr(result)));
2552 return (W_ERROR_IS_OK(result));
2555 /********************************************************************
2557 * ReplyFindFirstPrinterChangeNotifyEx
2559 * before replying OK: status=0 a rpc call is made to the workstation
2560 * asking ReplyOpenPrinter
2562 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2563 * called from api_spoolss_rffpcnex
2564 ********************************************************************/
2566 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2568 POLICY_HND *handle = &q_u->handle;
2569 uint32 flags = q_u->flags;
2570 uint32 options = q_u->options;
2571 UNISTR2 *localmachine = &q_u->localmachine;
2572 uint32 printerlocal = q_u->printerlocal;
2574 SPOOL_NOTIFY_OPTION *option = q_u->option;
2576 /* store the notify value in the printer struct */
2578 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2581 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2585 Printer->notify.flags=flags;
2586 Printer->notify.options=options;
2587 Printer->notify.printerlocal=printerlocal;
2589 if (Printer->notify.option)
2590 free_spool_notify_option(&Printer->notify.option);
2592 Printer->notify.option=dup_spool_notify_option(option);
2594 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2595 sizeof(Printer->notify.localmachine)-1);
2597 /* Connect to the client machine and send a ReplyOpenPrinter */
2599 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2601 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2602 !get_printer_snum(p, handle, &snum) )
2605 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2606 Printer->notify.printerlocal, 1,
2607 &Printer->notify.client_hnd))
2608 return WERR_SERVER_UNAVAILABLE;
2610 Printer->notify.client_connected=True;
2615 /*******************************************************************
2616 * fill a notify_info_data with the servername
2617 ********************************************************************/
2619 void spoolss_notify_server_name(int snum,
2620 SPOOL_NOTIFY_INFO_DATA *data,
2621 print_queue_struct *queue,
2622 NT_PRINTER_INFO_LEVEL *printer,
2623 TALLOC_CTX *mem_ctx)
2625 pstring temp_name, temp;
2628 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2630 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2632 data->notify_data.data.length = len;
2633 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2635 if (!data->notify_data.data.string) {
2636 data->notify_data.data.length = 0;
2640 memcpy(data->notify_data.data.string, temp, len);
2643 /*******************************************************************
2644 * fill a notify_info_data with the printername (not including the servername).
2645 ********************************************************************/
2647 void spoolss_notify_printer_name(int snum,
2648 SPOOL_NOTIFY_INFO_DATA *data,
2649 print_queue_struct *queue,
2650 NT_PRINTER_INFO_LEVEL *printer,
2651 TALLOC_CTX *mem_ctx)
2656 /* the notify name should not contain the \\server\ part */
2657 char *p = strrchr(printer->info_2->printername, '\\');
2660 p = printer->info_2->printername;
2665 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2667 data->notify_data.data.length = len;
2668 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2670 if (!data->notify_data.data.string) {
2671 data->notify_data.data.length = 0;
2675 memcpy(data->notify_data.data.string, temp, len);
2678 /*******************************************************************
2679 * fill a notify_info_data with the servicename
2680 ********************************************************************/
2682 void spoolss_notify_share_name(int snum,
2683 SPOOL_NOTIFY_INFO_DATA *data,
2684 print_queue_struct *queue,
2685 NT_PRINTER_INFO_LEVEL *printer,
2686 TALLOC_CTX *mem_ctx)
2691 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2693 data->notify_data.data.length = len;
2694 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2696 if (!data->notify_data.data.string) {
2697 data->notify_data.data.length = 0;
2701 memcpy(data->notify_data.data.string, temp, len);
2704 /*******************************************************************
2705 * fill a notify_info_data with the port name
2706 ********************************************************************/
2708 void spoolss_notify_port_name(int snum,
2709 SPOOL_NOTIFY_INFO_DATA *data,
2710 print_queue_struct *queue,
2711 NT_PRINTER_INFO_LEVEL *printer,
2712 TALLOC_CTX *mem_ctx)
2717 /* even if it's strange, that's consistant in all the code */
2719 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2721 data->notify_data.data.length = len;
2722 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2724 if (!data->notify_data.data.string) {
2725 data->notify_data.data.length = 0;
2729 memcpy(data->notify_data.data.string, temp, len);
2732 /*******************************************************************
2733 * fill a notify_info_data with the printername
2734 * but it doesn't exist, have to see what to do
2735 ********************************************************************/
2737 void spoolss_notify_driver_name(int snum,
2738 SPOOL_NOTIFY_INFO_DATA *data,
2739 print_queue_struct *queue,
2740 NT_PRINTER_INFO_LEVEL *printer,
2741 TALLOC_CTX *mem_ctx)
2746 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2748 data->notify_data.data.length = len;
2749 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2751 if (!data->notify_data.data.string) {
2752 data->notify_data.data.length = 0;
2756 memcpy(data->notify_data.data.string, temp, len);
2759 /*******************************************************************
2760 * fill a notify_info_data with the comment
2761 ********************************************************************/
2763 void spoolss_notify_comment(int snum,
2764 SPOOL_NOTIFY_INFO_DATA *data,
2765 print_queue_struct *queue,
2766 NT_PRINTER_INFO_LEVEL *printer,
2767 TALLOC_CTX *mem_ctx)
2772 if (*printer->info_2->comment == '\0')
2773 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2775 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2777 data->notify_data.data.length = len;
2778 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2780 if (!data->notify_data.data.string) {
2781 data->notify_data.data.length = 0;
2785 memcpy(data->notify_data.data.string, temp, len);
2788 /*******************************************************************
2789 * fill a notify_info_data with the comment
2790 * location = "Room 1, floor 2, building 3"
2791 ********************************************************************/
2793 void spoolss_notify_location(int snum,
2794 SPOOL_NOTIFY_INFO_DATA *data,
2795 print_queue_struct *queue,
2796 NT_PRINTER_INFO_LEVEL *printer,
2797 TALLOC_CTX *mem_ctx)
2802 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2804 data->notify_data.data.length = len;
2805 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2807 if (!data->notify_data.data.string) {
2808 data->notify_data.data.length = 0;
2812 memcpy(data->notify_data.data.string, temp, len);
2815 /*******************************************************************
2816 * fill a notify_info_data with the device mode
2817 * jfm:xxxx don't to it for know but that's a real problem !!!
2818 ********************************************************************/
2820 static void spoolss_notify_devmode(int snum,
2821 SPOOL_NOTIFY_INFO_DATA *data,
2822 print_queue_struct *queue,
2823 NT_PRINTER_INFO_LEVEL *printer,
2824 TALLOC_CTX *mem_ctx)
2828 /*******************************************************************
2829 * fill a notify_info_data with the separator file name
2830 ********************************************************************/
2832 void spoolss_notify_sepfile(int snum,
2833 SPOOL_NOTIFY_INFO_DATA *data,
2834 print_queue_struct *queue,
2835 NT_PRINTER_INFO_LEVEL *printer,
2836 TALLOC_CTX *mem_ctx)
2841 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2843 data->notify_data.data.length = len;
2844 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2846 if (!data->notify_data.data.string) {
2847 data->notify_data.data.length = 0;
2851 memcpy(data->notify_data.data.string, temp, len);
2854 /*******************************************************************
2855 * fill a notify_info_data with the print processor
2856 * jfm:xxxx return always winprint to indicate we don't do anything to it
2857 ********************************************************************/
2859 void spoolss_notify_print_processor(int snum,
2860 SPOOL_NOTIFY_INFO_DATA *data,
2861 print_queue_struct *queue,
2862 NT_PRINTER_INFO_LEVEL *printer,
2863 TALLOC_CTX *mem_ctx)
2868 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2870 data->notify_data.data.length = len;
2871 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2873 if (!data->notify_data.data.string) {
2874 data->notify_data.data.length = 0;
2878 memcpy(data->notify_data.data.string, temp, len);
2881 /*******************************************************************
2882 * fill a notify_info_data with the print processor options
2883 * jfm:xxxx send an empty string
2884 ********************************************************************/
2886 void spoolss_notify_parameters(int snum,
2887 SPOOL_NOTIFY_INFO_DATA *data,
2888 print_queue_struct *queue,
2889 NT_PRINTER_INFO_LEVEL *printer,
2890 TALLOC_CTX *mem_ctx)
2895 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2897 data->notify_data.data.length = len;
2898 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2900 if (!data->notify_data.data.string) {
2901 data->notify_data.data.length = 0;
2905 memcpy(data->notify_data.data.string, temp, len);
2908 /*******************************************************************
2909 * fill a notify_info_data with the data type
2910 * jfm:xxxx always send RAW as data type
2911 ********************************************************************/
2913 void spoolss_notify_datatype(int snum,
2914 SPOOL_NOTIFY_INFO_DATA *data,
2915 print_queue_struct *queue,
2916 NT_PRINTER_INFO_LEVEL *printer,
2917 TALLOC_CTX *mem_ctx)
2922 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2924 data->notify_data.data.length = len;
2925 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2927 if (!data->notify_data.data.string) {
2928 data->notify_data.data.length = 0;
2932 memcpy(data->notify_data.data.string, temp, len);
2935 /*******************************************************************
2936 * fill a notify_info_data with the security descriptor
2937 * jfm:xxxx send an null pointer to say no security desc
2938 * have to implement security before !
2939 ********************************************************************/
2941 static void spoolss_notify_security_desc(int snum,
2942 SPOOL_NOTIFY_INFO_DATA *data,
2943 print_queue_struct *queue,
2944 NT_PRINTER_INFO_LEVEL *printer,
2945 TALLOC_CTX *mem_ctx)
2947 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2948 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2951 /*******************************************************************
2952 * fill a notify_info_data with the attributes
2953 * jfm:xxxx a samba printer is always shared
2954 ********************************************************************/
2956 void spoolss_notify_attributes(int snum,
2957 SPOOL_NOTIFY_INFO_DATA *data,
2958 print_queue_struct *queue,
2959 NT_PRINTER_INFO_LEVEL *printer,
2960 TALLOC_CTX *mem_ctx)
2962 data->notify_data.value[0] = printer->info_2->attributes;
2963 data->notify_data.value[1] = 0;
2966 /*******************************************************************
2967 * fill a notify_info_data with the priority
2968 ********************************************************************/
2970 static void spoolss_notify_priority(int snum,
2971 SPOOL_NOTIFY_INFO_DATA *data,
2972 print_queue_struct *queue,
2973 NT_PRINTER_INFO_LEVEL *printer,
2974 TALLOC_CTX *mem_ctx)
2976 data->notify_data.value[0] = printer->info_2->priority;
2977 data->notify_data.value[1] = 0;
2980 /*******************************************************************
2981 * fill a notify_info_data with the default priority
2982 ********************************************************************/
2984 static void spoolss_notify_default_priority(int snum,
2985 SPOOL_NOTIFY_INFO_DATA *data,
2986 print_queue_struct *queue,
2987 NT_PRINTER_INFO_LEVEL *printer,
2988 TALLOC_CTX *mem_ctx)
2990 data->notify_data.value[0] = printer->info_2->default_priority;
2991 data->notify_data.value[1] = 0;
2994 /*******************************************************************
2995 * fill a notify_info_data with the start time
2996 ********************************************************************/
2998 static void spoolss_notify_start_time(int snum,
2999 SPOOL_NOTIFY_INFO_DATA *data,
3000 print_queue_struct *queue,
3001 NT_PRINTER_INFO_LEVEL *printer,
3002 TALLOC_CTX *mem_ctx)
3004 data->notify_data.value[0] = printer->info_2->starttime;
3005 data->notify_data.value[1] = 0;
3008 /*******************************************************************
3009 * fill a notify_info_data with the until time
3010 ********************************************************************/
3012 static void spoolss_notify_until_time(int snum,
3013 SPOOL_NOTIFY_INFO_DATA *data,
3014 print_queue_struct *queue,
3015 NT_PRINTER_INFO_LEVEL *printer,
3016 TALLOC_CTX *mem_ctx)
3018 data->notify_data.value[0] = printer->info_2->untiltime;
3019 data->notify_data.value[1] = 0;
3022 /*******************************************************************
3023 * fill a notify_info_data with the status
3024 ********************************************************************/
3026 static void spoolss_notify_status(int snum,
3027 SPOOL_NOTIFY_INFO_DATA *data,
3028 print_queue_struct *queue,
3029 NT_PRINTER_INFO_LEVEL *printer,
3030 TALLOC_CTX *mem_ctx)
3032 print_status_struct status;
3034 print_queue_length(snum, &status);
3035 data->notify_data.value[0]=(uint32) status.status;
3036 data->notify_data.value[1] = 0;
3039 /*******************************************************************
3040 * fill a notify_info_data with the number of jobs queued
3041 ********************************************************************/
3043 void spoolss_notify_cjobs(int snum,
3044 SPOOL_NOTIFY_INFO_DATA *data,
3045 print_queue_struct *queue,
3046 NT_PRINTER_INFO_LEVEL *printer,
3047 TALLOC_CTX *mem_ctx)
3049 data->notify_data.value[0] = print_queue_length(snum, NULL);
3050 data->notify_data.value[1] = 0;
3053 /*******************************************************************
3054 * fill a notify_info_data with the average ppm
3055 ********************************************************************/
3057 static void spoolss_notify_average_ppm(int snum,
3058 SPOOL_NOTIFY_INFO_DATA *data,
3059 print_queue_struct *queue,
3060 NT_PRINTER_INFO_LEVEL *printer,
3061 TALLOC_CTX *mem_ctx)
3063 /* always respond 8 pages per minutes */
3064 /* a little hard ! */
3065 data->notify_data.value[0] = printer->info_2->averageppm;
3066 data->notify_data.value[1] = 0;
3069 /*******************************************************************
3070 * fill a notify_info_data with username
3071 ********************************************************************/
3073 static void spoolss_notify_username(int snum,
3074 SPOOL_NOTIFY_INFO_DATA *data,
3075 print_queue_struct *queue,
3076 NT_PRINTER_INFO_LEVEL *printer,
3077 TALLOC_CTX *mem_ctx)
3082 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3084 data->notify_data.data.length = len;
3085 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3087 if (!data->notify_data.data.string) {
3088 data->notify_data.data.length = 0;
3092 memcpy(data->notify_data.data.string, temp, len);
3095 /*******************************************************************
3096 * fill a notify_info_data with job status
3097 ********************************************************************/
3099 static void spoolss_notify_job_status(int snum,
3100 SPOOL_NOTIFY_INFO_DATA *data,
3101 print_queue_struct *queue,
3102 NT_PRINTER_INFO_LEVEL *printer,
3103 TALLOC_CTX *mem_ctx)
3105 data->notify_data.value[0]=nt_printj_status(queue->status);
3106 data->notify_data.value[1] = 0;
3109 /*******************************************************************
3110 * fill a notify_info_data with job name
3111 ********************************************************************/
3113 static void spoolss_notify_job_name(int snum,
3114 SPOOL_NOTIFY_INFO_DATA *data,
3115 print_queue_struct *queue,
3116 NT_PRINTER_INFO_LEVEL *printer,
3117 TALLOC_CTX *mem_ctx)
3122 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3124 data->notify_data.data.length = len;
3125 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3127 if (!data->notify_data.data.string) {
3128 data->notify_data.data.length = 0;
3132 memcpy(data->notify_data.data.string, temp, len);
3135 /*******************************************************************
3136 * fill a notify_info_data with job status
3137 ********************************************************************/
3139 static void spoolss_notify_job_status_string(int snum,
3140 SPOOL_NOTIFY_INFO_DATA *data,
3141 print_queue_struct *queue,
3142 NT_PRINTER_INFO_LEVEL *printer,
3143 TALLOC_CTX *mem_ctx)
3146 * Now we're returning job status codes we just return a "" here. JRA.
3153 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3156 switch (queue->status) {
3161 p = ""; /* NT provides the paused string */
3170 #endif /* NO LONGER NEEDED. */
3172 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3174 data->notify_data.data.length = len;
3175 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3177 if (!data->notify_data.data.string) {
3178 data->notify_data.data.length = 0;
3182 memcpy(data->notify_data.data.string, temp, len);
3185 /*******************************************************************
3186 * fill a notify_info_data with job time
3187 ********************************************************************/
3189 static void spoolss_notify_job_time(int snum,
3190 SPOOL_NOTIFY_INFO_DATA *data,
3191 print_queue_struct *queue,
3192 NT_PRINTER_INFO_LEVEL *printer,
3193 TALLOC_CTX *mem_ctx)
3195 data->notify_data.value[0]=0x0;
3196 data->notify_data.value[1]=0;
3199 /*******************************************************************
3200 * fill a notify_info_data with job size
3201 ********************************************************************/
3203 static void spoolss_notify_job_size(int snum,
3204 SPOOL_NOTIFY_INFO_DATA *data,
3205 print_queue_struct *queue,
3206 NT_PRINTER_INFO_LEVEL *printer,
3207 TALLOC_CTX *mem_ctx)
3209 data->notify_data.value[0]=queue->size;
3210 data->notify_data.value[1]=0;
3213 /*******************************************************************
3214 * fill a notify_info_data with page info
3215 ********************************************************************/
3216 static void spoolss_notify_total_pages(int snum,
3217 SPOOL_NOTIFY_INFO_DATA *data,
3218 print_queue_struct *queue,
3219 NT_PRINTER_INFO_LEVEL *printer,
3220 TALLOC_CTX *mem_ctx)
3222 data->notify_data.value[0]=queue->page_count;
3223 data->notify_data.value[1]=0;
3226 /*******************************************************************
3227 * fill a notify_info_data with pages printed info.
3228 ********************************************************************/
3229 static void spoolss_notify_pages_printed(int snum,
3230 SPOOL_NOTIFY_INFO_DATA *data,
3231 print_queue_struct *queue,
3232 NT_PRINTER_INFO_LEVEL *printer,
3233 TALLOC_CTX *mem_ctx)
3235 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3236 data->notify_data.value[1]=0;
3239 /*******************************************************************
3240 Fill a notify_info_data with job position.
3241 ********************************************************************/
3243 static void spoolss_notify_job_position(int snum,
3244 SPOOL_NOTIFY_INFO_DATA *data,
3245 print_queue_struct *queue,
3246 NT_PRINTER_INFO_LEVEL *printer,
3247 TALLOC_CTX *mem_ctx)
3249 data->notify_data.value[0]=queue->job;
3250 data->notify_data.value[1]=0;
3253 /*******************************************************************
3254 Fill a notify_info_data with submitted time.
3255 ********************************************************************/
3257 static void spoolss_notify_submitted_time(int snum,
3258 SPOOL_NOTIFY_INFO_DATA *data,
3259 print_queue_struct *queue,
3260 NT_PRINTER_INFO_LEVEL *printer,
3261 TALLOC_CTX *mem_ctx)
3268 t=gmtime(&queue->time);
3270 len = sizeof(SYSTEMTIME);
3272 data->notify_data.data.length = len;
3273 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3275 if (!data->notify_data.data.string) {
3276 data->notify_data.data.length = 0;
3280 make_systemtime(&st, t);
3283 * Systemtime must be linearized as a set of UINT16's.
3284 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3287 p = (char *)data->notify_data.data.string;
3288 SSVAL(p, 0, st.year);
3289 SSVAL(p, 2, st.month);
3290 SSVAL(p, 4, st.dayofweek);
3291 SSVAL(p, 6, st.day);
3292 SSVAL(p, 8, st.hour);
3293 SSVAL(p, 10, st.minute);
3294 SSVAL(p, 12, st.second);
3295 SSVAL(p, 14, st.milliseconds);
3298 struct s_notify_info_data_table
3304 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3305 print_queue_struct *queue,
3306 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3309 /* A table describing the various print notification constants and
3310 whether the notification data is a pointer to a variable sized
3311 buffer, a one value uint32 or a two value uint32. */
3313 static const struct s_notify_info_data_table notify_info_data_table[] =
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3325 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3326 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3327 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3328 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3329 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3330 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3331 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3332 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3333 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3334 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3335 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3336 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3337 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3338 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3339 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3340 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3341 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3342 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3343 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3344 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3345 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3346 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3347 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3348 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3349 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3350 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3351 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3352 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3353 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3354 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3355 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3356 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3357 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3358 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3359 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3360 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3361 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3362 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3363 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3366 /*******************************************************************
3367 Return the size of info_data structure.
3368 ********************************************************************/
3370 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3374 for (i = 0; i < sizeof(notify_info_data_table); i++)
3376 if ( (notify_info_data_table[i].type == type)
3377 && (notify_info_data_table[i].field == field) )
3379 switch(notify_info_data_table[i].size)
3381 case NOTIFY_ONE_VALUE:
3382 case NOTIFY_TWO_VALUE:
3387 /* The only pointer notify data I have seen on
3388 the wire is the submitted time and this has
3389 the notify size set to 4. -tpot */
3391 case NOTIFY_POINTER:
3394 case NOTIFY_SECDESC:
3400 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3405 /*******************************************************************
3406 Return the type of notify_info_data.
3407 ********************************************************************/
3409 static int type_of_notify_info_data(uint16 type, uint16 field)
3413 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3414 if (notify_info_data_table[i].type == type &&
3415 notify_info_data_table[i].field == field)
3416 return notify_info_data_table[i].size;
3422 /****************************************************************************
3423 ****************************************************************************/
3425 static int search_notify(uint16 type, uint16 field, int *value)
3429 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3430 if (notify_info_data_table[i].type == type &&
3431 notify_info_data_table[i].field == field &&
3432 notify_info_data_table[i].fn != NULL) {
3441 /****************************************************************************
3442 ****************************************************************************/
3444 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3446 info_data->type = type;
3447 info_data->field = field;
3448 info_data->reserved = 0;
3450 info_data->size = size_of_notify_info_data(type, field);
3451 info_data->enc_type = type_of_notify_info_data(type, field);
3458 /*******************************************************************
3460 * fill a notify_info struct with info asked
3462 ********************************************************************/
3464 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3465 snum, SPOOL_NOTIFY_OPTION_TYPE
3466 *option_type, uint32 id,
3467 TALLOC_CTX *mem_ctx)
3473 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3474 NT_PRINTER_INFO_LEVEL *printer = NULL;
3475 print_queue_struct *queue=NULL;
3477 type=option_type->type;
3479 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3480 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3481 option_type->count, lp_servicename(snum)));
3483 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3486 for(field_num=0; field_num<option_type->count; field_num++) {
3487 field = option_type->fields[field_num];
3489 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3491 if (!search_notify(type, field, &j) )
3494 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3495 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3500 current_data = &info->data[info->count];
3502 construct_info_data(current_data, type, field, id);
3504 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3505 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3507 notify_info_data_table[j].fn(snum, current_data, queue,
3513 free_a_printer(&printer, 2);
3517 /*******************************************************************
3519 * fill a notify_info struct with info asked
3521 ********************************************************************/
3523 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3524 SPOOL_NOTIFY_INFO *info,
3525 NT_PRINTER_INFO_LEVEL *printer,
3526 int snum, SPOOL_NOTIFY_OPTION_TYPE
3527 *option_type, uint32 id,
3528 TALLOC_CTX *mem_ctx)
3534 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3536 DEBUG(4,("construct_notify_jobs_info\n"));
3538 type = option_type->type;
3540 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3541 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3542 option_type->count));
3544 for(field_num=0; field_num<option_type->count; field_num++) {
3545 field = option_type->fields[field_num];
3547 if (!search_notify(type, field, &j) )
3550 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3551 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3554 else info->data = tid;
3556 current_data=&(info->data[info->count]);
3558 construct_info_data(current_data, type, field, id);
3559 notify_info_data_table[j].fn(snum, current_data, queue,
3568 * JFM: The enumeration is not that simple, it's even non obvious.
3570 * let's take an example: I want to monitor the PRINTER SERVER for
3571 * the printer's name and the number of jobs currently queued.
3572 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3573 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3575 * I have 3 printers on the back of my server.
3577 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3580 * 1 printer 1 name 1
3581 * 2 printer 1 cjob 1
3582 * 3 printer 2 name 2
3583 * 4 printer 2 cjob 2
3584 * 5 printer 3 name 3
3585 * 6 printer 3 name 3
3587 * that's the print server case, the printer case is even worse.
3590 /*******************************************************************
3592 * enumerate all printers on the printserver
3593 * fill a notify_info struct with info asked
3595 ********************************************************************/
3597 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3598 SPOOL_NOTIFY_INFO *info,
3599 TALLOC_CTX *mem_ctx)
3602 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3603 int n_services=lp_numservices();
3606 SPOOL_NOTIFY_OPTION *option;
3607 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3609 DEBUG(4,("printserver_notify_info\n"));
3614 option=Printer->notify.option;
3620 for (i=0; i<option->count; i++) {
3621 option_type=&(option->ctr.type[i]);
3623 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3626 for (snum=0; snum<n_services; snum++)
3628 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3629 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3635 * Debugging information, don't delete.
3638 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3639 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3640 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3642 for (i=0; i<info->count; i++) {
3643 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3644 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3645 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3652 /*******************************************************************
3654 * fill a notify_info struct with info asked
3656 ********************************************************************/
3658 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3659 TALLOC_CTX *mem_ctx)
3662 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3665 SPOOL_NOTIFY_OPTION *option;
3666 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3668 print_queue_struct *queue=NULL;
3669 print_status_struct status;
3671 DEBUG(4,("printer_notify_info\n"));
3676 option=Printer->notify.option;
3682 get_printer_snum(p, hnd, &snum);
3684 for (i=0; i<option->count; i++) {
3685 option_type=&option->ctr.type[i];
3687 switch ( option_type->type ) {
3688 case PRINTER_NOTIFY_TYPE:
3689 if(construct_notify_printer_info(Printer, info, snum,
3695 case JOB_NOTIFY_TYPE: {
3696 NT_PRINTER_INFO_LEVEL *printer = NULL;
3698 count = print_queue_status(snum, &queue, &status);
3700 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3703 for (j=0; j<count; j++) {
3704 construct_notify_jobs_info(&queue[j], info,
3711 free_a_printer(&printer, 2);
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));
3737 /********************************************************************
3739 ********************************************************************/
3741 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3743 POLICY_HND *handle = &q_u->handle;
3744 SPOOL_NOTIFY_INFO *info = &r_u->info;
3746 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3747 WERROR result = WERR_BADFID;
3749 /* we always have a NOTIFY_INFO struct */
3753 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3754 OUR_HANDLE(handle)));
3758 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3761 * We are now using the change value, and
3762 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3763 * I don't have a global notification system, I'm sending back all the
3764 * informations even when _NOTHING_ has changed.
3767 /* We need to keep track of the change value to send back in
3768 RRPCN replies otherwise our updates are ignored. */
3770 Printer->notify.fnpcn = True;
3772 if (Printer->notify.client_connected) {
3773 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3774 Printer->notify.change = q_u->change;
3777 /* just ignore the SPOOL_NOTIFY_OPTION */
3779 switch (Printer->printer_type) {
3780 case PRINTER_HANDLE_IS_PRINTSERVER:
3781 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3784 case PRINTER_HANDLE_IS_PRINTER:
3785 result = printer_notify_info(p, handle, info, p->mem_ctx);
3789 Printer->notify.fnpcn = False;
3795 /********************************************************************
3796 * construct_printer_info_0
3797 * fill a printer_info_0 struct
3798 ********************************************************************/
3800 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3804 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3805 counter_printer_0 *session_counter;
3806 uint32 global_counter;
3809 print_status_struct status;
3811 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3814 count = print_queue_length(snum, &status);
3816 /* check if we already have a counter for this printer */
3817 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3819 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3820 if (session_counter->snum == snum)
3824 /* it's the first time, add it to the list */
3825 if (session_counter==NULL) {
3826 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3827 free_a_printer(&ntprinter, 2);
3830 ZERO_STRUCTP(session_counter);
3831 session_counter->snum=snum;
3832 session_counter->counter=0;
3833 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3837 session_counter->counter++;
3840 * the global_counter should be stored in a TDB as it's common to all the clients
3841 * and should be zeroed on samba startup
3843 global_counter=session_counter->counter;
3845 pstrcpy(chaine,ntprinter->info_2->printername);
3847 init_unistr(&printer->printername, chaine);
3849 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3850 init_unistr(&printer->servername, chaine);
3852 printer->cjobs = count;
3853 printer->total_jobs = 0;
3854 printer->total_bytes = 0;
3856 setuptime = (time_t)ntprinter->info_2->setuptime;
3857 t=gmtime(&setuptime);
3859 printer->year = t->tm_year+1900;
3860 printer->month = t->tm_mon+1;
3861 printer->dayofweek = t->tm_wday;
3862 printer->day = t->tm_mday;
3863 printer->hour = t->tm_hour;
3864 printer->minute = t->tm_min;
3865 printer->second = t->tm_sec;
3866 printer->milliseconds = 0;
3868 printer->global_counter = global_counter;
3869 printer->total_pages = 0;
3871 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3872 printer->major_version = 0x0005; /* NT 5 */
3873 printer->build_version = 0x0893; /* build 2195 */
3875 printer->unknown7 = 0x1;
3876 printer->unknown8 = 0x0;
3877 printer->unknown9 = 0x0;
3878 printer->session_counter = session_counter->counter;
3879 printer->unknown11 = 0x0;
3880 printer->printer_errors = 0x0; /* number of print failure */
3881 printer->unknown13 = 0x0;
3882 printer->unknown14 = 0x1;
3883 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3884 printer->unknown16 = 0x0;
3885 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3886 printer->unknown18 = 0x0;
3887 printer->status = nt_printq_status(status.status);
3888 printer->unknown20 = 0x0;
3889 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3890 printer->unknown22 = 0x0;
3891 printer->unknown23 = 0x6; /* 6 ???*/
3892 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3893 printer->unknown25 = 0;
3894 printer->unknown26 = 0;
3895 printer->unknown27 = 0;
3896 printer->unknown28 = 0;
3897 printer->unknown29 = 0;
3899 free_a_printer(&ntprinter,2);
3903 /********************************************************************
3904 * construct_printer_info_1
3905 * fill a printer_info_1 struct
3906 ********************************************************************/
3907 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3911 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3913 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3916 printer->flags=flags;
3918 if (*ntprinter->info_2->comment == '\0') {
3919 init_unistr(&printer->comment, lp_comment(snum));
3920 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3921 ntprinter->info_2->drivername, lp_comment(snum));
3924 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3925 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3926 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3929 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3931 init_unistr(&printer->description, chaine);
3932 init_unistr(&printer->name, chaine2);
3934 free_a_printer(&ntprinter,2);
3939 /****************************************************************************
3940 Free a DEVMODE struct.
3941 ****************************************************************************/
3943 static void free_dev_mode(DEVICEMODE *dev)
3948 SAFE_FREE(dev->private);
3953 /****************************************************************************
3954 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3955 should be valid upon entry
3956 ****************************************************************************/
3958 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
3960 if ( !devmode || !ntdevmode )
3963 init_unistr(&devmode->devicename, ntdevmode->devicename);
3965 init_unistr(&devmode->formname, ntdevmode->formname);
3967 devmode->specversion = ntdevmode->specversion;
3968 devmode->driverversion = ntdevmode->driverversion;
3969 devmode->size = ntdevmode->size;
3970 devmode->driverextra = ntdevmode->driverextra;
3971 devmode->fields = ntdevmode->fields;
3973 devmode->orientation = ntdevmode->orientation;
3974 devmode->papersize = ntdevmode->papersize;
3975 devmode->paperlength = ntdevmode->paperlength;
3976 devmode->paperwidth = ntdevmode->paperwidth;
3977 devmode->scale = ntdevmode->scale;
3978 devmode->copies = ntdevmode->copies;
3979 devmode->defaultsource = ntdevmode->defaultsource;
3980 devmode->printquality = ntdevmode->printquality;
3981 devmode->color = ntdevmode->color;
3982 devmode->duplex = ntdevmode->duplex;
3983 devmode->yresolution = ntdevmode->yresolution;
3984 devmode->ttoption = ntdevmode->ttoption;
3985 devmode->collate = ntdevmode->collate;
3986 devmode->icmmethod = ntdevmode->icmmethod;
3987 devmode->icmintent = ntdevmode->icmintent;
3988 devmode->mediatype = ntdevmode->mediatype;
3989 devmode->dithertype = ntdevmode->dithertype;
3991 if (ntdevmode->private != NULL) {
3992 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3999 /****************************************************************************
4000 Create a DEVMODE struct. Returns malloced memory.
4001 ****************************************************************************/
4003 DEVICEMODE *construct_dev_mode(int snum)
4005 NT_PRINTER_INFO_LEVEL *printer = NULL;
4006 DEVICEMODE *devmode = NULL;
4008 DEBUG(7,("construct_dev_mode\n"));
4010 DEBUGADD(8,("getting printer characteristics\n"));
4012 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4015 if ( !printer->info_2->devmode ) {
4016 DEBUG(5, ("BONG! There was no device mode!\n"));
4020 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4021 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4025 ZERO_STRUCTP(devmode);
4027 DEBUGADD(8,("loading DEVICEMODE\n"));
4029 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4030 free_dev_mode( devmode );
4035 free_a_printer(&printer,2);
4040 /********************************************************************
4041 * construct_printer_info_2
4042 * fill a printer_info_2 struct
4043 ********************************************************************/
4045 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4048 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4050 print_status_struct status;
4052 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4055 count = print_queue_length(snum, &status);
4057 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4058 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4059 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4060 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4061 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4063 if (*ntprinter->info_2->comment == '\0')
4064 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4066 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4068 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4069 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4070 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4071 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4072 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4074 printer->attributes = ntprinter->info_2->attributes;
4076 printer->priority = ntprinter->info_2->priority; /* priority */
4077 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4078 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4079 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4080 printer->status = nt_printq_status(status.status); /* status */
4081 printer->cjobs = count; /* jobs */
4082 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4084 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4085 DEBUG(8, ("Returning NULL Devicemode!\n"));
4088 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4089 /* steal the printer info sec_desc structure. [badly done]. */
4090 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4091 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4092 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4093 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4096 printer->secdesc = NULL;
4099 free_a_printer(&ntprinter, 2);
4103 /********************************************************************
4104 * construct_printer_info_3
4105 * fill a printer_info_3 struct
4106 ********************************************************************/
4108 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4110 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4111 PRINTER_INFO_3 *printer = NULL;
4113 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4117 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4118 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4122 ZERO_STRUCTP(printer);
4124 printer->flags = 4; /* These are the components of the SD we are returning. */
4125 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4126 /* steal the printer info sec_desc structure. [badly done]. */
4127 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4131 * Set the flags for the components we are returning.
4134 if (printer->secdesc->owner_sid)
4135 printer->flags |= OWNER_SECURITY_INFORMATION;
4137 if (printer->secdesc->grp_sid)
4138 printer->flags |= GROUP_SECURITY_INFORMATION;
4140 if (printer->secdesc->dacl)
4141 printer->flags |= DACL_SECURITY_INFORMATION;
4143 if (printer->secdesc->sacl)
4144 printer->flags |= SACL_SECURITY_INFORMATION;
4147 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4148 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4149 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4152 free_a_printer(&ntprinter, 2);
4154 *pp_printer = printer;
4158 /********************************************************************
4159 * construct_printer_info_4
4160 * fill a printer_info_4 struct
4161 ********************************************************************/
4163 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4165 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4167 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4170 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4171 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4172 printer->attributes = ntprinter->info_2->attributes;
4174 free_a_printer(&ntprinter, 2);
4178 /********************************************************************
4179 * construct_printer_info_5
4180 * fill a printer_info_5 struct
4181 ********************************************************************/
4183 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4185 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4187 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4190 init_unistr(&printer->printername, ntprinter->info_2->printername);
4191 init_unistr(&printer->portname, ntprinter->info_2->portname);
4192 printer->attributes = ntprinter->info_2->attributes;
4194 /* these two are not used by NT+ according to MSDN */
4196 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4197 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4199 free_a_printer(&ntprinter, 2);
4204 /********************************************************************
4205 * construct_printer_info_7
4206 * fill a printer_info_7 struct
4207 ********************************************************************/
4209 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4211 char *guid_str = NULL;
4214 if (is_printer_published(print_hnd, snum, &guid)) {
4215 asprintf(&guid_str, "{%s}", uuid_string_static(guid));
4217 init_unistr(&printer->guid, guid_str);
4218 printer->action = SPOOL_DS_PUBLISH;
4220 init_unistr(&printer->guid, "");
4221 printer->action = SPOOL_DS_UNPUBLISH;
4227 /********************************************************************
4228 Spoolss_enumprinters.
4229 ********************************************************************/
4231 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4235 int n_services=lp_numservices();
4236 PRINTER_INFO_1 *tp, *printers=NULL;
4237 PRINTER_INFO_1 current_prt;
4239 DEBUG(4,("enum_all_printers_info_1\n"));
4241 for (snum=0; snum<n_services; snum++) {
4242 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4243 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4245 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4246 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4247 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4248 SAFE_FREE(printers);
4253 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4255 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4261 /* check the required size. */
4262 for (i=0; i<*returned; i++)
4263 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4265 if (!alloc_buffer_size(buffer, *needed))
4266 return WERR_INSUFFICIENT_BUFFER;
4268 /* fill the buffer with the structures */
4269 for (i=0; i<*returned; i++)
4270 smb_io_printer_info_1("", buffer, &printers[i], 0);
4273 SAFE_FREE(printers);
4275 if (*needed > offered) {
4277 return WERR_INSUFFICIENT_BUFFER;
4283 /********************************************************************
4284 enum_all_printers_info_1_local.
4285 *********************************************************************/
4287 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4289 DEBUG(4,("enum_all_printers_info_1_local\n"));
4291 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4294 /********************************************************************
4295 enum_all_printers_info_1_name.
4296 *********************************************************************/
4298 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4302 DEBUG(4,("enum_all_printers_info_1_name\n"));
4304 if ((name[0] == '\\') && (name[1] == '\\'))
4307 if (is_myname_or_ipaddr(s)) {
4308 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4311 return WERR_INVALID_NAME;
4314 /********************************************************************
4315 enum_all_printers_info_1_remote.
4316 *********************************************************************/
4318 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4320 PRINTER_INFO_1 *printer;
4321 fstring printername;
4324 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4326 /* JFM: currently it's more a place holder than anything else.
4327 * In the spooler world there is a notion of server registration.
4328 * the print servers are registring (sp ?) on the PDC (in the same domain)
4330 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4333 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4338 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4339 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4340 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4342 init_unistr(&printer->description, desc);
4343 init_unistr(&printer->name, printername);
4344 init_unistr(&printer->comment, comment);
4345 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4347 /* check the required size. */
4348 *needed += spoolss_size_printer_info_1(printer);
4350 if (!alloc_buffer_size(buffer, *needed)) {
4352 return WERR_INSUFFICIENT_BUFFER;
4355 /* fill the buffer with the structures */
4356 smb_io_printer_info_1("", buffer, printer, 0);
4361 if (*needed > offered) {
4363 return WERR_INSUFFICIENT_BUFFER;
4369 /********************************************************************
4370 enum_all_printers_info_1_network.
4371 *********************************************************************/
4373 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4377 DEBUG(4,("enum_all_printers_info_1_network\n"));
4379 /* If we respond to a enum_printers level 1 on our name with flags
4380 set to PRINTER_ENUM_REMOTE with a list of printers then these
4381 printers incorrectly appear in the APW browse list.
4382 Specifically the printers for the server appear at the workgroup
4383 level where all the other servers in the domain are
4384 listed. Windows responds to this call with a
4385 WERR_CAN_NOT_COMPLETE so we should do the same. */
4387 if (name[0] == '\\' && name[1] == '\\')
4390 if (is_myname_or_ipaddr(s))
4391 return WERR_CAN_NOT_COMPLETE;
4393 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4396 /********************************************************************
4397 * api_spoolss_enumprinters
4399 * called from api_spoolss_enumprinters (see this to understand)
4400 ********************************************************************/
4402 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4406 int n_services=lp_numservices();
4407 PRINTER_INFO_2 *tp, *printers=NULL;
4408 PRINTER_INFO_2 current_prt;
4410 for (snum=0; snum<n_services; snum++) {
4411 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4412 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4414 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4415 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4416 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4417 SAFE_FREE(printers);
4422 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4423 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4429 /* check the required size. */
4430 for (i=0; i<*returned; i++)
4431 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4433 if (!alloc_buffer_size(buffer, *needed)) {
4434 for (i=0; i<*returned; i++) {
4435 free_devmode(printers[i].devmode);
4437 SAFE_FREE(printers);
4438 return WERR_INSUFFICIENT_BUFFER;
4441 /* fill the buffer with the structures */
4442 for (i=0; i<*returned; i++)
4443 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4446 for (i=0; i<*returned; i++) {
4447 free_devmode(printers[i].devmode);
4449 SAFE_FREE(printers);
4451 if (*needed > offered) {
4453 return WERR_INSUFFICIENT_BUFFER;
4459 /********************************************************************
4460 * handle enumeration of printers at level 1
4461 ********************************************************************/
4463 static WERROR enumprinters_level1( uint32 flags, fstring name,
4464 NEW_BUFFER *buffer, uint32 offered,
4465 uint32 *needed, uint32 *returned)
4467 /* Not all the flags are equals */
4469 if (flags & PRINTER_ENUM_LOCAL)
4470 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4472 if (flags & PRINTER_ENUM_NAME)
4473 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4475 if (flags & PRINTER_ENUM_REMOTE)
4476 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4478 if (flags & PRINTER_ENUM_NETWORK)
4479 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4481 return WERR_OK; /* NT4sp5 does that */
4484 /********************************************************************
4485 * handle enumeration of printers at level 2
4486 ********************************************************************/
4488 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4489 NEW_BUFFER *buffer, uint32 offered,
4490 uint32 *needed, uint32 *returned)
4492 char *s = servername;
4494 if (flags & PRINTER_ENUM_LOCAL) {
4495 return enum_all_printers_info_2(buffer, offered, needed, returned);
4498 if (flags & PRINTER_ENUM_NAME) {
4499 if ((servername[0] == '\\') && (servername[1] == '\\'))
4501 if (is_myname_or_ipaddr(s))
4502 return enum_all_printers_info_2(buffer, offered, needed, returned);
4504 return WERR_INVALID_NAME;
4507 if (flags & PRINTER_ENUM_REMOTE)
4508 return WERR_UNKNOWN_LEVEL;
4513 /********************************************************************
4514 * handle enumeration of printers at level 5
4515 ********************************************************************/
4517 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4518 NEW_BUFFER *buffer, uint32 offered,
4519 uint32 *needed, uint32 *returned)
4521 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4525 /********************************************************************
4526 * api_spoolss_enumprinters
4528 * called from api_spoolss_enumprinters (see this to understand)
4529 ********************************************************************/
4531 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4533 uint32 flags = q_u->flags;
4534 UNISTR2 *servername = &q_u->servername;
4535 uint32 level = q_u->level;
4536 NEW_BUFFER *buffer = NULL;
4537 uint32 offered = q_u->offered;
4538 uint32 *needed = &r_u->needed;
4539 uint32 *returned = &r_u->returned;
4543 /* that's an [in out] buffer */
4544 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4545 buffer = r_u->buffer;
4547 DEBUG(4,("_spoolss_enumprinters\n"));
4554 * flags==PRINTER_ENUM_NAME
4555 * if name=="" then enumerates all printers
4556 * if name!="" then enumerate the printer
4557 * flags==PRINTER_ENUM_REMOTE
4558 * name is NULL, enumerate printers
4559 * Level 2: name!="" enumerates printers, name can't be NULL
4560 * Level 3: doesn't exist
4561 * Level 4: does a local registry lookup
4562 * Level 5: same as Level 2
4565 unistr2_to_ascii(name, servername, sizeof(name)-1);
4570 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4572 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4574 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4579 return WERR_UNKNOWN_LEVEL;
4582 /****************************************************************************
4583 ****************************************************************************/
4585 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4587 PRINTER_INFO_0 *printer=NULL;
4589 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4592 construct_printer_info_0(print_hnd, printer, snum);
4594 /* check the required size. */
4595 *needed += spoolss_size_printer_info_0(printer);
4597 if (!alloc_buffer_size(buffer, *needed)) {
4599 return WERR_INSUFFICIENT_BUFFER;
4602 /* fill the buffer with the structures */
4603 smb_io_printer_info_0("", buffer, printer, 0);
4608 if (*needed > offered) {
4609 return WERR_INSUFFICIENT_BUFFER;
4615 /****************************************************************************
4616 ****************************************************************************/
4618 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4620 PRINTER_INFO_1 *printer=NULL;
4622 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4625 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4627 /* check the required size. */
4628 *needed += spoolss_size_printer_info_1(printer);
4630 if (!alloc_buffer_size(buffer, *needed)) {
4632 return WERR_INSUFFICIENT_BUFFER;
4635 /* fill the buffer with the structures */
4636 smb_io_printer_info_1("", buffer, printer, 0);
4641 if (*needed > offered) {
4642 return WERR_INSUFFICIENT_BUFFER;
4648 /****************************************************************************
4649 ****************************************************************************/
4651 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4653 PRINTER_INFO_2 *printer=NULL;
4655 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4658 construct_printer_info_2(print_hnd, printer, snum);
4660 /* check the required size. */
4661 *needed += spoolss_size_printer_info_2(printer);
4663 if (!alloc_buffer_size(buffer, *needed)) {
4664 free_printer_info_2(printer);
4665 return WERR_INSUFFICIENT_BUFFER;
4668 /* fill the buffer with the structures */
4669 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4670 free_printer_info_2(printer);
4675 free_printer_info_2(printer);
4677 if (*needed > offered) {
4678 return WERR_INSUFFICIENT_BUFFER;
4684 /****************************************************************************
4685 ****************************************************************************/
4687 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4689 PRINTER_INFO_3 *printer=NULL;
4691 if (!construct_printer_info_3(print_hnd, &printer, snum))
4694 /* check the required size. */
4695 *needed += spoolss_size_printer_info_3(printer);
4697 if (!alloc_buffer_size(buffer, *needed)) {
4698 free_printer_info_3(printer);
4699 return WERR_INSUFFICIENT_BUFFER;
4702 /* fill the buffer with the structures */
4703 smb_io_printer_info_3("", buffer, printer, 0);
4706 free_printer_info_3(printer);
4708 if (*needed > offered) {
4709 return WERR_INSUFFICIENT_BUFFER;
4715 /****************************************************************************
4716 ****************************************************************************/
4718 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4720 PRINTER_INFO_4 *printer=NULL;
4722 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4725 if (!construct_printer_info_4(print_hnd, printer, snum))
4728 /* check the required size. */
4729 *needed += spoolss_size_printer_info_4(printer);
4731 if (!alloc_buffer_size(buffer, *needed)) {
4732 free_printer_info_4(printer);
4733 return WERR_INSUFFICIENT_BUFFER;
4736 /* fill the buffer with the structures */
4737 smb_io_printer_info_4("", buffer, printer, 0);
4740 free_printer_info_4(printer);
4742 if (*needed > offered) {
4743 return WERR_INSUFFICIENT_BUFFER;
4749 /****************************************************************************
4750 ****************************************************************************/
4752 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4754 PRINTER_INFO_5 *printer=NULL;
4756 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4759 if (!construct_printer_info_5(print_hnd, printer, snum))
4762 /* check the required size. */
4763 *needed += spoolss_size_printer_info_5(printer);
4765 if (!alloc_buffer_size(buffer, *needed)) {
4766 free_printer_info_5(printer);
4767 return WERR_INSUFFICIENT_BUFFER;
4770 /* fill the buffer with the structures */
4771 smb_io_printer_info_5("", buffer, printer, 0);
4774 free_printer_info_5(printer);
4776 if (*needed > offered) {
4777 return WERR_INSUFFICIENT_BUFFER;
4783 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4785 PRINTER_INFO_7 *printer=NULL;
4787 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4790 if (!construct_printer_info_7(print_hnd, printer, snum))
4793 /* check the required size. */
4794 *needed += spoolss_size_printer_info_7(printer);
4796 if (!alloc_buffer_size(buffer, *needed)) {
4797 free_printer_info_7(printer);
4798 return WERR_INSUFFICIENT_BUFFER;
4801 /* fill the buffer with the structures */
4802 smb_io_printer_info_7("", buffer, printer, 0);
4805 free_printer_info_7(printer);
4807 if (*needed > offered) {
4808 return WERR_INSUFFICIENT_BUFFER;
4814 /****************************************************************************
4815 ****************************************************************************/
4817 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4819 POLICY_HND *handle = &q_u->handle;
4820 uint32 level = q_u->level;
4821 NEW_BUFFER *buffer = NULL;
4822 uint32 offered = q_u->offered;
4823 uint32 *needed = &r_u->needed;
4824 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4828 /* that's an [in out] buffer */
4829 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4830 buffer = r_u->buffer;
4834 if (!get_printer_snum(p, handle, &snum))
4839 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4841 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4843 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4845 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4847 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4849 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4851 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4853 return WERR_UNKNOWN_LEVEL;
4856 /********************************************************************
4857 * fill a DRIVER_INFO_1 struct
4858 ********************************************************************/
4860 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4862 init_unistr( &info->name, driver.info_3->name);
4865 /********************************************************************
4866 * construct_printer_driver_info_1
4867 ********************************************************************/
4869 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4871 NT_PRINTER_INFO_LEVEL *printer = NULL;
4872 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4874 ZERO_STRUCT(driver);
4876 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4877 return WERR_INVALID_PRINTER_NAME;
4879 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4880 return WERR_UNKNOWN_PRINTER_DRIVER;
4882 fill_printer_driver_info_1(info, driver, servername, architecture);
4884 free_a_printer(&printer,2);
4889 /********************************************************************
4890 * construct_printer_driver_info_2
4891 * fill a printer_info_2 struct
4892 ********************************************************************/
4894 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4898 info->version=driver.info_3->cversion;
4900 init_unistr( &info->name, driver.info_3->name );
4901 init_unistr( &info->architecture, driver.info_3->environment );
4904 if (strlen(driver.info_3->driverpath)) {
4905 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4906 init_unistr( &info->driverpath, temp );
4908 init_unistr( &info->driverpath, "" );
4910 if (strlen(driver.info_3->datafile)) {
4911 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4912 init_unistr( &info->datafile, temp );
4914 init_unistr( &info->datafile, "" );
4916 if (strlen(driver.info_3->configfile)) {
4917 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4918 init_unistr( &info->configfile, temp );
4920 init_unistr( &info->configfile, "" );
4923 /********************************************************************
4924 * construct_printer_driver_info_2
4925 * fill a printer_info_2 struct
4926 ********************************************************************/
4928 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4930 NT_PRINTER_INFO_LEVEL *printer = NULL;
4931 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4933 ZERO_STRUCT(printer);
4934 ZERO_STRUCT(driver);
4936 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4937 return WERR_INVALID_PRINTER_NAME;
4939 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4940 return WERR_UNKNOWN_PRINTER_DRIVER;
4942 fill_printer_driver_info_2(info, driver, servername);
4944 free_a_printer(&printer,2);
4949 /********************************************************************
4950 * copy a strings array and convert to UNICODE
4952 * convert an array of ascii string to a UNICODE string
4953 ********************************************************************/
4955 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
4963 DEBUG(6,("init_unistr_array\n"));
4974 v = ""; /* hack to handle null lists */
4977 /* hack to allow this to be used in places other than when generating
4978 the list of dependent files */
4981 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4985 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4987 /* add one extra unit16 for the second terminating NULL */
4989 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4990 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4998 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5003 /* special case for ""; we need to add both NULL's here */
5005 (*uni_array)[j++]=0x0000;
5006 (*uni_array)[j]=0x0000;
5009 DEBUGADD(6,("last one:done\n"));
5011 /* return size of array in uint16's */
5016 /********************************************************************
5017 * construct_printer_info_3
5018 * fill a printer_info_3 struct
5019 ********************************************************************/
5021 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5027 info->version=driver.info_3->cversion;
5029 init_unistr( &info->name, driver.info_3->name );
5030 init_unistr( &info->architecture, driver.info_3->environment );
5032 if (strlen(driver.info_3->driverpath)) {
5033 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5034 init_unistr( &info->driverpath, temp );
5036 init_unistr( &info->driverpath, "" );
5038 if (strlen(driver.info_3->datafile)) {
5039 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5040 init_unistr( &info->datafile, temp );
5042 init_unistr( &info->datafile, "" );
5044 if (strlen(driver.info_3->configfile)) {
5045 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5046 init_unistr( &info->configfile, temp );
5048 init_unistr( &info->configfile, "" );
5050 if (strlen(driver.info_3->helpfile)) {
5051 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5052 init_unistr( &info->helpfile, temp );
5054 init_unistr( &info->helpfile, "" );
5056 init_unistr( &info->monitorname, driver.info_3->monitorname );
5057 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5059 info->dependentfiles=NULL;
5060 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5063 /********************************************************************
5064 * construct_printer_info_3
5065 * fill a printer_info_3 struct
5066 ********************************************************************/
5068 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5070 NT_PRINTER_INFO_LEVEL *printer = NULL;
5071 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5073 ZERO_STRUCT(driver);
5075 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5076 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5077 if (!W_ERROR_IS_OK(status))
5078 return WERR_INVALID_PRINTER_NAME;
5080 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5081 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5086 * I put this code in during testing. Helpful when commenting out the
5087 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5088 * as win2k always queries the driver using an infor level of 6.
5089 * I've left it in (but ifdef'd out) because I'll probably
5090 * use it in experimentation again in the future. --jerry 22/01/2002
5093 if (!W_ERROR_IS_OK(status)) {
5095 * Is this a W2k client ?
5098 /* Yes - try again with a WinNT driver. */
5100 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5101 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5105 if (!W_ERROR_IS_OK(status)) {
5106 free_a_printer(&printer,2);
5107 return WERR_UNKNOWN_PRINTER_DRIVER;
5115 fill_printer_driver_info_3(info, driver, servername);
5117 free_a_printer(&printer,2);
5122 /********************************************************************
5123 * construct_printer_info_6
5124 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5125 ********************************************************************/
5127 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5133 memset(&nullstr, '\0', sizeof(fstring));
5135 info->version=driver.info_3->cversion;
5137 init_unistr( &info->name, driver.info_3->name );
5138 init_unistr( &info->architecture, driver.info_3->environment );
5140 if (strlen(driver.info_3->driverpath)) {
5141 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5142 init_unistr( &info->driverpath, temp );
5144 init_unistr( &info->driverpath, "" );
5146 if (strlen(driver.info_3->datafile)) {
5147 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5148 init_unistr( &info->datafile, temp );
5150 init_unistr( &info->datafile, "" );
5152 if (strlen(driver.info_3->configfile)) {
5153 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5154 init_unistr( &info->configfile, temp );
5156 init_unistr( &info->configfile, "" );
5158 if (strlen(driver.info_3->helpfile)) {
5159 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5160 init_unistr( &info->helpfile, temp );
5162 init_unistr( &info->helpfile, "" );
5164 init_unistr( &info->monitorname, driver.info_3->monitorname );
5165 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5167 info->dependentfiles = NULL;
5168 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5170 info->previousdrivernames=NULL;
5171 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5173 info->driver_date.low=0;
5174 info->driver_date.high=0;
5177 info->driver_version_low=0;
5178 info->driver_version_high=0;
5180 init_unistr( &info->mfgname, "");
5181 init_unistr( &info->oem_url, "");
5182 init_unistr( &info->hardware_id, "");
5183 init_unistr( &info->provider, "");
5186 /********************************************************************
5187 * construct_printer_info_6
5188 * fill a printer_info_6 struct
5189 ********************************************************************/
5191 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5192 fstring servername, fstring architecture, uint32 version)
5194 NT_PRINTER_INFO_LEVEL *printer = NULL;
5195 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5198 ZERO_STRUCT(driver);
5200 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5202 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5204 if (!W_ERROR_IS_OK(status))
5205 return WERR_INVALID_PRINTER_NAME;
5207 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5209 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5211 if (!W_ERROR_IS_OK(status))
5214 * Is this a W2k client ?
5218 free_a_printer(&printer,2);
5219 return WERR_UNKNOWN_PRINTER_DRIVER;
5222 /* Yes - try again with a WinNT driver. */
5224 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5225 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5226 if (!W_ERROR_IS_OK(status)) {
5227 free_a_printer(&printer,2);
5228 return WERR_UNKNOWN_PRINTER_DRIVER;
5232 fill_printer_driver_info_6(info, driver, servername);
5234 free_a_printer(&printer,2);
5235 free_a_printer_driver(driver, 3);
5240 /****************************************************************************
5241 ****************************************************************************/
5243 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5245 SAFE_FREE(info->dependentfiles);
5248 /****************************************************************************
5249 ****************************************************************************/
5251 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5253 SAFE_FREE(info->dependentfiles);
5257 /****************************************************************************
5258 ****************************************************************************/
5260 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5262 DRIVER_INFO_1 *info=NULL;
5265 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5268 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5269 if (!W_ERROR_IS_OK(status)) {
5274 /* check the required size. */
5275 *needed += spoolss_size_printer_driver_info_1(info);
5277 if (!alloc_buffer_size(buffer, *needed)) {
5279 return WERR_INSUFFICIENT_BUFFER;
5282 /* fill the buffer with the structures */
5283 smb_io_printer_driver_info_1("", buffer, info, 0);
5288 if (*needed > offered)
5289 return WERR_INSUFFICIENT_BUFFER;
5294 /****************************************************************************
5295 ****************************************************************************/
5297 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5299 DRIVER_INFO_2 *info=NULL;
5302 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5305 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5306 if (!W_ERROR_IS_OK(status)) {
5311 /* check the required size. */
5312 *needed += spoolss_size_printer_driver_info_2(info);
5314 if (!alloc_buffer_size(buffer, *needed)) {
5316 return WERR_INSUFFICIENT_BUFFER;
5319 /* fill the buffer with the structures */
5320 smb_io_printer_driver_info_2("", buffer, info, 0);
5325 if (*needed > offered)
5326 return WERR_INSUFFICIENT_BUFFER;
5331 /****************************************************************************
5332 ****************************************************************************/
5334 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5341 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5342 if (!W_ERROR_IS_OK(status)) {
5346 /* check the required size. */
5347 *needed += spoolss_size_printer_driver_info_3(&info);
5349 if (!alloc_buffer_size(buffer, *needed)) {
5350 free_printer_driver_info_3(&info);
5351 return WERR_INSUFFICIENT_BUFFER;
5354 /* fill the buffer with the structures */
5355 smb_io_printer_driver_info_3("", buffer, &info, 0);
5357 free_printer_driver_info_3(&info);
5359 if (*needed > offered)
5360 return WERR_INSUFFICIENT_BUFFER;
5365 /****************************************************************************
5366 ****************************************************************************/
5368 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5375 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5376 if (!W_ERROR_IS_OK(status)) {
5380 /* check the required size. */
5381 *needed += spoolss_size_printer_driver_info_6(&info);
5383 if (!alloc_buffer_size(buffer, *needed)) {
5384 free_printer_driver_info_6(&info);
5385 return WERR_INSUFFICIENT_BUFFER;
5388 /* fill the buffer with the structures */
5389 smb_io_printer_driver_info_6("", buffer, &info, 0);
5391 free_printer_driver_info_6(&info);
5393 if (*needed > offered)
5394 return WERR_INSUFFICIENT_BUFFER;
5399 /****************************************************************************
5400 ****************************************************************************/
5402 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5404 POLICY_HND *handle = &q_u->handle;
5405 UNISTR2 *uni_arch = &q_u->architecture;
5406 uint32 level = q_u->level;
5407 uint32 clientmajorversion = q_u->clientmajorversion;
5408 NEW_BUFFER *buffer = NULL;
5409 uint32 offered = q_u->offered;
5410 uint32 *needed = &r_u->needed;
5411 uint32 *servermajorversion = &r_u->servermajorversion;
5412 uint32 *serverminorversion = &r_u->serverminorversion;
5415 fstring architecture;
5418 /* that's an [in out] buffer */
5419 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5420 buffer = r_u->buffer;
5422 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5425 *servermajorversion = 0;
5426 *serverminorversion = 0;
5428 fstrcpy(servername, get_called_name());
5429 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5431 if (!get_printer_snum(p, handle, &snum))
5436 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5438 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5440 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5442 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5445 return WERR_UNKNOWN_LEVEL;
5448 /****************************************************************************
5449 ****************************************************************************/
5451 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5453 POLICY_HND *handle = &q_u->handle;
5455 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5458 DEBUG(3,("Error in startpageprinter printer handle\n"));
5462 Printer->page_started=True;
5466 /****************************************************************************
5467 ****************************************************************************/
5469 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5471 POLICY_HND *handle = &q_u->handle;
5474 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5477 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5481 if (!get_printer_snum(p, handle, &snum))
5484 Printer->page_started=False;
5485 print_job_endpage(snum, Printer->jobid);
5490 /********************************************************************
5491 * api_spoolss_getprinter
5492 * called from the spoolss dispatcher
5494 ********************************************************************/
5496 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5498 POLICY_HND *handle = &q_u->handle;
5499 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5500 uint32 *jobid = &r_u->jobid;
5502 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5506 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5507 struct current_user user;
5510 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5514 get_current_user(&user, p);
5517 * a nice thing with NT is it doesn't listen to what you tell it.
5518 * when asked to send _only_ RAW datas, it tries to send datas
5521 * So I add checks like in NT Server ...
5524 if (info_1->p_datatype != 0) {
5525 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5526 if (strcmp(datatype, "RAW") != 0) {
5528 return WERR_INVALID_DATATYPE;
5532 /* get the share number of the printer */
5533 if (!get_printer_snum(p, handle, &snum)) {
5537 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5539 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5541 /* An error occured in print_job_start() so return an appropriate
5544 if (Printer->jobid == -1) {
5545 return map_werror_from_unix(errno);
5548 Printer->document_started=True;
5549 (*jobid) = Printer->jobid;
5554 /********************************************************************
5555 * api_spoolss_getprinter
5556 * called from the spoolss dispatcher
5558 ********************************************************************/
5560 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5562 POLICY_HND *handle = &q_u->handle;
5564 return _spoolss_enddocprinter_internal(p, handle);
5567 /****************************************************************************
5568 ****************************************************************************/
5570 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5572 POLICY_HND *handle = &q_u->handle;
5573 uint32 buffer_size = q_u->buffer_size;
5574 uint8 *buffer = q_u->buffer;
5575 uint32 *buffer_written = &q_u->buffer_size2;
5577 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5580 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5581 r_u->buffer_written = q_u->buffer_size2;
5585 if (!get_printer_snum(p, handle, &snum))
5588 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5589 if (*buffer_written == -1) {
5590 r_u->buffer_written = 0;
5591 if (errno == ENOSPC)
5592 return WERR_NO_SPOOL_SPACE;
5594 return WERR_ACCESS_DENIED;
5597 r_u->buffer_written = q_u->buffer_size2;
5602 /********************************************************************
5603 * api_spoolss_getprinter
5604 * called from the spoolss dispatcher
5606 ********************************************************************/
5608 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5611 struct current_user user;
5613 WERROR errcode = WERR_BADFUNC;
5614 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5616 get_current_user(&user, p);
5619 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5623 if (!get_printer_snum(p, handle, &snum))
5627 case PRINTER_CONTROL_PAUSE:
5628 if (print_queue_pause(&user, snum, &errcode)) {
5632 case PRINTER_CONTROL_RESUME:
5633 case PRINTER_CONTROL_UNPAUSE:
5634 if (print_queue_resume(&user, snum, &errcode)) {
5638 case PRINTER_CONTROL_PURGE:
5639 if (print_queue_purge(&user, snum, &errcode)) {
5644 return WERR_UNKNOWN_LEVEL;
5650 /********************************************************************
5651 * api_spoolss_abortprinter
5652 * From MSDN: "Deletes printer's spool file if printer is configured
5654 ********************************************************************/
5656 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5658 POLICY_HND *handle = &q_u->handle;
5659 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5661 struct current_user user;
5662 WERROR errcode = WERR_OK;
5665 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5669 if (!get_printer_snum(p, handle, &snum))
5672 get_current_user( &user, p );
5674 print_job_delete( &user, snum, Printer->jobid, &errcode );
5679 /********************************************************************
5680 * called by spoolss_api_setprinter
5681 * when updating a printer description
5682 ********************************************************************/
5684 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5685 const SPOOL_PRINTER_INFO_LEVEL *info,
5686 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5688 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5689 struct current_user user;
5693 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5695 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5696 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5697 OUR_HANDLE(handle)));
5699 result = WERR_BADFID;
5703 /* NT seems to like setting the security descriptor even though
5704 nothing may have actually changed. This causes annoying
5705 dialog boxes when the user doesn't have permission to change
5706 the security descriptor. */
5708 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5710 if (DEBUGLEVEL >= 10) {
5714 the_acl = old_secdesc_ctr->sec->dacl;
5715 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5716 PRINTERNAME(snum), the_acl->num_aces));
5718 for (i = 0; i < the_acl->num_aces; i++) {
5721 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5723 DEBUG(10, ("%s 0x%08x\n", sid_str,
5724 the_acl->ace[i].info.mask));
5727 the_acl = secdesc_ctr->sec->dacl;
5730 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5731 PRINTERNAME(snum), the_acl->num_aces));
5733 for (i = 0; i < the_acl->num_aces; i++) {
5736 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5738 DEBUG(10, ("%s 0x%08x\n", sid_str,
5739 the_acl->ace[i].info.mask));
5742 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5746 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5748 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5753 /* Work out which user is performing the operation */
5755 get_current_user(&user, p);
5757 /* Check the user has permissions to change the security
5758 descriptor. By experimentation with two NT machines, the user
5759 requires Full Access to the printer to change security
5762 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5763 result = WERR_ACCESS_DENIED;
5767 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5774 /********************************************************************
5775 Do Samba sanity checks on a printer info struct.
5776 this has changed purpose: it now "canonicalises" printer
5777 info from a client rather than just checking it is correct
5778 ********************************************************************/
5780 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5782 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5783 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5785 /* we force some elements to "correct" values */
5786 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5787 fstrcpy(info->sharename, lp_servicename(snum));
5788 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5789 get_called_name(), info->sharename);
5790 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5796 /****************************************************************************
5797 ****************************************************************************/
5799 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5801 extern userdom_struct current_user_info;
5802 char *cmd = lp_addprinter_cmd();
5808 fstring remote_machine = "%m";
5810 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5812 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5813 cmd, printer->info_2->printername, printer->info_2->sharename,
5814 printer->info_2->portname, printer->info_2->drivername,
5815 printer->info_2->location, printer->info_2->comment, remote_machine);
5817 DEBUG(10,("Running [%s]\n", command));
5818 ret = smbrun(command, &fd);
5819 DEBUGADD(10,("returned [%d]\n", ret));
5828 /* Get lines and convert them back to dos-codepage */
5829 qlines = fd_lines_load(fd, &numlines);
5830 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5834 /* Set the portname to what the script says the portname should be. */
5835 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5836 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5838 /* Send SIGHUP to process group... is there a better way? */
5841 /* reload our services immediately */
5842 reload_services( False );
5845 file_lines_free(qlines);
5849 /********************************************************************
5850 * Called by spoolss_api_setprinter
5851 * when updating a printer description.
5852 ********************************************************************/
5854 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5855 const SPOOL_PRINTER_INFO_LEVEL *info,
5856 DEVICEMODE *devmode)
5859 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5860 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5865 DEBUG(8,("update_printer\n"));
5870 result = WERR_BADFID;
5874 if (!get_printer_snum(p, handle, &snum)) {
5875 result = WERR_BADFID;
5879 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5880 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5881 result = WERR_BADFID;
5885 DEBUGADD(8,("Converting info_2 struct\n"));
5888 * convert_printer_info converts the incoming
5889 * info from the client and overwrites the info
5890 * just read from the tdb in the pointer 'printer'.
5893 if (!convert_printer_info(info, printer, level)) {
5894 result = WERR_NOMEM;
5899 /* we have a valid devmode
5900 convert it and link it*/
5902 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5903 if (!convert_devicemode(printer->info_2->printername, devmode,
5904 &printer->info_2->devmode)) {
5905 result = WERR_NOMEM;
5910 /* Do sanity check on the requested changes for Samba */
5912 if (!check_printer_ok(printer->info_2, snum)) {
5913 result = WERR_INVALID_PARAM;
5917 /* FIXME!!! If the driver has changed we really should verify that
5918 it is installed before doing much else --jerry */
5920 /* Check calling user has permission to update printer description */
5922 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5923 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5924 result = WERR_ACCESS_DENIED;
5928 /* Call addprinter hook */
5929 /* Check changes to see if this is really needed */
5931 if ( *lp_addprinter_cmd()
5932 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5933 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5934 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5935 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5937 if ( !add_printer_hook(printer) ) {
5938 result = WERR_ACCESS_DENIED;
5943 * make sure we actually reload the services after
5944 * this as smb.conf could have a new section in it
5945 * .... shouldn't .... but could
5947 reload_services(False);
5951 * When a *new* driver is bound to a printer, the drivername is used to
5952 * lookup previously saved driver initialization info, which is then
5953 * bound to the printer, simulating what happens in the Windows arch.
5955 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5957 if (!set_driver_init(printer, 2))
5959 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5960 printer->info_2->drivername));
5963 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5964 printer->info_2->drivername));
5966 notify_printer_driver(snum, printer->info_2->drivername);
5970 * flag which changes actually occured. This is a small subset of
5971 * all the possible changes. We also have to update things in the
5975 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5976 init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 );
5977 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5978 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5980 notify_printer_comment(snum, printer->info_2->comment);
5983 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5984 init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 );
5985 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5986 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5987 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5988 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5990 notify_printer_sharename(snum, printer->info_2->sharename);
5993 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5994 init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 );
5995 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5996 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5998 notify_printer_port(snum, printer->info_2->portname);
6001 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6002 init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 );
6003 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6004 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6006 notify_printer_location(snum, printer->info_2->location);
6009 /* here we need to update some more DsSpooler keys */
6010 /* uNCName, serverName, shortServerName */
6012 init_unistr2( &buffer, global_myname(), strlen(global_myname())+1 );
6013 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6014 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6015 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6016 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6018 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6019 global_myname(), printer->info_2->sharename );
6020 init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 );
6021 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6022 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6024 /* Update printer info */
6025 result = mod_a_printer(*printer, 2);
6028 free_a_printer(&printer, 2);
6029 free_a_printer(&old_printer, 2);
6035 /****************************************************************************
6036 ****************************************************************************/
6037 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6038 const SPOOL_PRINTER_INFO_LEVEL *info)
6041 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6043 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6046 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6053 if (!get_printer_snum(p, handle, &snum))
6056 nt_printer_publish(Printer, snum, info7->action);
6060 return WERR_UNKNOWN_LEVEL;
6063 /****************************************************************************
6064 ****************************************************************************/
6066 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6068 POLICY_HND *handle = &q_u->handle;
6069 uint32 level = q_u->level;
6070 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6071 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6072 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6073 uint32 command = q_u->command;
6075 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6078 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6082 /* check the level */
6085 return control_printer(handle, command, p);
6087 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6089 return update_printer_sec(handle, level, info, p,
6092 return publish_or_unpublish_printer(p, handle, info);
6094 return WERR_UNKNOWN_LEVEL;
6098 /****************************************************************************
6099 ****************************************************************************/
6101 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6103 POLICY_HND *handle = &q_u->handle;
6104 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6107 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6111 if (Printer->notify.client_connected==True) {
6114 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6116 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6117 !get_printer_snum(p, handle, &snum) )
6120 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6123 Printer->notify.flags=0;
6124 Printer->notify.options=0;
6125 Printer->notify.localmachine[0]='\0';
6126 Printer->notify.printerlocal=0;
6127 if (Printer->notify.option)
6128 free_spool_notify_option(&Printer->notify.option);
6129 Printer->notify.client_connected=False;
6134 /****************************************************************************
6135 ****************************************************************************/
6137 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6139 /* that's an [in out] buffer (despite appearences to the contrary) */
6140 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6143 return WERR_INVALID_PARAM; /* this is what a NT server
6144 returns for AddJob. AddJob
6145 must fail on non-local
6149 /****************************************************************************
6150 ****************************************************************************/
6152 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6153 int position, int snum)
6159 t=gmtime(&queue->time);
6160 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6162 job_info->jobid=queue->job;
6163 init_unistr(&job_info->printername, lp_servicename(snum));
6164 init_unistr(&job_info->machinename, temp_name);
6165 init_unistr(&job_info->username, queue->fs_user);
6166 init_unistr(&job_info->document, queue->fs_file);
6167 init_unistr(&job_info->datatype, "RAW");
6168 init_unistr(&job_info->text_status, "");
6169 job_info->status=nt_printj_status(queue->status);
6170 job_info->priority=queue->priority;
6171 job_info->position=position;
6172 job_info->totalpages=queue->page_count;
6173 job_info->pagesprinted=0;
6175 make_systemtime(&job_info->submitted, t);
6178 /****************************************************************************
6179 ****************************************************************************/
6181 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6182 int position, int snum,
6183 NT_PRINTER_INFO_LEVEL *ntprinter,
6184 DEVICEMODE *devmode)
6189 t=gmtime(&queue->time);
6190 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6192 job_info->jobid=queue->job;
6194 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6196 init_unistr(&job_info->machinename, temp_name);
6197 init_unistr(&job_info->username, queue->fs_user);
6198 init_unistr(&job_info->document, queue->fs_file);
6199 init_unistr(&job_info->notifyname, queue->fs_user);
6200 init_unistr(&job_info->datatype, "RAW");
6201 init_unistr(&job_info->printprocessor, "winprint");
6202 init_unistr(&job_info->parameters, "");
6203 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6204 init_unistr(&job_info->text_status, "");
6206 /* and here the security descriptor */
6208 job_info->status=nt_printj_status(queue->status);
6209 job_info->priority=queue->priority;
6210 job_info->position=position;
6211 job_info->starttime=0;
6212 job_info->untiltime=0;
6213 job_info->totalpages=queue->page_count;
6214 job_info->size=queue->size;
6215 make_systemtime(&(job_info->submitted), t);
6216 job_info->timeelapsed=0;
6217 job_info->pagesprinted=0;
6219 job_info->devmode = devmode;
6224 /****************************************************************************
6225 Enumjobs at level 1.
6226 ****************************************************************************/
6228 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6229 NEW_BUFFER *buffer, uint32 offered,
6230 uint32 *needed, uint32 *returned)
6235 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6242 for (i=0; i<*returned; i++)
6243 fill_job_info_1(&info[i], &queue[i], i, snum);
6247 /* check the required size. */
6248 for (i=0; i<*returned; i++)
6249 (*needed) += spoolss_size_job_info_1(&info[i]);
6251 if (!alloc_buffer_size(buffer, *needed)) {
6253 return WERR_INSUFFICIENT_BUFFER;
6256 /* fill the buffer with the structures */
6257 for (i=0; i<*returned; i++)
6258 smb_io_job_info_1("", buffer, &info[i], 0);
6263 if (*needed > offered) {
6265 return WERR_INSUFFICIENT_BUFFER;
6271 /****************************************************************************
6272 Enumjobs at level 2.
6273 ****************************************************************************/
6275 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6276 NEW_BUFFER *buffer, uint32 offered,
6277 uint32 *needed, uint32 *returned)
6279 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6280 JOB_INFO_2 *info = NULL;
6283 DEVICEMODE *devmode = NULL;
6285 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6288 result = WERR_NOMEM;
6292 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6293 if (!W_ERROR_IS_OK(result)) {
6298 /* this should not be a failure condition if the devmode is NULL */
6300 devmode = construct_dev_mode(snum);
6302 for (i=0; i<*returned; i++)
6303 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6306 free_a_printer(&ntprinter, 2);
6309 /* check the required size. */
6310 for (i=0; i<*returned; i++)
6311 (*needed) += spoolss_size_job_info_2(&info[i]);
6313 if (*needed > offered) {
6315 result = WERR_INSUFFICIENT_BUFFER;
6319 if (!alloc_buffer_size(buffer, *needed)) {
6321 result = WERR_INSUFFICIENT_BUFFER;
6325 /* fill the buffer with the structures */
6326 for (i=0; i<*returned; i++)
6327 smb_io_job_info_2("", buffer, &info[i], 0);
6332 free_a_printer(&ntprinter, 2);
6333 free_devmode(devmode);
6341 /****************************************************************************
6343 ****************************************************************************/
6345 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6347 POLICY_HND *handle = &q_u->handle;
6348 uint32 level = q_u->level;
6349 NEW_BUFFER *buffer = NULL;
6350 uint32 offered = q_u->offered;
6351 uint32 *needed = &r_u->needed;
6352 uint32 *returned = &r_u->returned;
6355 print_status_struct prt_status;
6356 print_queue_struct *queue=NULL;
6358 /* that's an [in out] buffer */
6359 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6360 buffer = r_u->buffer;
6362 DEBUG(4,("_spoolss_enumjobs\n"));
6367 if (!get_printer_snum(p, handle, &snum))
6370 *returned = print_queue_status(snum, &queue, &prt_status);
6371 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6373 if (*returned == 0) {
6380 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6382 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6386 return WERR_UNKNOWN_LEVEL;
6390 /****************************************************************************
6391 ****************************************************************************/
6393 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6398 /****************************************************************************
6399 ****************************************************************************/
6401 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6403 POLICY_HND *handle = &q_u->handle;
6404 uint32 jobid = q_u->jobid;
6405 uint32 command = q_u->command;
6407 struct current_user user;
6409 WERROR errcode = WERR_BADFUNC;
6411 if (!get_printer_snum(p, handle, &snum)) {
6415 if (!print_job_exists(snum, jobid)) {
6416 return WERR_INVALID_PRINTER_NAME;
6419 get_current_user(&user, p);
6422 case JOB_CONTROL_CANCEL:
6423 case JOB_CONTROL_DELETE:
6424 if (print_job_delete(&user, snum, jobid, &errcode)) {
6428 case JOB_CONTROL_PAUSE:
6429 if (print_job_pause(&user, snum, jobid, &errcode)) {
6433 case JOB_CONTROL_RESTART:
6434 case JOB_CONTROL_RESUME:
6435 if (print_job_resume(&user, snum, jobid, &errcode)) {
6440 return WERR_UNKNOWN_LEVEL;
6446 /****************************************************************************
6447 Enumerates all printer drivers at level 1.
6448 ****************************************************************************/
6450 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6455 fstring *list = NULL;
6457 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6458 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6462 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6464 ndrivers=get_ntdrivers(&list, architecture, version);
6465 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6471 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6472 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6473 SAFE_FREE(driver_info_1);
6477 else driver_info_1 = tdi1;
6480 for (i=0; i<ndrivers; i++) {
6482 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6483 ZERO_STRUCT(driver);
6484 status = get_a_printer_driver(&driver, 3, list[i],
6485 architecture, version);
6486 if (!W_ERROR_IS_OK(status)) {
6490 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6491 free_a_printer_driver(driver, 3);
6494 *returned+=ndrivers;
6498 /* check the required size. */
6499 for (i=0; i<*returned; i++) {
6500 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6501 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6504 if (!alloc_buffer_size(buffer, *needed)) {
6505 SAFE_FREE(driver_info_1);
6506 return WERR_INSUFFICIENT_BUFFER;
6509 /* fill the buffer with the driver structures */
6510 for (i=0; i<*returned; i++) {
6511 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6512 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6515 SAFE_FREE(driver_info_1);
6517 if (*needed > offered) {
6519 return WERR_INSUFFICIENT_BUFFER;
6525 /****************************************************************************
6526 Enumerates all printer drivers at level 2.
6527 ****************************************************************************/
6529 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6534 fstring *list = NULL;
6536 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6537 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6541 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6543 ndrivers=get_ntdrivers(&list, architecture, version);
6544 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6550 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6551 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6552 SAFE_FREE(driver_info_2);
6556 else driver_info_2 = tdi2;
6559 for (i=0; i<ndrivers; i++) {
6562 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6563 ZERO_STRUCT(driver);
6564 status = get_a_printer_driver(&driver, 3, list[i],
6565 architecture, version);
6566 if (!W_ERROR_IS_OK(status)) {
6570 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6571 free_a_printer_driver(driver, 3);
6574 *returned+=ndrivers;
6578 /* check the required size. */
6579 for (i=0; i<*returned; i++) {
6580 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6581 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6584 if (!alloc_buffer_size(buffer, *needed)) {
6585 SAFE_FREE(driver_info_2);
6586 return WERR_INSUFFICIENT_BUFFER;
6589 /* fill the buffer with the form structures */
6590 for (i=0; i<*returned; i++) {
6591 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6592 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6595 SAFE_FREE(driver_info_2);
6597 if (*needed > offered) {
6599 return WERR_INSUFFICIENT_BUFFER;
6605 /****************************************************************************
6606 Enumerates all printer drivers at level 3.
6607 ****************************************************************************/
6609 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6614 fstring *list = NULL;
6616 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6617 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6621 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6623 ndrivers=get_ntdrivers(&list, architecture, version);
6624 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6630 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6631 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6632 SAFE_FREE(driver_info_3);
6636 else driver_info_3 = tdi3;
6639 for (i=0; i<ndrivers; i++) {
6642 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6643 ZERO_STRUCT(driver);
6644 status = get_a_printer_driver(&driver, 3, list[i],
6645 architecture, version);
6646 if (!W_ERROR_IS_OK(status)) {
6650 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6651 free_a_printer_driver(driver, 3);
6654 *returned+=ndrivers;
6658 /* check the required size. */
6659 for (i=0; i<*returned; i++) {
6660 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6661 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6664 if (!alloc_buffer_size(buffer, *needed)) {
6665 SAFE_FREE(driver_info_3);
6666 return WERR_INSUFFICIENT_BUFFER;
6669 /* fill the buffer with the driver structures */
6670 for (i=0; i<*returned; i++) {
6671 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6672 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6675 for (i=0; i<*returned; i++)
6676 SAFE_FREE(driver_info_3[i].dependentfiles);
6678 SAFE_FREE(driver_info_3);
6680 if (*needed > offered) {
6682 return WERR_INSUFFICIENT_BUFFER;
6688 /****************************************************************************
6689 Enumerates all printer drivers.
6690 ****************************************************************************/
6692 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6694 UNISTR2 *environment = &q_u->environment;
6695 uint32 level = q_u->level;
6696 NEW_BUFFER *buffer = NULL;
6697 uint32 offered = q_u->offered;
6698 uint32 *needed = &r_u->needed;
6699 uint32 *returned = &r_u->returned;
6701 fstring *list = NULL;
6703 fstring architecture;
6705 /* that's an [in out] buffer */
6706 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6707 buffer = r_u->buffer;
6709 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6710 fstrcpy(servername, get_called_name());
6714 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6718 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6720 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6722 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6726 return WERR_UNKNOWN_LEVEL;
6730 /****************************************************************************
6731 ****************************************************************************/
6733 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6735 form->flag=list->flag;
6736 init_unistr(&form->name, list->name);
6737 form->width=list->width;
6738 form->length=list->length;
6739 form->left=list->left;
6740 form->top=list->top;
6741 form->right=list->right;
6742 form->bottom=list->bottom;
6745 /****************************************************************************
6746 ****************************************************************************/
6748 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6750 uint32 level = q_u->level;
6751 NEW_BUFFER *buffer = NULL;
6752 uint32 offered = q_u->offered;
6753 uint32 *needed = &r_u->needed;
6754 uint32 *numofforms = &r_u->numofforms;
6755 uint32 numbuiltinforms;
6757 nt_forms_struct *list=NULL;
6758 nt_forms_struct *builtinlist=NULL;
6763 /* that's an [in out] buffer */
6764 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6765 buffer = r_u->buffer;
6767 DEBUG(4,("_spoolss_enumforms\n"));
6768 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6769 DEBUGADD(5,("Info level [%d]\n", level));
6771 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6772 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6773 *numofforms = get_ntforms(&list);
6774 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6775 *numofforms += numbuiltinforms;
6777 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6781 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6786 /* construct the list of form structures */
6787 for (i=0; i<numbuiltinforms; i++) {
6788 DEBUGADD(6,("Filling form number [%d]\n",i));
6789 fill_form_1(&forms_1[i], &builtinlist[i]);
6792 SAFE_FREE(builtinlist);
6794 for (; i<*numofforms; i++) {
6795 DEBUGADD(6,("Filling form number [%d]\n",i));
6796 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6801 /* check the required size. */
6802 for (i=0; i<numbuiltinforms; i++) {
6803 DEBUGADD(6,("adding form [%d]'s size\n",i));
6804 buffer_size += spoolss_size_form_1(&forms_1[i]);
6806 for (; i<*numofforms; i++) {
6807 DEBUGADD(6,("adding form [%d]'s size\n",i));
6808 buffer_size += spoolss_size_form_1(&forms_1[i]);
6811 *needed=buffer_size;
6813 if (!alloc_buffer_size(buffer, buffer_size)){
6815 return WERR_INSUFFICIENT_BUFFER;
6818 /* fill the buffer with the form structures */
6819 for (i=0; i<numbuiltinforms; i++) {
6820 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6821 smb_io_form_1("", buffer, &forms_1[i], 0);
6823 for (; i<*numofforms; i++) {
6824 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6825 smb_io_form_1("", buffer, &forms_1[i], 0);
6830 if (*needed > offered) {
6832 return WERR_INSUFFICIENT_BUFFER;
6839 SAFE_FREE(builtinlist);
6840 return WERR_UNKNOWN_LEVEL;
6845 /****************************************************************************
6846 ****************************************************************************/
6848 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6850 uint32 level = q_u->level;
6851 UNISTR2 *uni_formname = &q_u->formname;
6852 NEW_BUFFER *buffer = NULL;
6853 uint32 offered = q_u->offered;
6854 uint32 *needed = &r_u->needed;
6856 nt_forms_struct *list=NULL;
6857 nt_forms_struct builtin_form;
6862 int numofforms=0, i=0;
6864 /* that's an [in out] buffer */
6865 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6866 buffer = r_u->buffer;
6868 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6870 DEBUG(4,("_spoolss_getform\n"));
6871 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6872 DEBUGADD(5,("Info level [%d]\n", level));
6874 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6875 if (!foundBuiltin) {
6876 numofforms = get_ntforms(&list);
6877 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6879 if (numofforms == 0)
6886 fill_form_1(&form_1, &builtin_form);
6889 /* Check if the requested name is in the list of form structures */
6890 for (i=0; i<numofforms; i++) {
6892 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6894 if (strequal(form_name, list[i].name)) {
6895 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6896 fill_form_1(&form_1, &list[i]);
6902 if (i == numofforms) {
6906 /* check the required size. */
6908 *needed=spoolss_size_form_1(&form_1);
6910 if (!alloc_buffer_size(buffer, buffer_size)){
6911 return WERR_INSUFFICIENT_BUFFER;
6914 if (*needed > offered) {
6915 return WERR_INSUFFICIENT_BUFFER;
6918 /* fill the buffer with the form structures */
6919 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6920 smb_io_form_1("", buffer, &form_1, 0);
6926 return WERR_UNKNOWN_LEVEL;
6930 /****************************************************************************
6931 ****************************************************************************/
6933 static void fill_port_1(PORT_INFO_1 *port, const char *name)
6935 init_unistr(&port->port_name, name);
6938 /****************************************************************************
6939 ****************************************************************************/
6941 static void fill_port_2(PORT_INFO_2 *port, const char *name)
6943 init_unistr(&port->port_name, name);
6944 init_unistr(&port->monitor_name, "Local Monitor");
6945 init_unistr(&port->description, "Local Port");
6946 #define PORT_TYPE_WRITE 1
6947 port->port_type=PORT_TYPE_WRITE;
6951 /****************************************************************************
6953 ****************************************************************************/
6955 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6957 PORT_INFO_1 *ports=NULL;
6960 if (*lp_enumports_cmd()) {
6961 char *cmd = lp_enumports_cmd();
6968 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6970 DEBUG(10,("Running [%s]\n", command));
6971 ret = smbrun(command, &fd);
6972 DEBUG(10,("Returned [%d]\n", ret));
6976 /* Is this the best error to return here? */
6977 return WERR_ACCESS_DENIED;
6981 qlines = fd_lines_load(fd, &numlines);
6982 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6986 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6987 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6988 dos_errstr(WERR_NOMEM)));
6989 file_lines_free(qlines);
6993 for (i=0; i<numlines; i++) {
6994 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6995 fill_port_1(&ports[i], qlines[i]);
6998 file_lines_free(qlines);
7001 *returned = numlines;
7004 *returned = 1; /* Sole Samba port returned. */
7006 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7009 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7011 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7014 /* check the required size. */
7015 for (i=0; i<*returned; i++) {
7016 DEBUGADD(6,("adding port [%d]'s size\n", i));
7017 *needed += spoolss_size_port_info_1(&ports[i]);
7020 if (!alloc_buffer_size(buffer, *needed)) {
7022 return WERR_INSUFFICIENT_BUFFER;
7025 /* fill the buffer with the ports structures */
7026 for (i=0; i<*returned; i++) {
7027 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7028 smb_io_port_1("", buffer, &ports[i], 0);
7033 if (*needed > offered) {
7035 return WERR_INSUFFICIENT_BUFFER;
7041 /****************************************************************************
7043 ****************************************************************************/
7045 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7047 PORT_INFO_2 *ports=NULL;
7050 if (*lp_enumports_cmd()) {
7051 char *cmd = lp_enumports_cmd();
7060 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7061 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7063 path = lp_lockdir();
7065 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7066 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7069 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7070 ret = smbrun(command, &fd);
7071 DEBUGADD(10,("returned [%d]\n", ret));
7075 /* Is this the best error to return here? */
7076 return WERR_ACCESS_DENIED;
7080 qlines = fd_lines_load(fd, &numlines);
7081 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7085 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7086 file_lines_free(qlines);
7090 for (i=0; i<numlines; i++) {
7091 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7092 fill_port_2(&(ports[i]), qlines[i]);
7095 file_lines_free(qlines);
7098 *returned = numlines;
7104 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7107 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7109 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7112 /* check the required size. */
7113 for (i=0; i<*returned; i++) {
7114 DEBUGADD(6,("adding port [%d]'s size\n", i));
7115 *needed += spoolss_size_port_info_2(&ports[i]);
7118 if (!alloc_buffer_size(buffer, *needed)) {
7120 return WERR_INSUFFICIENT_BUFFER;
7123 /* fill the buffer with the ports structures */
7124 for (i=0; i<*returned; i++) {
7125 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7126 smb_io_port_2("", buffer, &ports[i], 0);
7131 if (*needed > offered) {
7133 return WERR_INSUFFICIENT_BUFFER;
7139 /****************************************************************************
7141 ****************************************************************************/
7143 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7145 uint32 level = q_u->level;
7146 NEW_BUFFER *buffer = NULL;
7147 uint32 offered = q_u->offered;
7148 uint32 *needed = &r_u->needed;
7149 uint32 *returned = &r_u->returned;
7151 /* that's an [in out] buffer */
7152 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7153 buffer = r_u->buffer;
7155 DEBUG(4,("_spoolss_enumports\n"));
7162 return enumports_level_1(buffer, offered, needed, returned);
7164 return enumports_level_2(buffer, offered, needed, returned);
7166 return WERR_UNKNOWN_LEVEL;
7170 /****************************************************************************
7171 ****************************************************************************/
7173 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7174 const SPOOL_PRINTER_INFO_LEVEL *info,
7175 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7176 uint32 user_switch, const SPOOL_USER_CTR *user,
7179 NT_PRINTER_INFO_LEVEL *printer = NULL;
7182 WERROR err = WERR_OK;
7184 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7185 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7189 ZERO_STRUCTP(printer);
7191 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7192 if (!convert_printer_info(info, printer, 2)) {
7193 free_a_printer(&printer, 2);
7197 /* check to see if the printer already exists */
7199 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7200 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7201 printer->info_2->sharename));
7202 free_a_printer(&printer, 2);
7203 return WERR_PRINTER_ALREADY_EXISTS;
7206 /* FIXME!!! smbd should check to see if the driver is installed before
7207 trying to add a printer like this --jerry */
7209 if (*lp_addprinter_cmd() ) {
7210 if ( !add_printer_hook(printer) ) {
7211 free_a_printer(&printer,2);
7212 return WERR_ACCESS_DENIED;
7216 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7217 printer->info_2->sharename);
7220 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7221 free_a_printer(&printer,2);
7222 return WERR_ACCESS_DENIED;
7225 /* you must be a printer admin to add a new printer */
7226 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7227 free_a_printer(&printer,2);
7228 return WERR_ACCESS_DENIED;
7232 * Do sanity check on the requested changes for Samba.
7235 if (!check_printer_ok(printer->info_2, snum)) {
7236 free_a_printer(&printer,2);
7237 return WERR_INVALID_PARAM;
7241 * When a printer is created, the drivername bound to the printer is used
7242 * to lookup previously saved driver initialization info, which is then
7243 * bound to the new printer, simulating what happens in the Windows arch.
7248 set_driver_init(printer, 2);
7252 /* A valid devmode was included, convert and link it
7254 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7256 if (!convert_devicemode(printer->info_2->printername, devmode,
7257 &printer->info_2->devmode))
7261 /* write the ASCII on disk */
7262 err = mod_a_printer(*printer, 2);
7263 if (!W_ERROR_IS_OK(err)) {
7264 free_a_printer(&printer,2);
7268 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7269 /* Handle open failed - remove addition. */
7270 del_a_printer(printer->info_2->sharename);
7271 free_a_printer(&printer,2);
7272 return WERR_ACCESS_DENIED;
7275 update_c_setprinter(False);
7276 free_a_printer(&printer,2);
7281 /****************************************************************************
7282 ****************************************************************************/
7284 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7286 UNISTR2 *uni_srv_name = &q_u->server_name;
7287 uint32 level = q_u->level;
7288 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7289 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7290 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7291 uint32 user_switch = q_u->user_switch;
7292 SPOOL_USER_CTR *user = &q_u->user_ctr;
7293 POLICY_HND *handle = &r_u->handle;
7297 /* we don't handle yet */
7298 /* but I know what to do ... */
7299 return WERR_UNKNOWN_LEVEL;
7301 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7303 user_switch, user, handle);
7305 return WERR_UNKNOWN_LEVEL;
7309 /****************************************************************************
7310 ****************************************************************************/
7312 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7314 uint32 level = q_u->level;
7315 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7316 WERROR err = WERR_OK;
7317 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7318 struct current_user user;
7319 fstring driver_name;
7322 ZERO_STRUCT(driver);
7324 get_current_user(&user, p);
7326 if (!convert_printer_driver_info(info, &driver, level)) {
7331 DEBUG(5,("Cleaning driver's information\n"));
7332 err = clean_up_driver_struct(driver, level, &user);
7333 if (!W_ERROR_IS_OK(err))
7336 DEBUG(5,("Moving driver to final destination\n"));
7337 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7338 if (W_ERROR_IS_OK(err))
7339 err = WERR_ACCESS_DENIED;
7343 if (add_a_printer_driver(driver, level)!=0) {
7344 err = WERR_ACCESS_DENIED;
7348 /* BEGIN_ADMIN_LOG */
7351 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7352 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7353 fstrcpy(driver_name, driver.info_3->name);
7356 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7357 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7358 fstrcpy(driver_name, driver.info_6->name);
7364 * I think this is where he DrvUpgradePrinter() hook would be
7365 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7366 * server. Right now, we just need to send ourselves a message
7367 * to update each printer bound to this driver. --jerry
7370 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7371 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7376 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7377 * decide if the driver init data should be deleted. The rules are:
7378 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7379 * 2) delete init data only if there is no 2k/Xp driver
7380 * 3) always delete init data
7381 * The generalized rule is always use init data from the highest order driver.
7382 * It is necessary to follow the driver install by an initialization step to
7383 * finish off this process.
7386 version = driver.info_3->cversion;
7387 else if (level == 6)
7388 version = driver.info_6->version;
7393 * 9x printer driver - never delete init data
7396 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7401 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7402 * there is no 2k/Xp driver init data for this driver name.
7406 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7408 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7410 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7412 if (!del_driver_init(driver_name))
7413 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7416 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7418 free_a_printer_driver(driver1,3);
7419 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7426 * 2k or Xp printer driver - always delete init data
7429 if (!del_driver_init(driver_name))
7430 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7434 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7440 free_a_printer_driver(driver, level);
7444 /********************************************************************
7445 * spoolss_addprinterdriverex
7446 ********************************************************************/
7448 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7450 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7451 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7454 * we only support the semantics of AddPrinterDriver()
7455 * i.e. only copy files that are newer than existing ones
7458 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7459 return WERR_ACCESS_DENIED;
7461 ZERO_STRUCT(q_u_local);
7462 ZERO_STRUCT(r_u_local);
7464 /* just pass the information off to _spoolss_addprinterdriver() */
7465 q_u_local.server_name_ptr = q_u->server_name_ptr;
7466 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7467 q_u_local.level = q_u->level;
7468 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7470 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7473 /****************************************************************************
7474 ****************************************************************************/
7476 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7478 init_unistr(&info->name, name);
7481 /****************************************************************************
7482 ****************************************************************************/
7484 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7488 pstring short_archi;
7489 DRIVER_DIRECTORY_1 *info=NULL;
7491 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7493 if (get_short_archi(short_archi, long_archi)==False)
7494 return WERR_INVALID_ENVIRONMENT;
7496 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7499 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7501 DEBUG(4,("printer driver directory: [%s]\n", path));
7503 fill_driverdir_1(info, path);
7505 *needed += spoolss_size_driverdir_info_1(info);
7507 if (!alloc_buffer_size(buffer, *needed)) {
7509 return WERR_INSUFFICIENT_BUFFER;
7512 smb_io_driverdir_1("", buffer, info, 0);
7516 if (*needed > offered)
7517 return WERR_INSUFFICIENT_BUFFER;
7522 /****************************************************************************
7523 ****************************************************************************/
7525 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7527 UNISTR2 *name = &q_u->name;
7528 UNISTR2 *uni_environment = &q_u->environment;
7529 uint32 level = q_u->level;
7530 NEW_BUFFER *buffer = NULL;
7531 uint32 offered = q_u->offered;
7532 uint32 *needed = &r_u->needed;
7534 /* that's an [in out] buffer */
7535 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7536 buffer = r_u->buffer;
7538 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7544 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7546 return WERR_UNKNOWN_LEVEL;
7550 /****************************************************************************
7551 ****************************************************************************/
7553 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7555 POLICY_HND *handle = &q_u->handle;
7556 uint32 idx = q_u->index;
7557 uint32 in_value_len = q_u->valuesize;
7558 uint32 in_data_len = q_u->datasize;
7559 uint32 *out_max_value_len = &r_u->valuesize;
7560 uint16 **out_value = &r_u->value;
7561 uint32 *out_value_len = &r_u->realvaluesize;
7562 uint32 *out_type = &r_u->type;
7563 uint32 *out_max_data_len = &r_u->datasize;
7564 uint8 **data_out = &r_u->data;
7565 uint32 *out_data_len = &r_u->realdatasize;
7567 NT_PRINTER_INFO_LEVEL *printer = NULL;
7570 uint32 biggest_valuesize;
7571 uint32 biggest_datasize;
7573 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7576 REGISTRY_VALUE *val = NULL;
7577 NT_PRINTER_DATA *p_data;
7578 int i, key_index, num_values;
7581 ZERO_STRUCT( printer );
7585 *out_max_data_len = 0;
7589 DEBUG(5,("spoolss_enumprinterdata\n"));
7592 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7596 if (!get_printer_snum(p,handle, &snum))
7599 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7600 if (!W_ERROR_IS_OK(result))
7603 p_data = &printer->info_2->data;
7604 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7609 * The NT machine wants to know the biggest size of value and data
7611 * cf: MSDN EnumPrinterData remark section
7614 if ( !in_value_len && !in_data_len && (key_index != -1) )
7616 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7619 biggest_valuesize = 0;
7620 biggest_datasize = 0;
7622 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7624 for ( i=0; i<num_values; i++ )
7626 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7628 name_length = strlen(val->valuename);
7629 if ( strlen(val->valuename) > biggest_valuesize )
7630 biggest_valuesize = name_length;
7632 if ( val->size > biggest_datasize )
7633 biggest_datasize = val->size;
7635 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7639 /* the value is an UNICODE string but real_value_size is the length
7640 in bytes including the trailing 0 */
7642 *out_value_len = 2 * (1+biggest_valuesize);
7643 *out_data_len = biggest_datasize;
7645 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7651 * the value len is wrong in NT sp3
7652 * that's the number of bytes not the number of unicode chars
7655 if ( key_index != -1 )
7656 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7661 /* out_value should default to "" or else NT4 has
7662 problems unmarshalling the response */
7664 *out_max_value_len=(in_value_len/sizeof(uint16));
7666 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7668 result = WERR_NOMEM;
7672 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7674 /* the data is counted in bytes */
7676 *out_max_data_len = in_data_len;
7677 *out_data_len = in_data_len;
7679 /* only allocate when given a non-zero data_len */
7681 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7683 result = WERR_NOMEM;
7687 result = WERR_NO_MORE_ITEMS;
7693 * - counted in bytes in the request
7694 * - counted in UNICODE chars in the max reply
7695 * - counted in bytes in the real size
7697 * take a pause *before* coding not *during* coding
7701 *out_max_value_len=(in_value_len/sizeof(uint16));
7702 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7704 result = WERR_NOMEM;
7708 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7712 *out_type = regval_type( val );
7714 /* data - counted in bytes */
7716 *out_max_data_len = in_data_len;
7717 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7719 result = WERR_NOMEM;
7722 data_len = (size_t)regval_size(val);
7723 memcpy( *data_out, regval_data_p(val), data_len );
7724 *out_data_len = data_len;
7728 free_a_printer(&printer, 2);
7732 /****************************************************************************
7733 ****************************************************************************/
7735 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7737 POLICY_HND *handle = &q_u->handle;
7738 UNISTR2 *value = &q_u->value;
7739 uint32 type = q_u->type;
7740 uint8 *data = q_u->data;
7741 uint32 real_len = q_u->real_len;
7743 NT_PRINTER_INFO_LEVEL *printer = NULL;
7745 WERROR status = WERR_OK;
7746 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7749 DEBUG(5,("spoolss_setprinterdata\n"));
7752 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7756 if (!get_printer_snum(p,handle, &snum))
7760 * Access check : NT returns "access denied" if you make a
7761 * SetPrinterData call without the necessary privildge.
7762 * we were originally returning OK if nothing changed
7763 * which made Win2k issue **a lot** of SetPrinterData
7764 * when connecting to a printer --jerry
7767 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7769 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7770 status = WERR_ACCESS_DENIED;
7774 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7775 if (!W_ERROR_IS_OK(status))
7778 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7781 * When client side code sets a magic printer data key, detect it and save
7782 * the current printer data and the magic key's data (its the DEVMODE) for
7783 * future printer/driver initializations.
7785 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7787 /* Set devmode and printer initialization info */
7788 status = save_driver_init( printer, 2, data, real_len );
7790 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7794 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7795 type, data, real_len );
7796 if ( W_ERROR_IS_OK(status) )
7797 status = mod_a_printer(*printer, 2);
7801 free_a_printer(&printer, 2);
7806 /****************************************************************************
7807 ****************************************************************************/
7809 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7811 POLICY_HND *handle = &q_u->handle;
7812 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7815 DEBUG(5,("_spoolss_resetprinter\n"));
7818 * All we do is to check to see if the handle and queue is valid.
7819 * This call really doesn't mean anything to us because we only
7820 * support RAW printing. --jerry
7824 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7828 if (!get_printer_snum(p,handle, &snum))
7832 /* blindly return success */
7837 /****************************************************************************
7838 ****************************************************************************/
7840 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7842 POLICY_HND *handle = &q_u->handle;
7843 UNISTR2 *value = &q_u->valuename;
7845 NT_PRINTER_INFO_LEVEL *printer = NULL;
7847 WERROR status = WERR_OK;
7848 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7851 DEBUG(5,("spoolss_deleteprinterdata\n"));
7854 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7858 if (!get_printer_snum(p, handle, &snum))
7861 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7862 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7863 return 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 );
7872 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7874 free_a_printer(&printer, 2);
7879 /****************************************************************************
7880 ****************************************************************************/
7882 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7884 POLICY_HND *handle = &q_u->handle;
7885 FORM *form = &q_u->form;
7886 nt_forms_struct tmpForm;
7888 WERROR status = WERR_OK;
7889 NT_PRINTER_INFO_LEVEL *printer = NULL;
7892 nt_forms_struct *list=NULL;
7893 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7895 DEBUG(5,("spoolss_addform\n"));
7898 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7903 /* forms can be added on printer of on the print server handle */
7905 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7907 if (!get_printer_snum(p,handle, &snum))
7910 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7911 if (!W_ERROR_IS_OK(status))
7915 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7916 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7917 status = WERR_ACCESS_DENIED;
7921 /* can't add if builtin */
7923 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7924 status = WERR_ALREADY_EXISTS;
7928 count = get_ntforms(&list);
7930 if(!add_a_form(&list, form, &count)) {
7931 status = WERR_NOMEM;
7935 write_ntforms(&list, count);
7938 * ChangeID must always be set if this is a printer
7941 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7942 status = mod_a_printer(*printer, 2);
7946 free_a_printer(&printer, 2);
7952 /****************************************************************************
7953 ****************************************************************************/
7955 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7957 POLICY_HND *handle = &q_u->handle;
7958 UNISTR2 *form_name = &q_u->name;
7959 nt_forms_struct tmpForm;
7961 nt_forms_struct *list=NULL;
7962 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7964 WERROR status = WERR_OK;
7965 NT_PRINTER_INFO_LEVEL *printer = NULL;
7967 DEBUG(5,("spoolss_deleteform\n"));
7970 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7974 /* forms can be deleted on printer of on the print server handle */
7976 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7978 if (!get_printer_snum(p,handle, &snum))
7981 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7982 if (!W_ERROR_IS_OK(status))
7986 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7987 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7988 status = WERR_ACCESS_DENIED;
7992 /* can't delete if builtin */
7994 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7995 status = WERR_INVALID_PARAM;
7999 count = get_ntforms(&list);
8001 if ( !delete_a_form(&list, form_name, &count, &status ))
8005 * ChangeID must always be set if this is a printer
8008 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8009 status = mod_a_printer(*printer, 2);
8013 free_a_printer(&printer, 2);
8019 /****************************************************************************
8020 ****************************************************************************/
8022 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8024 POLICY_HND *handle = &q_u->handle;
8025 FORM *form = &q_u->form;
8026 nt_forms_struct tmpForm;
8028 WERROR status = WERR_OK;
8029 NT_PRINTER_INFO_LEVEL *printer = NULL;
8032 nt_forms_struct *list=NULL;
8033 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8035 DEBUG(5,("spoolss_setform\n"));
8038 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8042 /* forms can be modified on printer of on the print server handle */
8044 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8046 if (!get_printer_snum(p,handle, &snum))
8049 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8050 if (!W_ERROR_IS_OK(status))
8054 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8055 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8056 status = WERR_ACCESS_DENIED;
8060 /* can't set if builtin */
8061 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8062 status = WERR_INVALID_PARAM;
8066 count = get_ntforms(&list);
8067 update_a_form(&list, form, count);
8068 write_ntforms(&list, count);
8071 * ChangeID must always be set if this is a printer
8074 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8075 status = mod_a_printer(*printer, 2);
8080 free_a_printer(&printer, 2);
8086 /****************************************************************************
8087 enumprintprocessors level 1.
8088 ****************************************************************************/
8090 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8092 PRINTPROCESSOR_1 *info_1=NULL;
8094 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8099 init_unistr(&info_1->name, "winprint");
8101 *needed += spoolss_size_printprocessor_info_1(info_1);
8103 if (!alloc_buffer_size(buffer, *needed))
8104 return WERR_INSUFFICIENT_BUFFER;
8106 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8110 if (*needed > offered) {
8112 return WERR_INSUFFICIENT_BUFFER;
8118 /****************************************************************************
8119 ****************************************************************************/
8121 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8123 uint32 level = q_u->level;
8124 NEW_BUFFER *buffer = NULL;
8125 uint32 offered = q_u->offered;
8126 uint32 *needed = &r_u->needed;
8127 uint32 *returned = &r_u->returned;
8129 /* that's an [in out] buffer */
8130 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8131 buffer = r_u->buffer;
8133 DEBUG(5,("spoolss_enumprintprocessors\n"));
8136 * Enumerate the print processors ...
8138 * Just reply with "winprint", to keep NT happy
8139 * and I can use my nice printer checker.
8147 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8149 return WERR_UNKNOWN_LEVEL;
8153 /****************************************************************************
8154 enumprintprocdatatypes level 1.
8155 ****************************************************************************/
8157 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8159 PRINTPROCDATATYPE_1 *info_1=NULL;
8161 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8166 init_unistr(&info_1->name, "RAW");
8168 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8170 if (!alloc_buffer_size(buffer, *needed))
8171 return WERR_INSUFFICIENT_BUFFER;
8173 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8177 if (*needed > offered) {
8179 return WERR_INSUFFICIENT_BUFFER;
8185 /****************************************************************************
8186 ****************************************************************************/
8188 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8190 uint32 level = q_u->level;
8191 NEW_BUFFER *buffer = NULL;
8192 uint32 offered = q_u->offered;
8193 uint32 *needed = &r_u->needed;
8194 uint32 *returned = &r_u->returned;
8196 /* that's an [in out] buffer */
8197 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8198 buffer = r_u->buffer;
8200 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8207 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8209 return WERR_UNKNOWN_LEVEL;
8213 /****************************************************************************
8214 enumprintmonitors level 1.
8215 ****************************************************************************/
8217 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8219 PRINTMONITOR_1 *info_1=NULL;
8221 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8226 init_unistr(&info_1->name, "Local Port");
8228 *needed += spoolss_size_printmonitor_info_1(info_1);
8230 if (!alloc_buffer_size(buffer, *needed))
8231 return WERR_INSUFFICIENT_BUFFER;
8233 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8237 if (*needed > offered) {
8239 return WERR_INSUFFICIENT_BUFFER;
8245 /****************************************************************************
8246 enumprintmonitors level 2.
8247 ****************************************************************************/
8249 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8251 PRINTMONITOR_2 *info_2=NULL;
8253 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8258 init_unistr(&info_2->name, "Local Port");
8259 init_unistr(&info_2->environment, "Windows NT X86");
8260 init_unistr(&info_2->dll_name, "localmon.dll");
8262 *needed += spoolss_size_printmonitor_info_2(info_2);
8264 if (!alloc_buffer_size(buffer, *needed))
8265 return WERR_INSUFFICIENT_BUFFER;
8267 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8271 if (*needed > offered) {
8273 return WERR_INSUFFICIENT_BUFFER;
8279 /****************************************************************************
8280 ****************************************************************************/
8282 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8284 uint32 level = q_u->level;
8285 NEW_BUFFER *buffer = NULL;
8286 uint32 offered = q_u->offered;
8287 uint32 *needed = &r_u->needed;
8288 uint32 *returned = &r_u->returned;
8290 /* that's an [in out] buffer */
8291 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8292 buffer = r_u->buffer;
8294 DEBUG(5,("spoolss_enumprintmonitors\n"));
8297 * Enumerate the print monitors ...
8299 * Just reply with "Local Port", to keep NT happy
8300 * and I can use my nice printer checker.
8308 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8310 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8312 return WERR_UNKNOWN_LEVEL;
8316 /****************************************************************************
8317 ****************************************************************************/
8319 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8323 JOB_INFO_1 *info_1=NULL;
8325 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8327 if (info_1 == NULL) {
8332 for (i=0; i<count && found==False; i++) {
8333 if (queue[i].job==(int)jobid)
8340 /* NT treats not found as bad param... yet another bad choice */
8341 return WERR_INVALID_PARAM;
8344 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8346 *needed += spoolss_size_job_info_1(info_1);
8348 if (!alloc_buffer_size(buffer, *needed)) {
8350 return WERR_INSUFFICIENT_BUFFER;
8353 smb_io_job_info_1("", buffer, info_1, 0);
8357 if (*needed > offered)
8358 return WERR_INSUFFICIENT_BUFFER;
8363 /****************************************************************************
8364 ****************************************************************************/
8366 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8371 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8373 DEVICEMODE *devmode = NULL;
8374 NT_DEVICEMODE *nt_devmode = NULL;
8376 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8378 ZERO_STRUCTP(info_2);
8380 if (info_2 == NULL) {
8385 for ( i=0; i<count && found==False; i++ )
8387 if (queue[i].job == (int)jobid)
8393 /* NT treats not found as bad param... yet another bad
8395 ret = WERR_INVALID_PARAM;
8399 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8400 if (!W_ERROR_IS_OK(ret))
8404 * if the print job does not have a DEVMODE associated with it,
8405 * just use the one for the printer. A NULL devicemode is not
8406 * a failure condition
8409 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8410 devmode = construct_dev_mode(snum);
8412 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8413 ZERO_STRUCTP( devmode );
8414 convert_nt_devicemode( devmode, nt_devmode );
8418 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8420 *needed += spoolss_size_job_info_2(info_2);
8422 if (!alloc_buffer_size(buffer, *needed)) {
8423 ret = WERR_INSUFFICIENT_BUFFER;
8427 smb_io_job_info_2("", buffer, info_2, 0);
8429 if (*needed > offered) {
8430 ret = WERR_INSUFFICIENT_BUFFER;
8437 /* Cleanup allocated memory */
8439 free_job_info_2(info_2); /* Also frees devmode */
8441 free_a_printer(&ntprinter, 2);
8446 /****************************************************************************
8447 ****************************************************************************/
8449 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8451 POLICY_HND *handle = &q_u->handle;
8452 uint32 jobid = q_u->jobid;
8453 uint32 level = q_u->level;
8454 NEW_BUFFER *buffer = NULL;
8455 uint32 offered = q_u->offered;
8456 uint32 *needed = &r_u->needed;
8457 WERROR wstatus = WERR_OK;
8461 print_queue_struct *queue = NULL;
8462 print_status_struct prt_status;
8464 /* that's an [in out] buffer */
8465 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8466 buffer = r_u->buffer;
8468 DEBUG(5,("spoolss_getjob\n"));
8472 if (!get_printer_snum(p, handle, &snum))
8475 count = print_queue_status(snum, &queue, &prt_status);
8477 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8478 count, prt_status.status, prt_status.message));
8482 wstatus = getjob_level_1(queue, count, snum, jobid,
8483 buffer, offered, needed);
8486 wstatus = getjob_level_2(queue, count, snum, jobid,
8487 buffer, offered, needed);
8490 wstatus = WERR_UNKNOWN_LEVEL;
8498 /********************************************************************
8499 spoolss_getprinterdataex
8501 From MSDN documentation of GetPrinterDataEx: pass request
8502 to GetPrinterData if key is "PrinterDriverData".
8503 ********************************************************************/
8505 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8507 POLICY_HND *handle = &q_u->handle;
8508 uint32 in_size = q_u->size;
8509 uint32 *type = &r_u->type;
8510 uint32 *out_size = &r_u->size;
8511 uint8 **data = &r_u->data;
8512 uint32 *needed = &r_u->needed;
8513 fstring keyname, valuename;
8515 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8517 NT_PRINTER_INFO_LEVEL *printer = NULL;
8519 WERROR status = WERR_OK;
8521 DEBUG(4,("_spoolss_getprinterdataex\n"));
8523 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8524 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8526 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8527 keyname, valuename));
8529 /* in case of problem, return some default values */
8533 *out_size = in_size;
8536 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8537 status = WERR_BADFID;
8541 /* Is the handle to a printer or to the server? */
8543 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8544 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8545 status = WERR_INVALID_PARAM;
8549 if ( !get_printer_snum(p,handle, &snum) )
8552 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8553 if ( !W_ERROR_IS_OK(status) )
8556 /* check to see if the keyname is valid */
8557 if ( !strlen(keyname) ) {
8558 status = WERR_INVALID_PARAM;
8562 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8563 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8564 free_a_printer( &printer, 2 );
8565 status = WERR_BADFILE;
8569 /* When given a new keyname, we should just create it */
8571 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8573 if (*needed > *out_size)
8574 status = WERR_MORE_DATA;
8577 if ( !W_ERROR_IS_OK(status) )
8579 DEBUG(5, ("error: allocating %d\n", *out_size));
8581 /* reply this param doesn't exist */
8585 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8586 status = WERR_NOMEM;
8596 free_a_printer( &printer, 2 );
8601 /********************************************************************
8602 * spoolss_setprinterdataex
8603 ********************************************************************/
8605 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8607 POLICY_HND *handle = &q_u->handle;
8608 uint32 type = q_u->type;
8609 uint8 *data = q_u->data;
8610 uint32 real_len = q_u->real_len;
8612 NT_PRINTER_INFO_LEVEL *printer = NULL;
8614 WERROR status = WERR_OK;
8615 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8620 DEBUG(4,("_spoolss_setprinterdataex\n"));
8622 /* From MSDN documentation of SetPrinterDataEx: pass request to
8623 SetPrinterData if key is "PrinterDriverData" */
8626 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8630 if ( !get_printer_snum(p,handle, &snum) )
8634 * Access check : NT returns "access denied" if you make a
8635 * SetPrinterData call without the necessary privildge.
8636 * we were originally returning OK if nothing changed
8637 * which made Win2k issue **a lot** of SetPrinterData
8638 * when connecting to a printer --jerry
8641 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8643 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8644 return WERR_ACCESS_DENIED;
8647 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8648 if (!W_ERROR_IS_OK(status))
8651 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8652 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8654 /* check for OID in valuename */
8656 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8662 /* save the registry data */
8664 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8666 if ( W_ERROR_IS_OK(status) )
8668 /* save the OID if one was specified */
8670 fstrcat( keyname, "\\" );
8671 fstrcat( keyname, SPOOL_OID_KEY );
8674 * I'm not checking the status here on purpose. Don't know
8675 * if this is right, but I'm returning the status from the
8676 * previous set_printer_dataex() call. I have no idea if
8677 * this is right. --jerry
8680 set_printer_dataex( printer, keyname, valuename,
8681 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8684 status = mod_a_printer(*printer, 2);
8687 free_a_printer(&printer, 2);
8693 /********************************************************************
8694 * spoolss_deleteprinterdataex
8695 ********************************************************************/
8697 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8699 POLICY_HND *handle = &q_u->handle;
8700 UNISTR2 *value = &q_u->valuename;
8701 UNISTR2 *key = &q_u->keyname;
8703 NT_PRINTER_INFO_LEVEL *printer = NULL;
8705 WERROR status = WERR_OK;
8706 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8707 pstring valuename, keyname;
8709 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8712 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8716 if (!get_printer_snum(p, handle, &snum))
8719 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8720 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8721 return WERR_ACCESS_DENIED;
8724 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8725 if (!W_ERROR_IS_OK(status))
8728 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8729 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8731 status = delete_printer_dataex( printer, keyname, valuename );
8733 free_a_printer(&printer, 2);
8738 /********************************************************************
8739 * spoolss_enumprinterkey
8740 ********************************************************************/
8743 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8746 fstring *keynames = NULL;
8747 uint16 *enumkeys = NULL;
8750 POLICY_HND *handle = &q_u->handle;
8751 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8752 NT_PRINTER_DATA *data;
8753 NT_PRINTER_INFO_LEVEL *printer = NULL;
8755 WERROR status = WERR_BADFILE;
8758 DEBUG(4,("_spoolss_enumprinterkey\n"));
8761 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8765 if ( !get_printer_snum(p,handle, &snum) )
8768 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8769 if (!W_ERROR_IS_OK(status))
8772 /* get the list of subkey names */
8774 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8775 data = &printer->info_2->data;
8777 num_keys = get_printer_subkeys( data, key, &keynames );
8779 if ( num_keys == -1 ) {
8780 status = WERR_BADFILE;
8784 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8786 r_u->needed = printerkey_len*2;
8788 if ( q_u->size < r_u->needed ) {
8789 status = WERR_MORE_DATA;
8793 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8794 status = WERR_NOMEM;
8800 if ( q_u->size < r_u->needed )
8801 status = WERR_MORE_DATA;
8804 free_a_printer( &printer, 2 );
8805 SAFE_FREE( keynames );
8810 /********************************************************************
8811 * spoolss_deleteprinterkey
8812 ********************************************************************/
8814 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8816 POLICY_HND *handle = &q_u->handle;
8817 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8819 NT_PRINTER_INFO_LEVEL *printer = NULL;
8823 DEBUG(5,("spoolss_deleteprinterkey\n"));
8826 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8830 /* if keyname == NULL, return error */
8832 if ( !q_u->keyname.buffer )
8833 return WERR_INVALID_PARAM;
8835 if (!get_printer_snum(p, handle, &snum))
8838 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8839 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8840 return WERR_ACCESS_DENIED;
8843 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8844 if (!W_ERROR_IS_OK(status))
8847 /* delete the key and all subneys */
8849 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8851 status = delete_all_printer_data( printer->info_2, key );
8853 if ( W_ERROR_IS_OK(status) )
8854 status = mod_a_printer(*printer, 2);
8856 free_a_printer( &printer, 2 );
8862 /********************************************************************
8863 * spoolss_enumprinterdataex
8864 ********************************************************************/
8866 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8868 POLICY_HND *handle = &q_u->handle;
8869 uint32 in_size = q_u->size;
8872 NT_PRINTER_INFO_LEVEL *printer = NULL;
8873 PRINTER_ENUM_VALUES *enum_values = NULL;
8874 NT_PRINTER_DATA *p_data;
8876 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8881 REGISTRY_VALUE *val;
8886 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8889 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8894 * first check for a keyname of NULL or "". Win2k seems to send
8895 * this a lot and we should send back WERR_INVALID_PARAM
8896 * no need to spend time looking up the printer in this case.
8900 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8901 if ( !strlen(key) ) {
8902 result = WERR_INVALID_PARAM;
8906 /* get the printer off of disk */
8908 if (!get_printer_snum(p,handle, &snum))
8911 ZERO_STRUCT(printer);
8912 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8913 if (!W_ERROR_IS_OK(result))
8916 /* now look for a match on the key name */
8918 p_data = &printer->info_2->data;
8920 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8921 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8923 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8924 result = WERR_INVALID_PARAM;
8931 /* allocate the memory for the array of pointers -- if necessary */
8933 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8936 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8938 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8939 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8940 result = WERR_NOMEM;
8944 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8948 * loop through all params and build the array to pass
8949 * back to the client
8952 for ( i=0; i<num_entries; i++ )
8954 /* lookup the registry value */
8956 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8957 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8961 value_name = regval_name( val );
8962 init_unistr( &enum_values[i].valuename, value_name );
8963 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8964 enum_values[i].type = regval_type( val );
8966 data_len = regval_size( val );
8968 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8970 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8972 result = WERR_NOMEM;
8976 enum_values[i].data_len = data_len;
8978 /* keep track of the size of the array in bytes */
8980 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8983 /* housekeeping information in the reply */
8985 r_u->needed = needed;
8986 r_u->returned = num_entries;
8988 if (needed > in_size) {
8989 result = WERR_MORE_DATA;
8993 /* copy data into the reply */
8995 r_u->ctr.size = r_u->needed;
8996 r_u->ctr.size_of_array = r_u->returned;
8997 r_u->ctr.values = enum_values;
9003 free_a_printer(&printer, 2);
9008 /****************************************************************************
9009 ****************************************************************************/
9011 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9013 init_unistr(&info->name, name);
9016 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9017 UNISTR2 *environment,
9024 pstring short_archi;
9025 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9027 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9029 if (get_short_archi(short_archi, long_archi)==False)
9030 return WERR_INVALID_ENVIRONMENT;
9032 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9035 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9037 fill_printprocessordirectory_1(info, path);
9039 *needed += spoolss_size_printprocessordirectory_info_1(info);
9041 if (!alloc_buffer_size(buffer, *needed)) {
9043 return WERR_INSUFFICIENT_BUFFER;
9046 smb_io_printprocessordirectory_1("", buffer, info, 0);
9050 if (*needed > offered)
9051 return WERR_INSUFFICIENT_BUFFER;
9056 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9058 uint32 level = q_u->level;
9059 NEW_BUFFER *buffer = NULL;
9060 uint32 offered = q_u->offered;
9061 uint32 *needed = &r_u->needed;
9064 /* that's an [in out] buffer */
9065 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9066 buffer = r_u->buffer;
9068 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9074 result = getprintprocessordirectory_level_1
9075 (&q_u->name, &q_u->environment, buffer, offered, needed);
9078 result = WERR_UNKNOWN_LEVEL;
9086 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9087 SPOOL_R_REPLYOPENPRINTER *r_u)
9089 DEBUG(5,("_spoolss_replyopenprinter\n"));
9091 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9096 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9097 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9099 DEBUG(5,("_spoolss_replycloseprinter\n"));