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 */
51 static const char *get_drv_ver_to_os(int ver)
53 if (ver < 0 || ver > 3)
55 return drv_ver_to_os[ver];
59 const char *long_archi;
60 const char *short_archi;
64 static Printer_entry *printers_list;
66 typedef struct _counter_printer_0 {
74 static ubi_dlList counter_list;
76 static struct cli_state notify_cli; /* print notify back-channel */
77 static uint32 smb_connections=0;
80 /* in printing/nt_printing.c */
82 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
84 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
85 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
87 /* translate between internal status numbers and NT status numbers */
88 static int nt_printj_status(int v)
94 return JOB_STATUS_PAUSED;
96 return JOB_STATUS_SPOOLING;
98 return JOB_STATUS_PRINTING;
100 return JOB_STATUS_ERROR;
102 return JOB_STATUS_DELETING;
104 return JOB_STATUS_OFFLINE;
106 return JOB_STATUS_PAPEROUT;
108 return JOB_STATUS_PRINTED;
110 return JOB_STATUS_DELETED;
112 return JOB_STATUS_BLOCKED;
113 case LPQ_USER_INTERVENTION:
114 return JOB_STATUS_USER_INTERVENTION;
119 static int nt_printq_status(int v)
123 return PRINTER_STATUS_PAUSED;
132 /****************************************************************************
133 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
134 ****************************************************************************/
136 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
141 SAFE_FREE((*pp)->ctr.type);
145 /***************************************************************************
146 Disconnect from the client
147 ****************************************************************************/
149 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
154 * Tell the specific printing tdb we no longer want messages for this printer
155 * by deregistering our PID.
158 if (!print_notify_deregister_pid(snum))
159 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
161 /* weird if the test succeds !!! */
162 if (smb_connections==0) {
163 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
167 result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle);
169 if (!W_ERROR_IS_OK(result))
170 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171 dos_errstr(result)));
173 /* if it's the last connection, deconnect the IPC$ share */
174 if (smb_connections==1) {
175 cli_nt_session_close(¬ify_cli);
176 cli_ulogoff(¬ify_cli);
177 cli_shutdown(¬ify_cli);
178 message_deregister(MSG_PRINTER_NOTIFY2);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags( False, FLAG_MSG_PRINTING );
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static void free_printer_entry(void *ptr)
195 Printer_entry *Printer = (Printer_entry *)ptr;
197 if (Printer->notify.client_connected==True) {
200 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
202 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
204 snum = print_queue_snum(Printer->dev.handlename);
206 srv_spoolss_replycloseprinter(snum,
207 &Printer->notify.client_hnd);
211 Printer->notify.flags=0;
212 Printer->notify.options=0;
213 Printer->notify.localmachine[0]='\0';
214 Printer->notify.printerlocal=0;
215 free_spool_notify_option(&Printer->notify.option);
216 Printer->notify.option=NULL;
217 Printer->notify.client_connected=False;
219 free_nt_devicemode( &Printer->nt_devmode );
220 free_a_printer( &Printer->printer_info, 2 );
222 talloc_destroy( Printer->ctx );
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list, Printer);
230 /****************************************************************************
231 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
234 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
236 SPOOL_NOTIFY_OPTION *new_sp = NULL;
241 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
248 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
250 if (!new_sp->ctr.type) {
259 /****************************************************************************
260 find printer index by handle
261 ****************************************************************************/
263 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
265 Printer_entry *find_printer = NULL;
267 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
268 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
275 /****************************************************************************
276 find printer index by handle
277 ****************************************************************************/
279 void invalidate_printer_hnd_cache( char *printername )
283 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
285 for ( p=printers_list; p; p=p->next )
287 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
288 && StrCaseCmp(p->dev.handlename, printername)==0)
290 DEBUG(10,("invalidating printer_info cache for handl:\n"));
291 free_a_printer( &p->printer_info, 2 );
292 p->printer_info = NULL;
298 /****************************************************************************
299 Close printer index by handle.
300 ****************************************************************************/
302 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
304 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
307 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
311 close_policy_hnd(p, hnd);
316 /****************************************************************************
317 Delete a printer given a handle.
318 ****************************************************************************/
320 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
322 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
325 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
330 * It turns out that Windows allows delete printer on a handle
331 * opened by an admin user, then used on a pipe handle created
332 * by an anonymous user..... but they're working on security.... riiight !
336 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
337 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
338 return WERR_ACCESS_DENIED;
342 /* Check calling user has permission to delete printer. Note that
343 since we set the snum parameter to -1 only administrators can
344 delete the printer. This stops people with the Full Control
345 permission from deleting the printer. */
347 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
348 DEBUG(3, ("printer delete denied by security descriptor\n"));
349 return WERR_ACCESS_DENIED;
353 if (del_a_printer(Printer->dev.handlename) != 0) {
354 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
358 if (*lp_deleteprinter_cmd()) {
360 char *cmd = lp_deleteprinter_cmd();
365 /* Printer->dev.handlename equals portname equals sharename */
366 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
367 Printer->dev.handlename);
369 DEBUG(10,("Running [%s]\n", command));
370 ret = smbrun(command, NULL);
372 return WERR_BADFID; /* What to return here? */
374 DEBUGADD(10,("returned [%d]\n", ret));
376 /* Send SIGHUP to process group... is there a better way? */
379 /* go ahead and re-read the services immediately */
380 reload_services( False );
382 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
383 return WERR_ACCESS_DENIED;
389 /****************************************************************************
390 Return the snum of a printer corresponding to an handle.
391 ****************************************************************************/
393 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
395 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
398 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
402 switch (Printer->printer_type) {
403 case PRINTER_HANDLE_IS_PRINTER:
404 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
405 *number = print_queue_snum(Printer->dev.handlename);
406 return (*number != -1);
407 case PRINTER_HANDLE_IS_PRINTSERVER:
414 /****************************************************************************
415 Set printer handle type.
416 Check if it's \\server or \\server\printer
417 ****************************************************************************/
419 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
421 DEBUG(3,("Setting printer type=%s\n", handlename));
423 if ( strlen(handlename) < 3 ) {
424 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
428 /* it's a print server */
429 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
430 DEBUGADD(4,("Printer is a print server\n"));
431 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
435 DEBUGADD(4,("Printer is a printer\n"));
436 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
442 /****************************************************************************
443 Set printer handle name.
444 ****************************************************************************/
446 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
449 int n_services=lp_numservices();
454 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
456 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
457 ZERO_STRUCT(Printer->dev.printerservername);
458 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
462 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
465 if (*handlename=='\\') {
466 aprinter=strchr_m(handlename+2, '\\');
473 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
476 * The original code allowed smbd to store a printer name that
477 * was different from the share name. This is not possible
478 * anymore, so I've simplified this loop greatly. Here
479 * we are just verifying that the printer name is a valid
480 * printer service defined in smb.conf
481 * --jerry [Fri Feb 15 11:17:46 CST 2002]
484 for (snum=0; snum<n_services; snum++) {
486 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
489 fstrcpy(sname, lp_servicename(snum));
491 DEBUGADD(5,("share:%s\n",sname));
493 if (! StrCaseCmp(sname, aprinter)) {
502 DEBUGADD(4,("Printer not found\n"));
506 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
508 ZERO_STRUCT(Printer->dev.handlename);
509 fstrcpy(Printer->dev.handlename, sname);
514 /****************************************************************************
515 Find first available printer slot. creates a printer handle for you.
516 ****************************************************************************/
518 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
520 Printer_entry *new_printer;
522 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
524 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
527 ZERO_STRUCTP(new_printer);
529 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
530 SAFE_FREE(new_printer);
534 /* Add to the internal list. */
535 DLIST_ADD(printers_list, new_printer);
537 new_printer->notify.option=NULL;
539 if ( !(new_printer->ctx = talloc_init("Printer Entry [0x%x]", (uint32)hnd)) ) {
540 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
541 close_printer_handle(p, hnd);
545 if (!set_printer_hnd_printertype(new_printer, name)) {
546 close_printer_handle(p, hnd);
550 if (!set_printer_hnd_name(new_printer, name)) {
551 close_printer_handle(p, hnd);
555 new_printer->access_granted = access_granted;
557 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
562 /****************************************************************************
563 Allocate more memory for a BUFFER.
564 ****************************************************************************/
566 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
574 /* damn, I'm doing the reverse operation of prs_grow() :) */
575 if (buffer_size < prs_data_size(ps))
578 extra_space = buffer_size - prs_data_size(ps);
581 * save the offset and move to the end of the buffer
582 * prs_grow() checks the extra_space against the offset
584 old_offset=prs_offset(ps);
585 prs_set_offset(ps, prs_data_size(ps));
587 if (!prs_grow(ps, extra_space))
590 prs_set_offset(ps, old_offset);
592 buffer->string_at_end=prs_data_size(ps);
597 /***************************************************************************
598 check to see if the client motify handle is monitoring the notification
599 given by (notify_type, notify_field).
600 **************************************************************************/
602 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
608 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
611 SPOOL_NOTIFY_OPTION *option = p->notify.option;
615 * Flags should always be zero when the change notify
616 * is registered by the client's spooler. A user Win32 app
617 * might use the flags though instead of the NOTIFY_OPTION_INFO
622 return is_monitoring_event_flags(
623 p->notify.flags, notify_type, notify_field);
625 for (i = 0; i < option->count; i++) {
627 /* Check match for notify_type */
629 if (option->ctr.type[i].type != notify_type)
632 /* Check match for field */
634 for (j = 0; j < option->ctr.type[i].count; j++) {
635 if (option->ctr.type[i].fields[j] == notify_field) {
641 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
642 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
643 p->dev.handlename : p->dev.printerservername,
644 notify_type, notify_field));
649 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
651 static void notify_one_value(struct spoolss_notify_msg *msg,
652 SPOOL_NOTIFY_INFO_DATA *data,
655 data->notify_data.value[0] = msg->notify.value[0];
656 data->notify_data.value[1] = 0;
659 static void notify_string(struct spoolss_notify_msg *msg,
660 SPOOL_NOTIFY_INFO_DATA *data,
665 /* The length of the message includes the trailing \0 */
667 init_unistr2(&unistr, msg->notify.data, msg->len);
669 data->notify_data.data.length = msg->len * 2;
670 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
672 if (!data->notify_data.data.string) {
673 data->notify_data.data.length = 0;
677 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
680 static void notify_system_time(struct spoolss_notify_msg *msg,
681 SPOOL_NOTIFY_INFO_DATA *data,
687 if (msg->len != sizeof(time_t)) {
688 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
693 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
694 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
698 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
699 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
703 if (!spoolss_io_system_time("", &ps, 0, &systime))
706 data->notify_data.data.length = prs_offset(&ps);
707 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
709 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
714 struct notify2_message_table {
716 void (*fn)(struct spoolss_notify_msg *msg,
717 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
720 static struct notify2_message_table printer_notify_table[] = {
721 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
722 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
723 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
724 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
725 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
726 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
727 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
728 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
729 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
730 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
731 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
732 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
733 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
734 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
735 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
736 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
737 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
738 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
739 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
742 static struct notify2_message_table job_notify_table[] = {
743 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
744 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
745 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
746 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
747 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
748 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
749 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
750 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
751 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
752 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
753 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
754 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
755 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
756 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
757 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
758 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
759 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
760 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
761 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
762 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
763 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
764 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
765 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
766 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
770 /***********************************************************************
771 Allocate talloc context for container object
772 **********************************************************************/
774 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
779 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
784 /***********************************************************************
785 release all allocated memory and zero out structure
786 **********************************************************************/
788 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
794 talloc_destroy(ctr->ctx);
801 /***********************************************************************
802 **********************************************************************/
804 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 /***********************************************************************
813 **********************************************************************/
815 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
817 if ( !ctr || !ctr->msg_groups )
820 if ( idx >= ctr->num_groups )
823 return &ctr->msg_groups[idx];
827 /***********************************************************************
828 How many groups of change messages do we have ?
829 **********************************************************************/
831 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
836 return ctr->num_groups;
839 /***********************************************************************
840 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
841 **********************************************************************/
843 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
845 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
846 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
847 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
853 /* loop over all groups looking for a matching printer name */
855 for ( i=0; i<ctr->num_groups; i++ ) {
856 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
860 /* add a new group? */
862 if ( i == ctr->num_groups ) {
865 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
866 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
869 ctr->msg_groups = groups;
871 /* clear the new entry and set the printer name */
873 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
874 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
877 /* add the change messages; 'i' is the correct index now regardless */
879 msg_grp = &ctr->msg_groups[i];
883 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
884 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
887 msg_grp->msgs = msg_list;
889 new_slot = msg_grp->num_msgs-1;
890 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
892 /* need to allocate own copy of data */
895 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
897 return ctr->num_groups;
900 /***********************************************************************
901 Send a change notication message on all handles which have a call
903 **********************************************************************/
905 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
908 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
909 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
910 SPOOLSS_NOTIFY_MSG *messages;
911 int sending_msg_count;
914 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
918 messages = msg_group->msgs;
921 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
925 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
927 /* loop over all printers */
929 for (p = printers_list; p; p = p->next) {
930 SPOOL_NOTIFY_INFO_DATA *data;
935 /* Is there notification on this handle? */
937 if ( !p->notify.client_connected )
940 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
942 /* For this printer? Print servers always receive
945 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
946 ( !strequal(msg_group->printername, p->dev.handlename) ) )
949 DEBUG(10,("Our printer\n"));
951 /* allocate the max entries possible */
953 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
958 /* build the array of change notifications */
960 sending_msg_count = 0;
962 for ( i=0; i<msg_group->num_msgs; i++ ) {
963 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
965 /* Are we monitoring this event? */
967 if (!is_monitoring_event(p, msg->type, msg->field))
973 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
974 msg->type, msg->field, p->dev.handlename));
977 * if the is a printer notification handle and not a job notification
978 * type, then set the id to 0. Other wise just use what was specified
981 * When registering change notification on a print server handle
982 * we always need to send back the id (snum) matching the printer
983 * for which the change took place. For change notify registered
984 * on a printer handle, this does not matter and the id should be 0.
989 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
995 /* Convert unix jobid to smb jobid */
997 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
998 id = sysjob_to_jobid(msg->id);
1001 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1006 construct_info_data( &data[data_len], msg->type, msg->field, id );
1009 case PRINTER_NOTIFY_TYPE:
1010 if ( printer_notify_table[msg->field].fn )
1011 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1014 case JOB_NOTIFY_TYPE:
1015 if ( job_notify_table[msg->field].fn )
1016 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1020 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1027 if ( sending_msg_count ) {
1028 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1029 data_len, data, p->notify.change, 0 );
1034 DEBUG(8,("send_notify2_changes: Exit...\n"));
1038 /***********************************************************************
1039 **********************************************************************/
1041 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1044 uint32 tv_sec, tv_usec;
1047 /* Unpack message */
1049 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1052 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1054 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1057 tdb_unpack((char *)buf + offset, len - offset, "dd",
1058 &msg->notify.value[0], &msg->notify.value[1]);
1060 tdb_unpack((char *)buf + offset, len - offset, "B",
1061 &msg->len, &msg->notify.data);
1063 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1064 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1066 tv->tv_sec = tv_sec;
1067 tv->tv_usec = tv_usec;
1070 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1071 msg->notify.value[1]));
1073 dump_data(3, msg->notify.data, msg->len);
1078 /* ENUMJOB last timestamp list. */
1080 struct ejts_list *next, *prev;
1085 static struct ejts_list *ejts_head;
1087 static struct ejts_list *find_enumjobs_timestamp(const char *printer_name)
1089 struct ejts_list *ejtsl;
1091 for( ejtsl = ejts_head; ejtsl; ejtsl = ejtsl->next)
1092 if (strequal(ejtsl->printer_name, printer_name))
1097 static void set_enumjobs_timestamp(int snum)
1099 const char *printer_name = lp_const_servicename(snum);
1100 struct ejts_list *ejtsl = find_enumjobs_timestamp(printer_name);
1103 ejtsl = (struct ejts_list *)malloc(sizeof(struct ejts_list));
1106 ejtsl->printer_name = strdup(printer_name);
1107 if (!ejtsl->printer_name) {
1111 DLIST_ADD(ejts_head, ejtsl);
1114 gettimeofday(&ejtsl->tv, NULL);
1117 static int timeval_diff(struct timeval *tv1, struct timeval *tv2)
1119 if (tv1->tv_sec > tv2->tv_sec)
1121 if (tv1->tv_sec < tv2->tv_sec)
1123 if (tv1->tv_usec > tv2->tv_usec)
1125 if (tv1->tv_usec < tv2->tv_usec)
1130 /********************************************************************
1131 Receive a notify2 message list
1132 ********************************************************************/
1134 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1136 size_t msg_count, i;
1137 char *buf = (char *)msg;
1140 SPOOLSS_NOTIFY_MSG notify;
1141 SPOOLSS_NOTIFY_MSG_CTR messages;
1145 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1149 msg_count = IVAL(buf, 0);
1152 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1154 if (msg_count == 0) {
1155 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1159 /* initialize the container */
1161 ZERO_STRUCT( messages );
1162 notify_msg_ctr_init( &messages );
1165 * build message groups for each printer identified
1166 * in a change_notify msg. Remember that a PCN message
1167 * includes the handle returned for the srv_spoolss_replyopenprinter()
1168 * call. Therefore messages are grouped according to printer handle.
1171 for ( i=0; i<msg_count; i++ ) {
1172 struct timeval msg_tv;
1174 if (msg_ptr + 4 - buf > len) {
1175 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1179 msg_len = IVAL(msg_ptr,0);
1182 if (msg_ptr + msg_len - buf > len) {
1183 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1187 /* unpack messages */
1189 ZERO_STRUCT( notify );
1190 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1193 /* See if it is still relevent. */
1194 if (notify.type == JOB_NOTIFY_TYPE) {
1195 BOOL status_is_deleting = False;
1197 if (notify.field == JOB_NOTIFY_STATUS && (notify.notify.value[0] & (JOB_STATUS_DELETING|JOB_STATUS_DELETED)))
1198 status_is_deleting = True;
1200 if (!status_is_deleting) {
1201 struct ejts_list *ejtsl = find_enumjobs_timestamp(notify.printer);
1203 if (ejtsl && (timeval_diff(&ejtsl->tv, &msg_tv) > 0)) {
1205 DEBUG(10, ("receive_notify2_message_list: enumjobs ts = %u, %u, msg ts = %u, %u discarding\n",
1206 (unsigned int)ejtsl->tv.tv_sec, (unsigned int)ejtsl->tv.tv_usec,
1207 (unsigned int)msg_tv.tv_sec, (unsigned int)msg_tv.tv_usec ));
1209 /* Message no longer relevent. Ignore it. */
1210 if ( notify.len != 0 )
1211 SAFE_FREE( notify.notify.data );
1216 /* add to correct list in container */
1218 notify_msg_ctr_addmsg( &messages, ¬ify );
1220 /* free memory that might have been allocated by notify2_unpack_msg() */
1222 if ( notify.len != 0 )
1223 SAFE_FREE( notify.notify.data );
1226 /* process each group of messages */
1228 num_groups = notify_msg_ctr_numgroups( &messages );
1229 for ( i=0; i<num_groups; i++ )
1230 send_notify2_changes( &messages, i );
1235 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1237 notify_msg_ctr_destroy( &messages );
1242 /********************************************************************
1243 Send a message to ourself about new driver being installed
1244 so we can upgrade the information for each printer bound to this
1246 ********************************************************************/
1248 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1250 int len = strlen(drivername);
1255 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1258 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1263 /**********************************************************************
1264 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1265 over all printers, upgrading ones as necessary
1266 **********************************************************************/
1268 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1272 int n_services = lp_numservices();
1274 len = MIN(len,sizeof(drivername)-1);
1275 strncpy(drivername, buf, len);
1277 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1279 /* Iterate the printer list */
1281 for (snum=0; snum<n_services; snum++)
1283 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1286 NT_PRINTER_INFO_LEVEL *printer = NULL;
1288 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1289 if (!W_ERROR_IS_OK(result))
1292 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1294 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1296 /* all we care about currently is the change_id */
1298 result = mod_a_printer(*printer, 2);
1299 if (!W_ERROR_IS_OK(result)) {
1300 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1301 dos_errstr(result)));
1305 free_a_printer(&printer, 2);
1312 /********************************************************************
1313 Update the cache for all printq's with a registered client
1315 ********************************************************************/
1317 void update_monitored_printq_cache( void )
1319 Printer_entry *printer = printers_list;
1322 /* loop through all printers and update the cache where
1323 client_connected == True */
1326 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1327 && printer->notify.client_connected )
1329 snum = print_queue_snum(printer->dev.handlename);
1330 print_queue_status( snum, NULL, NULL );
1333 printer = printer->next;
1338 /********************************************************************
1339 Send a message to ourself about new driver being installed
1340 so we can upgrade the information for each printer bound to this
1342 ********************************************************************/
1344 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1346 int len = strlen(drivername);
1351 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1354 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1359 /**********************************************************************
1360 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1361 over all printers, resetting printer data as neessary
1362 **********************************************************************/
1364 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1368 int n_services = lp_numservices();
1370 len = MIN( len, sizeof(drivername)-1 );
1371 strncpy( drivername, buf, len );
1373 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1375 /* Iterate the printer list */
1377 for ( snum=0; snum<n_services; snum++ )
1379 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1382 NT_PRINTER_INFO_LEVEL *printer = NULL;
1384 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1385 if ( !W_ERROR_IS_OK(result) )
1389 * if the printer is bound to the driver,
1390 * then reset to the new driver initdata
1393 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1395 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1397 if ( !set_driver_init(printer, 2) ) {
1398 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1399 printer->info_2->printername, printer->info_2->drivername));
1402 result = mod_a_printer( *printer, 2 );
1403 if ( !W_ERROR_IS_OK(result) ) {
1404 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1405 get_dos_error_msg(result)));
1409 free_a_printer( &printer, 2 );
1418 /********************************************************************
1419 Copy routines used by convert_to_openprinterex()
1420 *******************************************************************/
1422 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1430 DEBUG (8,("dup_devmode\n"));
1432 /* bulk copy first */
1434 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1438 /* dup the pointer members separately */
1440 len = unistrlen(devmode->devicename.buffer);
1442 d->devicename.buffer = talloc(ctx, len*2);
1443 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1448 len = unistrlen(devmode->formname.buffer);
1450 d->devicename.buffer = talloc(ctx, len*2);
1451 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1455 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1460 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1462 if (!new_ctr || !ctr)
1465 DEBUG(8,("copy_devmode_ctr\n"));
1467 new_ctr->size = ctr->size;
1468 new_ctr->devmode_ptr = ctr->devmode_ptr;
1470 if(ctr->devmode_ptr)
1471 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1474 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1476 if (!new_def || !def)
1479 DEBUG(8,("copy_printer_defaults\n"));
1481 new_def->datatype_ptr = def->datatype_ptr;
1483 if (def->datatype_ptr)
1484 copy_unistr2(&new_def->datatype, &def->datatype);
1486 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1488 new_def->access_required = def->access_required;
1491 /********************************************************************
1492 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1493 * SPOOL_Q_OPEN_PRINTER_EX structure
1494 ********************************************************************/
1496 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1498 if (!q_u_ex || !q_u)
1501 DEBUG(8,("convert_to_openprinterex\n"));
1503 q_u_ex->printername_ptr = q_u->printername_ptr;
1505 if (q_u->printername_ptr)
1506 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1508 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1511 /********************************************************************
1512 * spoolss_open_printer
1514 * called from the spoolss dispatcher
1515 ********************************************************************/
1517 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1519 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1520 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1525 ZERO_STRUCT(q_u_ex);
1526 ZERO_STRUCT(r_u_ex);
1528 /* convert the OpenPrinter() call to OpenPrinterEx() */
1530 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1532 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1534 /* convert back to OpenPrinter() */
1536 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1541 /********************************************************************
1542 * spoolss_open_printer
1544 * If the openprinterex rpc call contains a devmode,
1545 * it's a per-user one. This per-user devmode is derivated
1546 * from the global devmode. Openprinterex() contains a per-user
1547 * devmode for when you do EMF printing and spooling.
1548 * In the EMF case, the NT workstation is only doing half the job
1549 * of rendering the page. The other half is done by running the printer
1550 * driver on the server.
1551 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1552 * The EMF file only contains what is to be printed on the page.
1553 * So in order for the server to know how to print, the NT client sends
1554 * a devicemode attached to the openprinterex call.
1555 * But this devicemode is short lived, it's only valid for the current print job.
1557 * If Samba would have supported EMF spooling, this devicemode would
1558 * have been attached to the handle, to sent it to the driver to correctly
1559 * rasterize the EMF file.
1561 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1562 * we just act as a pass-thru between windows and the printer.
1564 * In order to know that Samba supports only RAW spooling, NT has to call
1565 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1566 * and until NT sends a RAW job, we refuse it.
1568 * But to call getprinter() or startdoc(), you first need a valid handle,
1569 * and to get an handle you have to call openprintex(). Hence why you have
1570 * a devicemode in the openprinterex() call.
1573 * Differences between NT4 and NT 2000.
1576 * On NT4, you only have a global devicemode. This global devicemode can be changed
1577 * by the administrator (or by a user with enough privs). Everytime a user
1578 * wants to print, the devicemode is resetted to the default. In Word, everytime
1579 * you print, the printer's characteristics are always reset to the global devicemode.
1583 * In W2K, there is the notion of per-user devicemode. The first time you use
1584 * a printer, a per-user devicemode is build from the global devicemode.
1585 * If you change your per-user devicemode, it is saved in the registry, under the
1586 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1587 * printer preferences available.
1589 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1590 * on the General Tab of the printer properties windows.
1592 * To change the global devicemode: it's the "Printing Defaults..." button
1593 * on the Advanced Tab of the printer properties window.
1596 ********************************************************************/
1598 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1600 UNISTR2 *printername = NULL;
1601 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1602 POLICY_HND *handle = &r_u->handle;
1606 struct current_user user;
1607 Printer_entry *Printer=NULL;
1609 if (q_u->printername_ptr != 0)
1610 printername = &q_u->printername;
1612 if (printername == NULL)
1613 return WERR_INVALID_PRINTER_NAME;
1615 /* some sanity check because you can open a printer or a print server */
1616 /* aka: \\server\printer or \\server */
1617 unistr2_to_ascii(name, printername, sizeof(name)-1);
1619 DEBUGADD(3,("checking name: %s\n",name));
1621 if (!open_printer_hnd(p, handle, name, 0))
1622 return WERR_INVALID_PRINTER_NAME;
1624 Printer=find_printer_index_by_hnd(p, handle);
1626 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1627 Can't find printer handle we created for printer %s\n", name ));
1628 close_printer_handle(p,handle);
1629 return WERR_INVALID_PRINTER_NAME;
1632 get_current_user(&user, p);
1635 * First case: the user is opening the print server:
1637 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1638 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1640 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1641 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1642 * or if the user is listed in the smb.conf printer admin parameter.
1644 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1645 * client view printer folder, but does not show the MSAPW.
1647 * Note: this test needs code to check access rights here too. Jeremy
1648 * could you look at this?
1650 * Second case: the user is opening a printer:
1651 * NT doesn't let us connect to a printer if the connecting user
1652 * doesn't have print permission.
1655 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1657 /* Printserver handles use global struct... */
1661 /* Map standard access rights to object specific access rights */
1663 se_map_standard(&printer_default->access_required,
1664 &printserver_std_mapping);
1666 /* Deny any object specific bits that don't apply to print
1667 servers (i.e printer and job specific bits) */
1669 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1671 if (printer_default->access_required &
1672 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1673 DEBUG(3, ("access DENIED for non-printserver bits"));
1674 close_printer_handle(p, handle);
1675 return WERR_ACCESS_DENIED;
1678 /* Allow admin access */
1680 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1682 if (!lp_ms_add_printer_wizard()) {
1683 close_printer_handle(p, handle);
1684 return WERR_ACCESS_DENIED;
1687 /* if the user is not root and not a printer admin, then fail */
1690 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1692 close_printer_handle(p, handle);
1693 return WERR_ACCESS_DENIED;
1696 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1700 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1703 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1704 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1706 /* We fall through to return WERR_OK */
1711 /* NT doesn't let us connect to a printer if the connecting user
1712 doesn't have print permission. */
1714 if (!get_printer_snum(p, handle, &snum)) {
1715 close_printer_handle(p, handle);
1719 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1721 /* map an empty access mask to the minimum access mask */
1722 if (printer_default->access_required == 0x0)
1723 printer_default->access_required = PRINTER_ACCESS_USE;
1726 * If we are not serving the printer driver for this printer,
1727 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1728 * will keep NT clients happy --jerry
1731 if (lp_use_client_driver(snum)
1732 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1734 printer_default->access_required = PRINTER_ACCESS_USE;
1737 /* check smb.conf parameters and the the sec_desc */
1739 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1740 DEBUG(3, ("access DENIED for printer open\n"));
1741 close_printer_handle(p, handle);
1742 return WERR_ACCESS_DENIED;
1745 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1746 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1747 close_printer_handle(p, handle);
1748 return WERR_ACCESS_DENIED;
1751 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1752 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1754 printer_default->access_required = PRINTER_ACCESS_USE;
1756 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1757 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1761 Printer->access_granted = printer_default->access_required;
1764 * If the client sent a devmode in the OpenPrinter() call, then
1765 * save it here in case we get a job submission on this handle
1768 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1769 && q_u->printer_default.devmode_cont.devmode_ptr )
1771 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1772 &Printer->nt_devmode );
1775 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1776 optimization in Windows 2000 clients --jerry */
1778 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1779 && (RA_WIN2K == get_remote_arch()) )
1781 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1788 /****************************************************************************
1789 ****************************************************************************/
1791 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1792 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1798 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1807 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1808 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1814 printer->info_3=NULL;
1815 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1819 printer->info_6=NULL;
1820 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1830 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1831 NT_DEVICEMODE **pp_nt_devmode)
1833 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1836 * Ensure nt_devmode is a valid pointer
1837 * as we will be overwriting it.
1840 if (nt_devmode == NULL) {
1841 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1842 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1846 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1847 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1849 nt_devmode->specversion=devmode->specversion;
1850 nt_devmode->driverversion=devmode->driverversion;
1851 nt_devmode->size=devmode->size;
1852 nt_devmode->fields=devmode->fields;
1853 nt_devmode->orientation=devmode->orientation;
1854 nt_devmode->papersize=devmode->papersize;
1855 nt_devmode->paperlength=devmode->paperlength;
1856 nt_devmode->paperwidth=devmode->paperwidth;
1857 nt_devmode->scale=devmode->scale;
1858 nt_devmode->copies=devmode->copies;
1859 nt_devmode->defaultsource=devmode->defaultsource;
1860 nt_devmode->printquality=devmode->printquality;
1861 nt_devmode->color=devmode->color;
1862 nt_devmode->duplex=devmode->duplex;
1863 nt_devmode->yresolution=devmode->yresolution;
1864 nt_devmode->ttoption=devmode->ttoption;
1865 nt_devmode->collate=devmode->collate;
1867 nt_devmode->logpixels=devmode->logpixels;
1868 nt_devmode->bitsperpel=devmode->bitsperpel;
1869 nt_devmode->pelswidth=devmode->pelswidth;
1870 nt_devmode->pelsheight=devmode->pelsheight;
1871 nt_devmode->displayflags=devmode->displayflags;
1872 nt_devmode->displayfrequency=devmode->displayfrequency;
1873 nt_devmode->icmmethod=devmode->icmmethod;
1874 nt_devmode->icmintent=devmode->icmintent;
1875 nt_devmode->mediatype=devmode->mediatype;
1876 nt_devmode->dithertype=devmode->dithertype;
1877 nt_devmode->reserved1=devmode->reserved1;
1878 nt_devmode->reserved2=devmode->reserved2;
1879 nt_devmode->panningwidth=devmode->panningwidth;
1880 nt_devmode->panningheight=devmode->panningheight;
1883 * Only change private and driverextra if the incoming devmode
1884 * has a new one. JRA.
1887 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1888 SAFE_FREE(nt_devmode->private);
1889 nt_devmode->driverextra=devmode->driverextra;
1890 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1892 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1895 *pp_nt_devmode = nt_devmode;
1900 /********************************************************************
1901 * _spoolss_enddocprinter_internal.
1902 ********************************************************************/
1904 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1906 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1910 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1914 if (!get_printer_snum(p, handle, &snum))
1917 Printer->document_started=False;
1918 print_job_end(snum, Printer->jobid,True);
1919 /* error codes unhandled so far ... */
1924 /********************************************************************
1925 * api_spoolss_closeprinter
1926 ********************************************************************/
1928 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1930 POLICY_HND *handle = &q_u->handle;
1932 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1934 if (Printer && Printer->document_started)
1935 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1937 if (!close_printer_handle(p, handle))
1940 /* clear the returned printer handle. Observed behavior
1941 from Win2k server. Don't think this really matters.
1942 Previous code just copied the value of the closed
1945 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1950 /********************************************************************
1951 * api_spoolss_deleteprinter
1953 ********************************************************************/
1955 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1957 POLICY_HND *handle = &q_u->handle;
1958 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1961 if (Printer && Printer->document_started)
1962 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1964 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1966 result = delete_printer_handle(p, handle);
1968 update_c_setprinter(False);
1973 /*******************************************************************
1974 * static function to lookup the version id corresponding to an
1975 * long architecture string
1976 ******************************************************************/
1978 static int get_version_id (char * arch)
1981 struct table_node archi_table[]= {
1983 {"Windows 4.0", "WIN40", 0 },
1984 {"Windows NT x86", "W32X86", 2 },
1985 {"Windows NT R4000", "W32MIPS", 2 },
1986 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1987 {"Windows NT PowerPC", "W32PPC", 2 },
1991 for (i=0; archi_table[i].long_archi != NULL; i++)
1993 if (strcmp(arch, archi_table[i].long_archi) == 0)
1994 return (archi_table[i].version);
2000 /********************************************************************
2001 * _spoolss_deleteprinterdriver
2002 ********************************************************************/
2004 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2008 NT_PRINTER_DRIVER_INFO_LEVEL info;
2009 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2011 struct current_user user;
2013 WERROR status_win2k = WERR_ACCESS_DENIED;
2015 get_current_user(&user, p);
2017 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2018 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2020 /* check that we have a valid driver name first */
2022 if ((version=get_version_id(arch)) == -1)
2023 return WERR_INVALID_ENVIRONMENT;
2026 ZERO_STRUCT(info_win2k);
2028 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2030 /* try for Win2k driver if "Windows NT x86" */
2032 if ( version == 2 ) {
2034 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2035 status = WERR_UNKNOWN_PRINTER_DRIVER;
2039 /* otherwise it was a failure */
2041 status = WERR_UNKNOWN_PRINTER_DRIVER;
2047 if (printer_driver_in_use(info.info_3)) {
2048 status = WERR_PRINTER_DRIVER_IN_USE;
2054 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2056 /* if we get to here, we now have 2 driver info structures to remove */
2057 /* remove the Win2k driver first*/
2059 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2060 free_a_printer_driver( info_win2k, 3 );
2062 /* this should not have failed---if it did, report to client */
2063 if ( !W_ERROR_IS_OK(status_win2k) )
2068 status = delete_printer_driver(info.info_3, &user, version, False);
2070 /* if at least one of the deletes succeeded return OK */
2072 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2076 free_a_printer_driver( info, 3 );
2081 /********************************************************************
2082 * spoolss_deleteprinterdriverex
2083 ********************************************************************/
2085 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2089 NT_PRINTER_DRIVER_INFO_LEVEL info;
2090 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2092 uint32 flags = q_u->delete_flags;
2094 struct current_user user;
2096 WERROR status_win2k = WERR_ACCESS_DENIED;
2098 get_current_user(&user, p);
2100 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2101 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2103 /* check that we have a valid driver name first */
2104 if ((version=get_version_id(arch)) == -1) {
2105 /* this is what NT returns */
2106 return WERR_INVALID_ENVIRONMENT;
2109 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2110 version = q_u->version;
2113 ZERO_STRUCT(info_win2k);
2115 status = get_a_printer_driver(&info, 3, driver, arch, version);
2117 if ( !W_ERROR_IS_OK(status) )
2120 * if the client asked for a specific version,
2121 * or this is something other than Windows NT x86,
2125 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2128 /* try for Win2k driver if "Windows NT x86" */
2131 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2132 status = WERR_UNKNOWN_PRINTER_DRIVER;
2137 if ( printer_driver_in_use(info.info_3) ) {
2138 status = WERR_PRINTER_DRIVER_IN_USE;
2143 * we have a couple of cases to consider.
2144 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2145 * then the delete should fail if **any** files overlap with
2147 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2148 * non-overlapping files
2149 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2150 * is set, the do not delete any files
2151 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2154 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2156 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2158 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2159 /* no idea of the correct error here */
2160 status = WERR_ACCESS_DENIED;
2165 /* also check for W32X86/3 if necessary; maybe we already have? */
2167 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2168 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2171 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2172 /* no idea of the correct error here */
2173 free_a_printer_driver( info_win2k, 3 );
2174 status = WERR_ACCESS_DENIED;
2178 /* if we get to here, we now have 2 driver info structures to remove */
2179 /* remove the Win2k driver first*/
2181 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2182 free_a_printer_driver( info_win2k, 3 );
2184 /* this should not have failed---if it did, report to client */
2186 if ( !W_ERROR_IS_OK(status_win2k) )
2191 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2193 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2196 free_a_printer_driver( info, 3 );
2202 /****************************************************************************
2203 Internal routine for retreiving printerdata
2204 ***************************************************************************/
2206 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2207 const char *key, const char *value, uint32 *type, uint8 **data,
2208 uint32 *needed, uint32 in_size )
2210 REGISTRY_VALUE *val;
2213 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2214 return WERR_BADFILE;
2216 *type = regval_type( val );
2218 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2220 size = regval_size( val );
2222 /* copy the min(in_size, len) */
2225 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2227 /* special case for 0 length values */
2229 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2233 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2242 DEBUG(5,("get_printer_dataex: copy done\n"));
2247 /****************************************************************************
2248 Internal routine for removing printerdata
2249 ***************************************************************************/
2251 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2253 return delete_printer_data( printer->info_2, key, value );
2256 /****************************************************************************
2257 Internal routine for storing printerdata
2258 ***************************************************************************/
2260 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2261 uint32 type, uint8 *data, int real_len )
2263 delete_printer_data( printer->info_2, key, value );
2265 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2268 /********************************************************************
2269 GetPrinterData on a printer server Handle.
2270 ********************************************************************/
2272 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2276 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2278 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2280 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2286 if (!StrCaseCmp(value, "BeepEnabled")) {
2288 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2290 SIVAL(*data, 0, 0x00);
2295 if (!StrCaseCmp(value, "EventLog")) {
2297 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2299 /* formally was 0x1b */
2300 SIVAL(*data, 0, 0x0);
2305 if (!StrCaseCmp(value, "NetPopup")) {
2307 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2309 SIVAL(*data, 0, 0x00);
2314 if (!StrCaseCmp(value, "MajorVersion")) {
2316 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2319 /* Windows NT 4.0 seems to not allow uploading of drivers
2320 to a server that reports 0x3 as the MajorVersion.
2321 need to investigate more how Win2k gets around this .
2324 if ( RA_WINNT == get_remote_arch() )
2333 if (!StrCaseCmp(value, "MinorVersion")) {
2335 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2344 * uint32 size = 0x114
2346 * uint32 minor = [0|1]
2347 * uint32 build = [2195|2600]
2348 * extra unicode string = e.g. "Service Pack 3"
2350 if (!StrCaseCmp(value, "OSVersion")) {
2352 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2360 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2363 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2365 *needed = 2*(strlen(string)+1);
2366 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2368 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2370 /* it's done by hand ready to go on the wire */
2371 for (i=0; i<strlen(string); i++) {
2372 (*data)[2*i]=string[i];
2373 (*data)[2*i+1]='\0';
2378 if (!StrCaseCmp(value, "Architecture")) {
2379 pstring string="Windows NT x86";
2381 *needed = 2*(strlen(string)+1);
2382 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2384 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2385 for (i=0; i<strlen(string); i++) {
2386 (*data)[2*i]=string[i];
2387 (*data)[2*i+1]='\0';
2392 if (!StrCaseCmp(value, "DsPresent")) {
2394 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2396 SIVAL(*data, 0, 0x01);
2401 if (!StrCaseCmp(value, "DNSMachineName")) {
2404 if (!get_myfullname(hostname))
2405 return WERR_BADFILE;
2407 *needed = 2*(strlen(hostname)+1);
2408 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2410 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2411 for (i=0; i<strlen(hostname); i++) {
2412 (*data)[2*i]=hostname[i];
2413 (*data)[2*i+1]='\0';
2419 return WERR_BADFILE;
2422 /********************************************************************
2423 * spoolss_getprinterdata
2424 ********************************************************************/
2426 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2428 POLICY_HND *handle = &q_u->handle;
2429 UNISTR2 *valuename = &q_u->valuename;
2430 uint32 in_size = q_u->size;
2431 uint32 *type = &r_u->type;
2432 uint32 *out_size = &r_u->size;
2433 uint8 **data = &r_u->data;
2434 uint32 *needed = &r_u->needed;
2437 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2438 NT_PRINTER_INFO_LEVEL *printer = NULL;
2442 * Reminder: when it's a string, the length is in BYTES
2443 * even if UNICODE is negociated.
2448 *out_size = in_size;
2450 /* in case of problem, return some default values */
2455 DEBUG(4,("_spoolss_getprinterdata\n"));
2458 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2459 status = WERR_BADFID;
2463 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2465 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2466 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2469 if ( !get_printer_snum(p,handle, &snum) ) {
2470 status = WERR_BADFID;
2474 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2475 if ( !W_ERROR_IS_OK(status) )
2478 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2480 if ( strequal(value, "ChangeId") ) {
2482 *needed = sizeof(uint32);
2483 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2484 status = WERR_NOMEM;
2487 SIVAL( *data, 0, printer->info_2->changeid );
2491 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2494 if (*needed > *out_size)
2495 status = WERR_MORE_DATA;
2498 if ( !W_ERROR_IS_OK(status) )
2500 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2502 /* reply this param doesn't exist */
2505 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2507 free_a_printer( &printer, 2 );
2516 /* cleanup & exit */
2519 free_a_printer( &printer, 2 );
2524 /*********************************************************
2525 Connect to the client machine.
2526 **********************************************************/
2528 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2529 struct in_addr *client_ip, const char *remote_machine)
2531 ZERO_STRUCTP(the_cli);
2533 if(cli_initialise(the_cli) == NULL) {
2534 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2538 if ( is_zero_ip(*client_ip) ) {
2539 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2540 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2541 cli_shutdown(the_cli);
2545 if (ismyip(the_cli->dest_ip)) {
2546 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2547 cli_shutdown(the_cli);
2552 the_cli->dest_ip.s_addr = client_ip->s_addr;
2553 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2554 inet_ntoa(*client_ip) ));
2557 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2558 DEBUG(0,("spoolss_connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2559 cli_shutdown(the_cli);
2563 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2564 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2566 cli_shutdown(the_cli);
2570 the_cli->protocol = PROTOCOL_NT1;
2572 if (!cli_negprot(the_cli)) {
2573 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2574 cli_shutdown(the_cli);
2578 if (the_cli->protocol != PROTOCOL_NT1) {
2579 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2580 cli_shutdown(the_cli);
2585 * Do an anonymous session setup.
2588 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2589 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2590 cli_shutdown(the_cli);
2594 if (!(the_cli->sec_mode & 1)) {
2595 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2596 cli_shutdown(the_cli);
2600 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2601 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2602 cli_shutdown(the_cli);
2607 * Ok - we have an anonymous connection to the IPC$ share.
2608 * Now start the NT Domain stuff :-).
2611 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2612 DEBUG(0,("spoolss_connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2613 cli_nt_session_close(the_cli);
2614 cli_ulogoff(the_cli);
2615 cli_shutdown(the_cli);
2622 /***************************************************************************
2623 Connect to the client.
2624 ****************************************************************************/
2626 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2627 uint32 localprinter, uint32 type,
2628 POLICY_HND *handle, struct in_addr *client_ip)
2633 * If it's the first connection, contact the client
2634 * and connect to the IPC$ share anonymously
2636 if (smb_connections==0) {
2637 fstring unix_printer;
2639 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2641 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2644 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2645 /* Tell the connections db we're now interested in printer
2646 * notify messages. */
2647 register_message_flags( True, FLAG_MSG_PRINTING );
2651 * Tell the specific printing tdb we want messages for this printer
2652 * by registering our PID.
2655 if (!print_notify_register_pid(snum))
2656 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2660 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2663 if (!W_ERROR_IS_OK(result))
2664 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2665 dos_errstr(result)));
2667 return (W_ERROR_IS_OK(result));
2670 /********************************************************************
2672 * ReplyFindFirstPrinterChangeNotifyEx
2674 * before replying OK: status=0 a rpc call is made to the workstation
2675 * asking ReplyOpenPrinter
2677 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2678 * called from api_spoolss_rffpcnex
2679 ********************************************************************/
2681 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2683 POLICY_HND *handle = &q_u->handle;
2684 uint32 flags = q_u->flags;
2685 uint32 options = q_u->options;
2686 UNISTR2 *localmachine = &q_u->localmachine;
2687 uint32 printerlocal = q_u->printerlocal;
2689 SPOOL_NOTIFY_OPTION *option = q_u->option;
2690 struct in_addr client_ip;
2692 /* store the notify value in the printer struct */
2694 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2697 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2701 Printer->notify.flags=flags;
2702 Printer->notify.options=options;
2703 Printer->notify.printerlocal=printerlocal;
2705 if (Printer->notify.option)
2706 free_spool_notify_option(&Printer->notify.option);
2708 Printer->notify.option=dup_spool_notify_option(option);
2710 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2711 sizeof(Printer->notify.localmachine)-1);
2713 /* Connect to the client machine and send a ReplyOpenPrinter */
2715 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2717 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2718 !get_printer_snum(p, handle, &snum) )
2721 client_ip.s_addr = inet_addr(p->conn->client_address);
2723 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2724 Printer->notify.printerlocal, 1,
2725 &Printer->notify.client_hnd, &client_ip))
2726 return WERR_SERVER_UNAVAILABLE;
2728 Printer->notify.client_connected=True;
2733 /*******************************************************************
2734 * fill a notify_info_data with the servername
2735 ********************************************************************/
2737 void spoolss_notify_server_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)
2743 pstring temp_name, temp;
2746 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2748 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2750 data->notify_data.data.length = len;
2751 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2753 if (!data->notify_data.data.string) {
2754 data->notify_data.data.length = 0;
2758 memcpy(data->notify_data.data.string, temp, len);
2761 /*******************************************************************
2762 * fill a notify_info_data with the printername (not including the servername).
2763 ********************************************************************/
2765 void spoolss_notify_printer_name(int snum,
2766 SPOOL_NOTIFY_INFO_DATA *data,
2767 print_queue_struct *queue,
2768 NT_PRINTER_INFO_LEVEL *printer,
2769 TALLOC_CTX *mem_ctx)
2774 /* the notify name should not contain the \\server\ part */
2775 char *p = strrchr(printer->info_2->printername, '\\');
2778 p = printer->info_2->printername;
2783 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2785 data->notify_data.data.length = len;
2786 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2788 if (!data->notify_data.data.string) {
2789 data->notify_data.data.length = 0;
2793 memcpy(data->notify_data.data.string, temp, len);
2796 /*******************************************************************
2797 * fill a notify_info_data with the servicename
2798 ********************************************************************/
2800 void spoolss_notify_share_name(int snum,
2801 SPOOL_NOTIFY_INFO_DATA *data,
2802 print_queue_struct *queue,
2803 NT_PRINTER_INFO_LEVEL *printer,
2804 TALLOC_CTX *mem_ctx)
2809 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2811 data->notify_data.data.length = len;
2812 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2814 if (!data->notify_data.data.string) {
2815 data->notify_data.data.length = 0;
2819 memcpy(data->notify_data.data.string, temp, len);
2822 /*******************************************************************
2823 * fill a notify_info_data with the port name
2824 ********************************************************************/
2826 void spoolss_notify_port_name(int snum,
2827 SPOOL_NOTIFY_INFO_DATA *data,
2828 print_queue_struct *queue,
2829 NT_PRINTER_INFO_LEVEL *printer,
2830 TALLOC_CTX *mem_ctx)
2835 /* even if it's strange, that's consistant in all the code */
2837 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2839 data->notify_data.data.length = len;
2840 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2842 if (!data->notify_data.data.string) {
2843 data->notify_data.data.length = 0;
2847 memcpy(data->notify_data.data.string, temp, len);
2850 /*******************************************************************
2851 * fill a notify_info_data with the printername
2852 * but it doesn't exist, have to see what to do
2853 ********************************************************************/
2855 void spoolss_notify_driver_name(int snum,
2856 SPOOL_NOTIFY_INFO_DATA *data,
2857 print_queue_struct *queue,
2858 NT_PRINTER_INFO_LEVEL *printer,
2859 TALLOC_CTX *mem_ctx)
2864 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2866 data->notify_data.data.length = len;
2867 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2869 if (!data->notify_data.data.string) {
2870 data->notify_data.data.length = 0;
2874 memcpy(data->notify_data.data.string, temp, len);
2877 /*******************************************************************
2878 * fill a notify_info_data with the comment
2879 ********************************************************************/
2881 void spoolss_notify_comment(int snum,
2882 SPOOL_NOTIFY_INFO_DATA *data,
2883 print_queue_struct *queue,
2884 NT_PRINTER_INFO_LEVEL *printer,
2885 TALLOC_CTX *mem_ctx)
2890 if (*printer->info_2->comment == '\0')
2891 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2893 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2895 data->notify_data.data.length = len;
2896 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2898 if (!data->notify_data.data.string) {
2899 data->notify_data.data.length = 0;
2903 memcpy(data->notify_data.data.string, temp, len);
2906 /*******************************************************************
2907 * fill a notify_info_data with the comment
2908 * location = "Room 1, floor 2, building 3"
2909 ********************************************************************/
2911 void spoolss_notify_location(int snum,
2912 SPOOL_NOTIFY_INFO_DATA *data,
2913 print_queue_struct *queue,
2914 NT_PRINTER_INFO_LEVEL *printer,
2915 TALLOC_CTX *mem_ctx)
2920 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2922 data->notify_data.data.length = len;
2923 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2925 if (!data->notify_data.data.string) {
2926 data->notify_data.data.length = 0;
2930 memcpy(data->notify_data.data.string, temp, len);
2933 /*******************************************************************
2934 * fill a notify_info_data with the device mode
2935 * jfm:xxxx don't to it for know but that's a real problem !!!
2936 ********************************************************************/
2938 static void spoolss_notify_devmode(int snum,
2939 SPOOL_NOTIFY_INFO_DATA *data,
2940 print_queue_struct *queue,
2941 NT_PRINTER_INFO_LEVEL *printer,
2942 TALLOC_CTX *mem_ctx)
2946 /*******************************************************************
2947 * fill a notify_info_data with the separator file name
2948 ********************************************************************/
2950 void spoolss_notify_sepfile(int snum,
2951 SPOOL_NOTIFY_INFO_DATA *data,
2952 print_queue_struct *queue,
2953 NT_PRINTER_INFO_LEVEL *printer,
2954 TALLOC_CTX *mem_ctx)
2959 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2961 data->notify_data.data.length = len;
2962 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2964 if (!data->notify_data.data.string) {
2965 data->notify_data.data.length = 0;
2969 memcpy(data->notify_data.data.string, temp, len);
2972 /*******************************************************************
2973 * fill a notify_info_data with the print processor
2974 * jfm:xxxx return always winprint to indicate we don't do anything to it
2975 ********************************************************************/
2977 void spoolss_notify_print_processor(int snum,
2978 SPOOL_NOTIFY_INFO_DATA *data,
2979 print_queue_struct *queue,
2980 NT_PRINTER_INFO_LEVEL *printer,
2981 TALLOC_CTX *mem_ctx)
2986 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2988 data->notify_data.data.length = len;
2989 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2991 if (!data->notify_data.data.string) {
2992 data->notify_data.data.length = 0;
2996 memcpy(data->notify_data.data.string, temp, len);
2999 /*******************************************************************
3000 * fill a notify_info_data with the print processor options
3001 * jfm:xxxx send an empty string
3002 ********************************************************************/
3004 void spoolss_notify_parameters(int snum,
3005 SPOOL_NOTIFY_INFO_DATA *data,
3006 print_queue_struct *queue,
3007 NT_PRINTER_INFO_LEVEL *printer,
3008 TALLOC_CTX *mem_ctx)
3013 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3015 data->notify_data.data.length = len;
3016 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3018 if (!data->notify_data.data.string) {
3019 data->notify_data.data.length = 0;
3023 memcpy(data->notify_data.data.string, temp, len);
3026 /*******************************************************************
3027 * fill a notify_info_data with the data type
3028 * jfm:xxxx always send RAW as data type
3029 ********************************************************************/
3031 void spoolss_notify_datatype(int snum,
3032 SPOOL_NOTIFY_INFO_DATA *data,
3033 print_queue_struct *queue,
3034 NT_PRINTER_INFO_LEVEL *printer,
3035 TALLOC_CTX *mem_ctx)
3040 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3042 data->notify_data.data.length = len;
3043 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3045 if (!data->notify_data.data.string) {
3046 data->notify_data.data.length = 0;
3050 memcpy(data->notify_data.data.string, temp, len);
3053 /*******************************************************************
3054 * fill a notify_info_data with the security descriptor
3055 * jfm:xxxx send an null pointer to say no security desc
3056 * have to implement security before !
3057 ********************************************************************/
3059 static void spoolss_notify_security_desc(int snum,
3060 SPOOL_NOTIFY_INFO_DATA *data,
3061 print_queue_struct *queue,
3062 NT_PRINTER_INFO_LEVEL *printer,
3063 TALLOC_CTX *mem_ctx)
3065 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3066 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3069 /*******************************************************************
3070 * fill a notify_info_data with the attributes
3071 * jfm:xxxx a samba printer is always shared
3072 ********************************************************************/
3074 void spoolss_notify_attributes(int snum,
3075 SPOOL_NOTIFY_INFO_DATA *data,
3076 print_queue_struct *queue,
3077 NT_PRINTER_INFO_LEVEL *printer,
3078 TALLOC_CTX *mem_ctx)
3080 data->notify_data.value[0] = printer->info_2->attributes;
3081 data->notify_data.value[1] = 0;
3084 /*******************************************************************
3085 * fill a notify_info_data with the priority
3086 ********************************************************************/
3088 static void spoolss_notify_priority(int snum,
3089 SPOOL_NOTIFY_INFO_DATA *data,
3090 print_queue_struct *queue,
3091 NT_PRINTER_INFO_LEVEL *printer,
3092 TALLOC_CTX *mem_ctx)
3094 data->notify_data.value[0] = printer->info_2->priority;
3095 data->notify_data.value[1] = 0;
3098 /*******************************************************************
3099 * fill a notify_info_data with the default priority
3100 ********************************************************************/
3102 static void spoolss_notify_default_priority(int snum,
3103 SPOOL_NOTIFY_INFO_DATA *data,
3104 print_queue_struct *queue,
3105 NT_PRINTER_INFO_LEVEL *printer,
3106 TALLOC_CTX *mem_ctx)
3108 data->notify_data.value[0] = printer->info_2->default_priority;
3109 data->notify_data.value[1] = 0;
3112 /*******************************************************************
3113 * fill a notify_info_data with the start time
3114 ********************************************************************/
3116 static void spoolss_notify_start_time(int snum,
3117 SPOOL_NOTIFY_INFO_DATA *data,
3118 print_queue_struct *queue,
3119 NT_PRINTER_INFO_LEVEL *printer,
3120 TALLOC_CTX *mem_ctx)
3122 data->notify_data.value[0] = printer->info_2->starttime;
3123 data->notify_data.value[1] = 0;
3126 /*******************************************************************
3127 * fill a notify_info_data with the until time
3128 ********************************************************************/
3130 static void spoolss_notify_until_time(int snum,
3131 SPOOL_NOTIFY_INFO_DATA *data,
3132 print_queue_struct *queue,
3133 NT_PRINTER_INFO_LEVEL *printer,
3134 TALLOC_CTX *mem_ctx)
3136 data->notify_data.value[0] = printer->info_2->untiltime;
3137 data->notify_data.value[1] = 0;
3140 /*******************************************************************
3141 * fill a notify_info_data with the status
3142 ********************************************************************/
3144 static void spoolss_notify_status(int snum,
3145 SPOOL_NOTIFY_INFO_DATA *data,
3146 print_queue_struct *queue,
3147 NT_PRINTER_INFO_LEVEL *printer,
3148 TALLOC_CTX *mem_ctx)
3150 print_status_struct status;
3152 print_queue_length(snum, &status);
3153 data->notify_data.value[0]=(uint32) status.status;
3154 data->notify_data.value[1] = 0;
3157 /*******************************************************************
3158 * fill a notify_info_data with the number of jobs queued
3159 ********************************************************************/
3161 void spoolss_notify_cjobs(int snum,
3162 SPOOL_NOTIFY_INFO_DATA *data,
3163 print_queue_struct *queue,
3164 NT_PRINTER_INFO_LEVEL *printer,
3165 TALLOC_CTX *mem_ctx)
3167 data->notify_data.value[0] = print_queue_length(snum, NULL);
3168 data->notify_data.value[1] = 0;
3171 /*******************************************************************
3172 * fill a notify_info_data with the average ppm
3173 ********************************************************************/
3175 static void spoolss_notify_average_ppm(int snum,
3176 SPOOL_NOTIFY_INFO_DATA *data,
3177 print_queue_struct *queue,
3178 NT_PRINTER_INFO_LEVEL *printer,
3179 TALLOC_CTX *mem_ctx)
3181 /* always respond 8 pages per minutes */
3182 /* a little hard ! */
3183 data->notify_data.value[0] = printer->info_2->averageppm;
3184 data->notify_data.value[1] = 0;
3187 /*******************************************************************
3188 * fill a notify_info_data with username
3189 ********************************************************************/
3191 static void spoolss_notify_username(int snum,
3192 SPOOL_NOTIFY_INFO_DATA *data,
3193 print_queue_struct *queue,
3194 NT_PRINTER_INFO_LEVEL *printer,
3195 TALLOC_CTX *mem_ctx)
3200 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3202 data->notify_data.data.length = len;
3203 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3205 if (!data->notify_data.data.string) {
3206 data->notify_data.data.length = 0;
3210 memcpy(data->notify_data.data.string, temp, len);
3213 /*******************************************************************
3214 * fill a notify_info_data with job status
3215 ********************************************************************/
3217 static void spoolss_notify_job_status(int snum,
3218 SPOOL_NOTIFY_INFO_DATA *data,
3219 print_queue_struct *queue,
3220 NT_PRINTER_INFO_LEVEL *printer,
3221 TALLOC_CTX *mem_ctx)
3223 data->notify_data.value[0]=nt_printj_status(queue->status);
3224 data->notify_data.value[1] = 0;
3227 /*******************************************************************
3228 * fill a notify_info_data with job name
3229 ********************************************************************/
3231 static void spoolss_notify_job_name(int snum,
3232 SPOOL_NOTIFY_INFO_DATA *data,
3233 print_queue_struct *queue,
3234 NT_PRINTER_INFO_LEVEL *printer,
3235 TALLOC_CTX *mem_ctx)
3240 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3242 data->notify_data.data.length = len;
3243 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3245 if (!data->notify_data.data.string) {
3246 data->notify_data.data.length = 0;
3250 memcpy(data->notify_data.data.string, temp, len);
3253 /*******************************************************************
3254 * fill a notify_info_data with job status
3255 ********************************************************************/
3257 static void spoolss_notify_job_status_string(int snum,
3258 SPOOL_NOTIFY_INFO_DATA *data,
3259 print_queue_struct *queue,
3260 NT_PRINTER_INFO_LEVEL *printer,
3261 TALLOC_CTX *mem_ctx)
3264 * Now we're returning job status codes we just return a "" here. JRA.
3271 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3274 switch (queue->status) {
3279 p = ""; /* NT provides the paused string */
3288 #endif /* NO LONGER NEEDED. */
3290 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3292 data->notify_data.data.length = len;
3293 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3295 if (!data->notify_data.data.string) {
3296 data->notify_data.data.length = 0;
3300 memcpy(data->notify_data.data.string, temp, len);
3303 /*******************************************************************
3304 * fill a notify_info_data with job time
3305 ********************************************************************/
3307 static void spoolss_notify_job_time(int snum,
3308 SPOOL_NOTIFY_INFO_DATA *data,
3309 print_queue_struct *queue,
3310 NT_PRINTER_INFO_LEVEL *printer,
3311 TALLOC_CTX *mem_ctx)
3313 data->notify_data.value[0]=0x0;
3314 data->notify_data.value[1]=0;
3317 /*******************************************************************
3318 * fill a notify_info_data with job size
3319 ********************************************************************/
3321 static void spoolss_notify_job_size(int snum,
3322 SPOOL_NOTIFY_INFO_DATA *data,
3323 print_queue_struct *queue,
3324 NT_PRINTER_INFO_LEVEL *printer,
3325 TALLOC_CTX *mem_ctx)
3327 data->notify_data.value[0]=queue->size;
3328 data->notify_data.value[1]=0;
3331 /*******************************************************************
3332 * fill a notify_info_data with page info
3333 ********************************************************************/
3334 static void spoolss_notify_total_pages(int snum,
3335 SPOOL_NOTIFY_INFO_DATA *data,
3336 print_queue_struct *queue,
3337 NT_PRINTER_INFO_LEVEL *printer,
3338 TALLOC_CTX *mem_ctx)
3340 data->notify_data.value[0]=queue->page_count;
3341 data->notify_data.value[1]=0;
3344 /*******************************************************************
3345 * fill a notify_info_data with pages printed info.
3346 ********************************************************************/
3347 static void spoolss_notify_pages_printed(int snum,
3348 SPOOL_NOTIFY_INFO_DATA *data,
3349 print_queue_struct *queue,
3350 NT_PRINTER_INFO_LEVEL *printer,
3351 TALLOC_CTX *mem_ctx)
3353 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3354 data->notify_data.value[1]=0;
3357 /*******************************************************************
3358 Fill a notify_info_data with job position.
3359 ********************************************************************/
3361 static void spoolss_notify_job_position(int snum,
3362 SPOOL_NOTIFY_INFO_DATA *data,
3363 print_queue_struct *queue,
3364 NT_PRINTER_INFO_LEVEL *printer,
3365 TALLOC_CTX *mem_ctx)
3367 data->notify_data.value[0]=queue->job;
3368 data->notify_data.value[1]=0;
3371 /*******************************************************************
3372 Fill a notify_info_data with submitted time.
3373 ********************************************************************/
3375 static void spoolss_notify_submitted_time(int snum,
3376 SPOOL_NOTIFY_INFO_DATA *data,
3377 print_queue_struct *queue,
3378 NT_PRINTER_INFO_LEVEL *printer,
3379 TALLOC_CTX *mem_ctx)
3386 t=gmtime(&queue->time);
3388 len = sizeof(SYSTEMTIME);
3390 data->notify_data.data.length = len;
3391 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3393 if (!data->notify_data.data.string) {
3394 data->notify_data.data.length = 0;
3398 make_systemtime(&st, t);
3401 * Systemtime must be linearized as a set of UINT16's.
3402 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3405 p = (char *)data->notify_data.data.string;
3406 SSVAL(p, 0, st.year);
3407 SSVAL(p, 2, st.month);
3408 SSVAL(p, 4, st.dayofweek);
3409 SSVAL(p, 6, st.day);
3410 SSVAL(p, 8, st.hour);
3411 SSVAL(p, 10, st.minute);
3412 SSVAL(p, 12, st.second);
3413 SSVAL(p, 14, st.milliseconds);
3416 struct s_notify_info_data_table
3422 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3423 print_queue_struct *queue,
3424 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3427 /* A table describing the various print notification constants and
3428 whether the notification data is a pointer to a variable sized
3429 buffer, a one value uint32 or a two value uint32. */
3431 static const struct s_notify_info_data_table notify_info_data_table[] =
3433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3463 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3484 /*******************************************************************
3485 Return the size of info_data structure.
3486 ********************************************************************/
3488 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3492 for (i = 0; i < sizeof(notify_info_data_table); i++)
3494 if ( (notify_info_data_table[i].type == type)
3495 && (notify_info_data_table[i].field == field) )
3497 switch(notify_info_data_table[i].size)
3499 case NOTIFY_ONE_VALUE:
3500 case NOTIFY_TWO_VALUE:
3505 /* The only pointer notify data I have seen on
3506 the wire is the submitted time and this has
3507 the notify size set to 4. -tpot */
3509 case NOTIFY_POINTER:
3512 case NOTIFY_SECDESC:
3518 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3523 /*******************************************************************
3524 Return the type of notify_info_data.
3525 ********************************************************************/
3527 static int type_of_notify_info_data(uint16 type, uint16 field)
3531 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3532 if (notify_info_data_table[i].type == type &&
3533 notify_info_data_table[i].field == field)
3534 return notify_info_data_table[i].size;
3540 /****************************************************************************
3541 ****************************************************************************/
3543 static int search_notify(uint16 type, uint16 field, int *value)
3547 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3548 if (notify_info_data_table[i].type == type &&
3549 notify_info_data_table[i].field == field &&
3550 notify_info_data_table[i].fn != NULL) {
3559 /****************************************************************************
3560 ****************************************************************************/
3562 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3564 info_data->type = type;
3565 info_data->field = field;
3566 info_data->reserved = 0;
3568 info_data->size = size_of_notify_info_data(type, field);
3569 info_data->enc_type = type_of_notify_info_data(type, field);
3576 /*******************************************************************
3578 * fill a notify_info struct with info asked
3580 ********************************************************************/
3582 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3583 snum, SPOOL_NOTIFY_OPTION_TYPE
3584 *option_type, uint32 id,
3585 TALLOC_CTX *mem_ctx)
3591 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3592 NT_PRINTER_INFO_LEVEL *printer = NULL;
3593 print_queue_struct *queue=NULL;
3595 type=option_type->type;
3597 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3598 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3599 option_type->count, lp_servicename(snum)));
3601 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3604 for(field_num=0; field_num<option_type->count; field_num++) {
3605 field = option_type->fields[field_num];
3607 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3609 if (!search_notify(type, field, &j) )
3612 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3613 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3618 current_data = &info->data[info->count];
3620 construct_info_data(current_data, type, field, id);
3622 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3623 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3625 notify_info_data_table[j].fn(snum, current_data, queue,
3631 free_a_printer(&printer, 2);
3635 /*******************************************************************
3637 * fill a notify_info struct with info asked
3639 ********************************************************************/
3641 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3642 SPOOL_NOTIFY_INFO *info,
3643 NT_PRINTER_INFO_LEVEL *printer,
3644 int snum, SPOOL_NOTIFY_OPTION_TYPE
3645 *option_type, uint32 id,
3646 TALLOC_CTX *mem_ctx)
3652 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3654 DEBUG(4,("construct_notify_jobs_info\n"));
3656 type = option_type->type;
3658 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3659 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3660 option_type->count));
3662 for(field_num=0; field_num<option_type->count; field_num++) {
3663 field = option_type->fields[field_num];
3665 if (!search_notify(type, field, &j) )
3668 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3669 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3672 else info->data = tid;
3674 current_data=&(info->data[info->count]);
3676 construct_info_data(current_data, type, field, id);
3677 notify_info_data_table[j].fn(snum, current_data, queue,
3686 * JFM: The enumeration is not that simple, it's even non obvious.
3688 * let's take an example: I want to monitor the PRINTER SERVER for
3689 * the printer's name and the number of jobs currently queued.
3690 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3691 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3693 * I have 3 printers on the back of my server.
3695 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3698 * 1 printer 1 name 1
3699 * 2 printer 1 cjob 1
3700 * 3 printer 2 name 2
3701 * 4 printer 2 cjob 2
3702 * 5 printer 3 name 3
3703 * 6 printer 3 name 3
3705 * that's the print server case, the printer case is even worse.
3708 /*******************************************************************
3710 * enumerate all printers on the printserver
3711 * fill a notify_info struct with info asked
3713 ********************************************************************/
3715 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3716 SPOOL_NOTIFY_INFO *info,
3717 TALLOC_CTX *mem_ctx)
3720 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3721 int n_services=lp_numservices();
3724 SPOOL_NOTIFY_OPTION *option;
3725 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3727 DEBUG(4,("printserver_notify_info\n"));
3732 option=Printer->notify.option;
3738 for (i=0; i<option->count; i++) {
3739 option_type=&(option->ctr.type[i]);
3741 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3744 for (snum=0; snum<n_services; snum++)
3746 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3747 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3753 * Debugging information, don't delete.
3756 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3757 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3758 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3760 for (i=0; i<info->count; i++) {
3761 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3762 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3763 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3770 /*******************************************************************
3772 * fill a notify_info struct with info asked
3774 ********************************************************************/
3776 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3777 TALLOC_CTX *mem_ctx)
3780 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3783 SPOOL_NOTIFY_OPTION *option;
3784 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3786 print_queue_struct *queue=NULL;
3787 print_status_struct status;
3789 DEBUG(4,("printer_notify_info\n"));
3794 option=Printer->notify.option;
3800 get_printer_snum(p, hnd, &snum);
3802 for (i=0; i<option->count; i++) {
3803 option_type=&option->ctr.type[i];
3805 switch ( option_type->type ) {
3806 case PRINTER_NOTIFY_TYPE:
3807 if(construct_notify_printer_info(Printer, info, snum,
3813 case JOB_NOTIFY_TYPE: {
3814 NT_PRINTER_INFO_LEVEL *printer = NULL;
3816 count = print_queue_status(snum, &queue, &status);
3818 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3821 for (j=0; j<count; j++) {
3822 construct_notify_jobs_info(&queue[j], info,
3829 free_a_printer(&printer, 2);
3839 * Debugging information, don't delete.
3842 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3843 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3844 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3846 for (i=0; i<info->count; i++) {
3847 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3848 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3849 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3855 /********************************************************************
3857 ********************************************************************/
3859 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3861 POLICY_HND *handle = &q_u->handle;
3862 SPOOL_NOTIFY_INFO *info = &r_u->info;
3864 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3865 WERROR result = WERR_BADFID;
3867 /* we always have a NOTIFY_INFO struct */
3871 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3872 OUR_HANDLE(handle)));
3876 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3879 * We are now using the change value, and
3880 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3881 * I don't have a global notification system, I'm sending back all the
3882 * informations even when _NOTHING_ has changed.
3885 /* We need to keep track of the change value to send back in
3886 RRPCN replies otherwise our updates are ignored. */
3888 Printer->notify.fnpcn = True;
3890 if (Printer->notify.client_connected) {
3891 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3892 Printer->notify.change = q_u->change;
3895 /* just ignore the SPOOL_NOTIFY_OPTION */
3897 switch (Printer->printer_type) {
3898 case PRINTER_HANDLE_IS_PRINTSERVER:
3899 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3902 case PRINTER_HANDLE_IS_PRINTER:
3903 result = printer_notify_info(p, handle, info, p->mem_ctx);
3907 Printer->notify.fnpcn = False;
3913 /********************************************************************
3914 * construct_printer_info_0
3915 * fill a printer_info_0 struct
3916 ********************************************************************/
3918 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3922 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3923 counter_printer_0 *session_counter;
3924 uint32 global_counter;
3927 print_status_struct status;
3929 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3932 count = print_queue_length(snum, &status);
3934 /* check if we already have a counter for this printer */
3935 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3937 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3938 if (session_counter->snum == snum)
3942 /* it's the first time, add it to the list */
3943 if (session_counter==NULL) {
3944 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3945 free_a_printer(&ntprinter, 2);
3948 ZERO_STRUCTP(session_counter);
3949 session_counter->snum=snum;
3950 session_counter->counter=0;
3951 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3955 session_counter->counter++;
3958 * the global_counter should be stored in a TDB as it's common to all the clients
3959 * and should be zeroed on samba startup
3961 global_counter=session_counter->counter;
3963 pstrcpy(chaine,ntprinter->info_2->printername);
3965 init_unistr(&printer->printername, chaine);
3967 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3968 init_unistr(&printer->servername, chaine);
3970 printer->cjobs = count;
3971 printer->total_jobs = 0;
3972 printer->total_bytes = 0;
3974 setuptime = (time_t)ntprinter->info_2->setuptime;
3975 t=gmtime(&setuptime);
3977 printer->year = t->tm_year+1900;
3978 printer->month = t->tm_mon+1;
3979 printer->dayofweek = t->tm_wday;
3980 printer->day = t->tm_mday;
3981 printer->hour = t->tm_hour;
3982 printer->minute = t->tm_min;
3983 printer->second = t->tm_sec;
3984 printer->milliseconds = 0;
3986 printer->global_counter = global_counter;
3987 printer->total_pages = 0;
3989 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3990 printer->major_version = 0x0005; /* NT 5 */
3991 printer->build_version = 0x0893; /* build 2195 */
3993 printer->unknown7 = 0x1;
3994 printer->unknown8 = 0x0;
3995 printer->unknown9 = 0x0;
3996 printer->session_counter = session_counter->counter;
3997 printer->unknown11 = 0x0;
3998 printer->printer_errors = 0x0; /* number of print failure */
3999 printer->unknown13 = 0x0;
4000 printer->unknown14 = 0x1;
4001 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4002 printer->unknown16 = 0x0;
4003 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4004 printer->unknown18 = 0x0;
4005 printer->status = nt_printq_status(status.status);
4006 printer->unknown20 = 0x0;
4007 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4008 printer->unknown22 = 0x0;
4009 printer->unknown23 = 0x6; /* 6 ???*/
4010 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4011 printer->unknown25 = 0;
4012 printer->unknown26 = 0;
4013 printer->unknown27 = 0;
4014 printer->unknown28 = 0;
4015 printer->unknown29 = 0;
4017 free_a_printer(&ntprinter,2);
4021 /********************************************************************
4022 * construct_printer_info_1
4023 * fill a printer_info_1 struct
4024 ********************************************************************/
4025 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4029 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4031 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4034 printer->flags=flags;
4036 if (*ntprinter->info_2->comment == '\0') {
4037 init_unistr(&printer->comment, lp_comment(snum));
4038 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4039 ntprinter->info_2->drivername, lp_comment(snum));
4042 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4043 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4044 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4047 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4049 init_unistr(&printer->description, chaine);
4050 init_unistr(&printer->name, chaine2);
4052 free_a_printer(&ntprinter,2);
4057 /****************************************************************************
4058 Free a DEVMODE struct.
4059 ****************************************************************************/
4061 static void free_dev_mode(DEVICEMODE *dev)
4066 SAFE_FREE(dev->private);
4071 /****************************************************************************
4072 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4073 should be valid upon entry
4074 ****************************************************************************/
4076 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4078 if ( !devmode || !ntdevmode )
4081 init_unistr(&devmode->devicename, ntdevmode->devicename);
4083 init_unistr(&devmode->formname, ntdevmode->formname);
4085 devmode->specversion = ntdevmode->specversion;
4086 devmode->driverversion = ntdevmode->driverversion;
4087 devmode->size = ntdevmode->size;
4088 devmode->driverextra = ntdevmode->driverextra;
4089 devmode->fields = ntdevmode->fields;
4091 devmode->orientation = ntdevmode->orientation;
4092 devmode->papersize = ntdevmode->papersize;
4093 devmode->paperlength = ntdevmode->paperlength;
4094 devmode->paperwidth = ntdevmode->paperwidth;
4095 devmode->scale = ntdevmode->scale;
4096 devmode->copies = ntdevmode->copies;
4097 devmode->defaultsource = ntdevmode->defaultsource;
4098 devmode->printquality = ntdevmode->printquality;
4099 devmode->color = ntdevmode->color;
4100 devmode->duplex = ntdevmode->duplex;
4101 devmode->yresolution = ntdevmode->yresolution;
4102 devmode->ttoption = ntdevmode->ttoption;
4103 devmode->collate = ntdevmode->collate;
4104 devmode->icmmethod = ntdevmode->icmmethod;
4105 devmode->icmintent = ntdevmode->icmintent;
4106 devmode->mediatype = ntdevmode->mediatype;
4107 devmode->dithertype = ntdevmode->dithertype;
4109 if (ntdevmode->private != NULL) {
4110 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4117 /****************************************************************************
4118 Create a DEVMODE struct. Returns malloced memory.
4119 ****************************************************************************/
4121 DEVICEMODE *construct_dev_mode(int snum)
4123 NT_PRINTER_INFO_LEVEL *printer = NULL;
4124 DEVICEMODE *devmode = NULL;
4126 DEBUG(7,("construct_dev_mode\n"));
4128 DEBUGADD(8,("getting printer characteristics\n"));
4130 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4133 if ( !printer->info_2->devmode ) {
4134 DEBUG(5, ("BONG! There was no device mode!\n"));
4138 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4139 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4143 ZERO_STRUCTP(devmode);
4145 DEBUGADD(8,("loading DEVICEMODE\n"));
4147 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4148 free_dev_mode( devmode );
4153 free_a_printer(&printer,2);
4158 /********************************************************************
4159 * construct_printer_info_2
4160 * fill a printer_info_2 struct
4161 ********************************************************************/
4163 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4166 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4168 print_status_struct status;
4170 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4173 count = print_queue_length(snum, &status);
4175 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4176 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4177 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4178 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4179 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4181 if (*ntprinter->info_2->comment == '\0')
4182 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4184 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4186 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4187 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4188 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4189 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4190 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4192 printer->attributes = ntprinter->info_2->attributes;
4194 printer->priority = ntprinter->info_2->priority; /* priority */
4195 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4196 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4197 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4198 printer->status = nt_printq_status(status.status); /* status */
4199 printer->cjobs = count; /* jobs */
4200 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4202 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4203 DEBUG(8, ("Returning NULL Devicemode!\n"));
4206 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4207 /* steal the printer info sec_desc structure. [badly done]. */
4208 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4209 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4210 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4211 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4214 printer->secdesc = NULL;
4217 free_a_printer(&ntprinter, 2);
4221 /********************************************************************
4222 * construct_printer_info_3
4223 * fill a printer_info_3 struct
4224 ********************************************************************/
4226 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4228 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4229 PRINTER_INFO_3 *printer = NULL;
4231 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4235 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4236 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4240 ZERO_STRUCTP(printer);
4242 printer->flags = 4; /* These are the components of the SD we are returning. */
4243 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4244 /* steal the printer info sec_desc structure. [badly done]. */
4245 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4249 * Set the flags for the components we are returning.
4252 if (printer->secdesc->owner_sid)
4253 printer->flags |= OWNER_SECURITY_INFORMATION;
4255 if (printer->secdesc->grp_sid)
4256 printer->flags |= GROUP_SECURITY_INFORMATION;
4258 if (printer->secdesc->dacl)
4259 printer->flags |= DACL_SECURITY_INFORMATION;
4261 if (printer->secdesc->sacl)
4262 printer->flags |= SACL_SECURITY_INFORMATION;
4265 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4266 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4267 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4270 free_a_printer(&ntprinter, 2);
4272 *pp_printer = printer;
4276 /********************************************************************
4277 * construct_printer_info_4
4278 * fill a printer_info_4 struct
4279 ********************************************************************/
4281 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4283 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4285 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4288 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4289 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4290 printer->attributes = ntprinter->info_2->attributes;
4292 free_a_printer(&ntprinter, 2);
4296 /********************************************************************
4297 * construct_printer_info_5
4298 * fill a printer_info_5 struct
4299 ********************************************************************/
4301 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4303 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4305 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4308 init_unistr(&printer->printername, ntprinter->info_2->printername);
4309 init_unistr(&printer->portname, ntprinter->info_2->portname);
4310 printer->attributes = ntprinter->info_2->attributes;
4312 /* these two are not used by NT+ according to MSDN */
4314 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4315 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4317 free_a_printer(&ntprinter, 2);
4322 /********************************************************************
4323 * construct_printer_info_7
4324 * fill a printer_info_7 struct
4325 ********************************************************************/
4327 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4329 char *guid_str = NULL;
4332 if (is_printer_published(print_hnd, snum, &guid)) {
4333 asprintf(&guid_str, "{%s}", uuid_string_static(guid));
4335 init_unistr(&printer->guid, guid_str);
4336 printer->action = SPOOL_DS_PUBLISH;
4338 init_unistr(&printer->guid, "");
4339 printer->action = SPOOL_DS_UNPUBLISH;
4345 /********************************************************************
4346 Spoolss_enumprinters.
4347 ********************************************************************/
4349 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4353 int n_services=lp_numservices();
4354 PRINTER_INFO_1 *tp, *printers=NULL;
4355 PRINTER_INFO_1 current_prt;
4357 DEBUG(4,("enum_all_printers_info_1\n"));
4359 for (snum=0; snum<n_services; snum++) {
4360 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4361 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4363 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4364 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4365 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4366 SAFE_FREE(printers);
4371 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4373 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4379 /* check the required size. */
4380 for (i=0; i<*returned; i++)
4381 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4383 if (!alloc_buffer_size(buffer, *needed))
4384 return WERR_INSUFFICIENT_BUFFER;
4386 /* fill the buffer with the structures */
4387 for (i=0; i<*returned; i++)
4388 smb_io_printer_info_1("", buffer, &printers[i], 0);
4391 SAFE_FREE(printers);
4393 if (*needed > offered) {
4395 return WERR_INSUFFICIENT_BUFFER;
4401 /********************************************************************
4402 enum_all_printers_info_1_local.
4403 *********************************************************************/
4405 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4407 DEBUG(4,("enum_all_printers_info_1_local\n"));
4409 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4412 /********************************************************************
4413 enum_all_printers_info_1_name.
4414 *********************************************************************/
4416 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4420 DEBUG(4,("enum_all_printers_info_1_name\n"));
4422 if ((name[0] == '\\') && (name[1] == '\\'))
4425 if (is_myname_or_ipaddr(s)) {
4426 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4429 return WERR_INVALID_NAME;
4432 /********************************************************************
4433 enum_all_printers_info_1_remote.
4434 *********************************************************************/
4436 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4438 PRINTER_INFO_1 *printer;
4439 fstring printername;
4442 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4444 /* JFM: currently it's more a place holder than anything else.
4445 * In the spooler world there is a notion of server registration.
4446 * the print servers are registring (sp ?) on the PDC (in the same domain)
4448 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4451 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4456 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4457 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4458 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4460 init_unistr(&printer->description, desc);
4461 init_unistr(&printer->name, printername);
4462 init_unistr(&printer->comment, comment);
4463 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4465 /* check the required size. */
4466 *needed += spoolss_size_printer_info_1(printer);
4468 if (!alloc_buffer_size(buffer, *needed)) {
4470 return WERR_INSUFFICIENT_BUFFER;
4473 /* fill the buffer with the structures */
4474 smb_io_printer_info_1("", buffer, printer, 0);
4479 if (*needed > offered) {
4481 return WERR_INSUFFICIENT_BUFFER;
4487 /********************************************************************
4488 enum_all_printers_info_1_network.
4489 *********************************************************************/
4491 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4495 DEBUG(4,("enum_all_printers_info_1_network\n"));
4497 /* If we respond to a enum_printers level 1 on our name with flags
4498 set to PRINTER_ENUM_REMOTE with a list of printers then these
4499 printers incorrectly appear in the APW browse list.
4500 Specifically the printers for the server appear at the workgroup
4501 level where all the other servers in the domain are
4502 listed. Windows responds to this call with a
4503 WERR_CAN_NOT_COMPLETE so we should do the same. */
4505 if (name[0] == '\\' && name[1] == '\\')
4508 if (is_myname_or_ipaddr(s))
4509 return WERR_CAN_NOT_COMPLETE;
4511 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4514 /********************************************************************
4515 * api_spoolss_enumprinters
4517 * called from api_spoolss_enumprinters (see this to understand)
4518 ********************************************************************/
4520 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4524 int n_services=lp_numservices();
4525 PRINTER_INFO_2 *tp, *printers=NULL;
4526 PRINTER_INFO_2 current_prt;
4528 for (snum=0; snum<n_services; snum++) {
4529 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4530 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4532 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4533 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4534 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4535 SAFE_FREE(printers);
4540 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4541 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4547 /* check the required size. */
4548 for (i=0; i<*returned; i++)
4549 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4551 if (!alloc_buffer_size(buffer, *needed)) {
4552 for (i=0; i<*returned; i++) {
4553 free_devmode(printers[i].devmode);
4555 SAFE_FREE(printers);
4556 return WERR_INSUFFICIENT_BUFFER;
4559 /* fill the buffer with the structures */
4560 for (i=0; i<*returned; i++)
4561 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4564 for (i=0; i<*returned; i++) {
4565 free_devmode(printers[i].devmode);
4567 SAFE_FREE(printers);
4569 if (*needed > offered) {
4571 return WERR_INSUFFICIENT_BUFFER;
4577 /********************************************************************
4578 * handle enumeration of printers at level 1
4579 ********************************************************************/
4581 static WERROR enumprinters_level1( uint32 flags, fstring name,
4582 NEW_BUFFER *buffer, uint32 offered,
4583 uint32 *needed, uint32 *returned)
4585 /* Not all the flags are equals */
4587 if (flags & PRINTER_ENUM_LOCAL)
4588 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4590 if (flags & PRINTER_ENUM_NAME)
4591 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4593 if (flags & PRINTER_ENUM_REMOTE)
4594 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4596 if (flags & PRINTER_ENUM_NETWORK)
4597 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4599 return WERR_OK; /* NT4sp5 does that */
4602 /********************************************************************
4603 * handle enumeration of printers at level 2
4604 ********************************************************************/
4606 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4607 NEW_BUFFER *buffer, uint32 offered,
4608 uint32 *needed, uint32 *returned)
4610 char *s = servername;
4612 if (flags & PRINTER_ENUM_LOCAL) {
4613 return enum_all_printers_info_2(buffer, offered, needed, returned);
4616 if (flags & PRINTER_ENUM_NAME) {
4617 if ((servername[0] == '\\') && (servername[1] == '\\'))
4619 if (is_myname_or_ipaddr(s))
4620 return enum_all_printers_info_2(buffer, offered, needed, returned);
4622 return WERR_INVALID_NAME;
4625 if (flags & PRINTER_ENUM_REMOTE)
4626 return WERR_UNKNOWN_LEVEL;
4631 /********************************************************************
4632 * handle enumeration of printers at level 5
4633 ********************************************************************/
4635 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4636 NEW_BUFFER *buffer, uint32 offered,
4637 uint32 *needed, uint32 *returned)
4639 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4643 /********************************************************************
4644 * api_spoolss_enumprinters
4646 * called from api_spoolss_enumprinters (see this to understand)
4647 ********************************************************************/
4649 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4651 uint32 flags = q_u->flags;
4652 UNISTR2 *servername = &q_u->servername;
4653 uint32 level = q_u->level;
4654 NEW_BUFFER *buffer = NULL;
4655 uint32 offered = q_u->offered;
4656 uint32 *needed = &r_u->needed;
4657 uint32 *returned = &r_u->returned;
4661 /* that's an [in out] buffer */
4662 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4663 buffer = r_u->buffer;
4665 DEBUG(4,("_spoolss_enumprinters\n"));
4672 * flags==PRINTER_ENUM_NAME
4673 * if name=="" then enumerates all printers
4674 * if name!="" then enumerate the printer
4675 * flags==PRINTER_ENUM_REMOTE
4676 * name is NULL, enumerate printers
4677 * Level 2: name!="" enumerates printers, name can't be NULL
4678 * Level 3: doesn't exist
4679 * Level 4: does a local registry lookup
4680 * Level 5: same as Level 2
4683 unistr2_to_ascii(name, servername, sizeof(name)-1);
4688 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4690 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4692 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4697 return WERR_UNKNOWN_LEVEL;
4700 /****************************************************************************
4701 ****************************************************************************/
4703 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4705 PRINTER_INFO_0 *printer=NULL;
4707 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4710 construct_printer_info_0(print_hnd, printer, snum);
4712 /* check the required size. */
4713 *needed += spoolss_size_printer_info_0(printer);
4715 if (!alloc_buffer_size(buffer, *needed)) {
4717 return WERR_INSUFFICIENT_BUFFER;
4720 /* fill the buffer with the structures */
4721 smb_io_printer_info_0("", buffer, printer, 0);
4726 if (*needed > offered) {
4727 return WERR_INSUFFICIENT_BUFFER;
4733 /****************************************************************************
4734 ****************************************************************************/
4736 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4738 PRINTER_INFO_1 *printer=NULL;
4740 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4743 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4745 /* check the required size. */
4746 *needed += spoolss_size_printer_info_1(printer);
4748 if (!alloc_buffer_size(buffer, *needed)) {
4750 return WERR_INSUFFICIENT_BUFFER;
4753 /* fill the buffer with the structures */
4754 smb_io_printer_info_1("", buffer, printer, 0);
4759 if (*needed > offered) {
4760 return WERR_INSUFFICIENT_BUFFER;
4766 /****************************************************************************
4767 ****************************************************************************/
4769 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4771 PRINTER_INFO_2 *printer=NULL;
4773 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4776 construct_printer_info_2(print_hnd, printer, snum);
4778 /* check the required size. */
4779 *needed += spoolss_size_printer_info_2(printer);
4781 if (!alloc_buffer_size(buffer, *needed)) {
4782 free_printer_info_2(printer);
4783 return WERR_INSUFFICIENT_BUFFER;
4786 /* fill the buffer with the structures */
4787 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4788 free_printer_info_2(printer);
4793 free_printer_info_2(printer);
4795 if (*needed > offered) {
4796 return WERR_INSUFFICIENT_BUFFER;
4802 /****************************************************************************
4803 ****************************************************************************/
4805 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4807 PRINTER_INFO_3 *printer=NULL;
4809 if (!construct_printer_info_3(print_hnd, &printer, snum))
4812 /* check the required size. */
4813 *needed += spoolss_size_printer_info_3(printer);
4815 if (!alloc_buffer_size(buffer, *needed)) {
4816 free_printer_info_3(printer);
4817 return WERR_INSUFFICIENT_BUFFER;
4820 /* fill the buffer with the structures */
4821 smb_io_printer_info_3("", buffer, printer, 0);
4824 free_printer_info_3(printer);
4826 if (*needed > offered) {
4827 return WERR_INSUFFICIENT_BUFFER;
4833 /****************************************************************************
4834 ****************************************************************************/
4836 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4838 PRINTER_INFO_4 *printer=NULL;
4840 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4843 if (!construct_printer_info_4(print_hnd, printer, snum))
4846 /* check the required size. */
4847 *needed += spoolss_size_printer_info_4(printer);
4849 if (!alloc_buffer_size(buffer, *needed)) {
4850 free_printer_info_4(printer);
4851 return WERR_INSUFFICIENT_BUFFER;
4854 /* fill the buffer with the structures */
4855 smb_io_printer_info_4("", buffer, printer, 0);
4858 free_printer_info_4(printer);
4860 if (*needed > offered) {
4861 return WERR_INSUFFICIENT_BUFFER;
4867 /****************************************************************************
4868 ****************************************************************************/
4870 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4872 PRINTER_INFO_5 *printer=NULL;
4874 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4877 if (!construct_printer_info_5(print_hnd, printer, snum))
4880 /* check the required size. */
4881 *needed += spoolss_size_printer_info_5(printer);
4883 if (!alloc_buffer_size(buffer, *needed)) {
4884 free_printer_info_5(printer);
4885 return WERR_INSUFFICIENT_BUFFER;
4888 /* fill the buffer with the structures */
4889 smb_io_printer_info_5("", buffer, printer, 0);
4892 free_printer_info_5(printer);
4894 if (*needed > offered) {
4895 return WERR_INSUFFICIENT_BUFFER;
4901 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4903 PRINTER_INFO_7 *printer=NULL;
4905 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4908 if (!construct_printer_info_7(print_hnd, printer, snum))
4911 /* check the required size. */
4912 *needed += spoolss_size_printer_info_7(printer);
4914 if (!alloc_buffer_size(buffer, *needed)) {
4915 free_printer_info_7(printer);
4916 return WERR_INSUFFICIENT_BUFFER;
4919 /* fill the buffer with the structures */
4920 smb_io_printer_info_7("", buffer, printer, 0);
4923 free_printer_info_7(printer);
4925 if (*needed > offered) {
4926 return WERR_INSUFFICIENT_BUFFER;
4932 /****************************************************************************
4933 ****************************************************************************/
4935 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4937 POLICY_HND *handle = &q_u->handle;
4938 uint32 level = q_u->level;
4939 NEW_BUFFER *buffer = NULL;
4940 uint32 offered = q_u->offered;
4941 uint32 *needed = &r_u->needed;
4942 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4946 /* that's an [in out] buffer */
4947 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4948 buffer = r_u->buffer;
4952 if (!get_printer_snum(p, handle, &snum))
4957 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4959 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4961 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4963 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4965 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4967 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4969 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4971 return WERR_UNKNOWN_LEVEL;
4974 /********************************************************************
4975 * fill a DRIVER_INFO_1 struct
4976 ********************************************************************/
4978 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4980 init_unistr( &info->name, driver.info_3->name);
4983 /********************************************************************
4984 * construct_printer_driver_info_1
4985 ********************************************************************/
4987 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4989 NT_PRINTER_INFO_LEVEL *printer = NULL;
4990 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4992 ZERO_STRUCT(driver);
4994 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4995 return WERR_INVALID_PRINTER_NAME;
4997 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4998 return WERR_UNKNOWN_PRINTER_DRIVER;
5000 fill_printer_driver_info_1(info, driver, servername, architecture);
5002 free_a_printer(&printer,2);
5007 /********************************************************************
5008 * construct_printer_driver_info_2
5009 * fill a printer_info_2 struct
5010 ********************************************************************/
5012 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5016 info->version=driver.info_3->cversion;
5018 init_unistr( &info->name, driver.info_3->name );
5019 init_unistr( &info->architecture, driver.info_3->environment );
5022 if (strlen(driver.info_3->driverpath)) {
5023 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5024 init_unistr( &info->driverpath, temp );
5026 init_unistr( &info->driverpath, "" );
5028 if (strlen(driver.info_3->datafile)) {
5029 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5030 init_unistr( &info->datafile, temp );
5032 init_unistr( &info->datafile, "" );
5034 if (strlen(driver.info_3->configfile)) {
5035 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5036 init_unistr( &info->configfile, temp );
5038 init_unistr( &info->configfile, "" );
5041 /********************************************************************
5042 * construct_printer_driver_info_2
5043 * fill a printer_info_2 struct
5044 ********************************************************************/
5046 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5048 NT_PRINTER_INFO_LEVEL *printer = NULL;
5049 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5051 ZERO_STRUCT(printer);
5052 ZERO_STRUCT(driver);
5054 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5055 return WERR_INVALID_PRINTER_NAME;
5057 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5058 return WERR_UNKNOWN_PRINTER_DRIVER;
5060 fill_printer_driver_info_2(info, driver, servername);
5062 free_a_printer(&printer,2);
5067 /********************************************************************
5068 * copy a strings array and convert to UNICODE
5070 * convert an array of ascii string to a UNICODE string
5071 ********************************************************************/
5073 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5081 DEBUG(6,("init_unistr_array\n"));
5092 v = ""; /* hack to handle null lists */
5095 /* hack to allow this to be used in places other than when generating
5096 the list of dependent files */
5099 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5103 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
5105 /* add one extra unit16 for the second terminating NULL */
5107 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5108 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5116 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5121 /* special case for ""; we need to add both NULL's here */
5123 (*uni_array)[j++]=0x0000;
5124 (*uni_array)[j]=0x0000;
5127 DEBUGADD(6,("last one:done\n"));
5129 /* return size of array in uint16's */
5134 /********************************************************************
5135 * construct_printer_info_3
5136 * fill a printer_info_3 struct
5137 ********************************************************************/
5139 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5145 info->version=driver.info_3->cversion;
5147 init_unistr( &info->name, driver.info_3->name );
5148 init_unistr( &info->architecture, driver.info_3->environment );
5150 if (strlen(driver.info_3->driverpath)) {
5151 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5152 init_unistr( &info->driverpath, temp );
5154 init_unistr( &info->driverpath, "" );
5156 if (strlen(driver.info_3->datafile)) {
5157 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5158 init_unistr( &info->datafile, temp );
5160 init_unistr( &info->datafile, "" );
5162 if (strlen(driver.info_3->configfile)) {
5163 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5164 init_unistr( &info->configfile, temp );
5166 init_unistr( &info->configfile, "" );
5168 if (strlen(driver.info_3->helpfile)) {
5169 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5170 init_unistr( &info->helpfile, temp );
5172 init_unistr( &info->helpfile, "" );
5174 init_unistr( &info->monitorname, driver.info_3->monitorname );
5175 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5177 info->dependentfiles=NULL;
5178 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5181 /********************************************************************
5182 * construct_printer_info_3
5183 * fill a printer_info_3 struct
5184 ********************************************************************/
5186 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5188 NT_PRINTER_INFO_LEVEL *printer = NULL;
5189 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5191 ZERO_STRUCT(driver);
5193 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5194 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5195 if (!W_ERROR_IS_OK(status))
5196 return WERR_INVALID_PRINTER_NAME;
5198 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5199 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5204 * I put this code in during testing. Helpful when commenting out the
5205 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5206 * as win2k always queries the driver using an infor level of 6.
5207 * I've left it in (but ifdef'd out) because I'll probably
5208 * use it in experimentation again in the future. --jerry 22/01/2002
5211 if (!W_ERROR_IS_OK(status)) {
5213 * Is this a W2k client ?
5216 /* Yes - try again with a WinNT driver. */
5218 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5219 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5223 if (!W_ERROR_IS_OK(status)) {
5224 free_a_printer(&printer,2);
5225 return WERR_UNKNOWN_PRINTER_DRIVER;
5233 fill_printer_driver_info_3(info, driver, servername);
5235 free_a_printer(&printer,2);
5240 /********************************************************************
5241 * construct_printer_info_6
5242 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5243 ********************************************************************/
5245 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5251 memset(&nullstr, '\0', sizeof(fstring));
5253 info->version=driver.info_3->cversion;
5255 init_unistr( &info->name, driver.info_3->name );
5256 init_unistr( &info->architecture, driver.info_3->environment );
5258 if (strlen(driver.info_3->driverpath)) {
5259 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5260 init_unistr( &info->driverpath, temp );
5262 init_unistr( &info->driverpath, "" );
5264 if (strlen(driver.info_3->datafile)) {
5265 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5266 init_unistr( &info->datafile, temp );
5268 init_unistr( &info->datafile, "" );
5270 if (strlen(driver.info_3->configfile)) {
5271 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5272 init_unistr( &info->configfile, temp );
5274 init_unistr( &info->configfile, "" );
5276 if (strlen(driver.info_3->helpfile)) {
5277 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5278 init_unistr( &info->helpfile, temp );
5280 init_unistr( &info->helpfile, "" );
5282 init_unistr( &info->monitorname, driver.info_3->monitorname );
5283 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5285 info->dependentfiles = NULL;
5286 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5288 info->previousdrivernames=NULL;
5289 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5291 info->driver_date.low=0;
5292 info->driver_date.high=0;
5295 info->driver_version_low=0;
5296 info->driver_version_high=0;
5298 init_unistr( &info->mfgname, "");
5299 init_unistr( &info->oem_url, "");
5300 init_unistr( &info->hardware_id, "");
5301 init_unistr( &info->provider, "");
5304 /********************************************************************
5305 * construct_printer_info_6
5306 * fill a printer_info_6 struct
5307 ********************************************************************/
5309 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5310 fstring servername, fstring architecture, uint32 version)
5312 NT_PRINTER_INFO_LEVEL *printer = NULL;
5313 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5316 ZERO_STRUCT(driver);
5318 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5320 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5322 if (!W_ERROR_IS_OK(status))
5323 return WERR_INVALID_PRINTER_NAME;
5325 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5327 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5329 if (!W_ERROR_IS_OK(status))
5332 * Is this a W2k client ?
5336 free_a_printer(&printer,2);
5337 return WERR_UNKNOWN_PRINTER_DRIVER;
5340 /* Yes - try again with a WinNT driver. */
5342 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5343 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5344 if (!W_ERROR_IS_OK(status)) {
5345 free_a_printer(&printer,2);
5346 return WERR_UNKNOWN_PRINTER_DRIVER;
5350 fill_printer_driver_info_6(info, driver, servername);
5352 free_a_printer(&printer,2);
5353 free_a_printer_driver(driver, 3);
5358 /****************************************************************************
5359 ****************************************************************************/
5361 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5363 SAFE_FREE(info->dependentfiles);
5366 /****************************************************************************
5367 ****************************************************************************/
5369 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5371 SAFE_FREE(info->dependentfiles);
5375 /****************************************************************************
5376 ****************************************************************************/
5378 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5380 DRIVER_INFO_1 *info=NULL;
5383 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5386 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5387 if (!W_ERROR_IS_OK(status)) {
5392 /* check the required size. */
5393 *needed += spoolss_size_printer_driver_info_1(info);
5395 if (!alloc_buffer_size(buffer, *needed)) {
5397 return WERR_INSUFFICIENT_BUFFER;
5400 /* fill the buffer with the structures */
5401 smb_io_printer_driver_info_1("", buffer, info, 0);
5406 if (*needed > offered)
5407 return WERR_INSUFFICIENT_BUFFER;
5412 /****************************************************************************
5413 ****************************************************************************/
5415 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5417 DRIVER_INFO_2 *info=NULL;
5420 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5423 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5424 if (!W_ERROR_IS_OK(status)) {
5429 /* check the required size. */
5430 *needed += spoolss_size_printer_driver_info_2(info);
5432 if (!alloc_buffer_size(buffer, *needed)) {
5434 return WERR_INSUFFICIENT_BUFFER;
5437 /* fill the buffer with the structures */
5438 smb_io_printer_driver_info_2("", buffer, info, 0);
5443 if (*needed > offered)
5444 return WERR_INSUFFICIENT_BUFFER;
5449 /****************************************************************************
5450 ****************************************************************************/
5452 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5459 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5460 if (!W_ERROR_IS_OK(status)) {
5464 /* check the required size. */
5465 *needed += spoolss_size_printer_driver_info_3(&info);
5467 if (!alloc_buffer_size(buffer, *needed)) {
5468 free_printer_driver_info_3(&info);
5469 return WERR_INSUFFICIENT_BUFFER;
5472 /* fill the buffer with the structures */
5473 smb_io_printer_driver_info_3("", buffer, &info, 0);
5475 free_printer_driver_info_3(&info);
5477 if (*needed > offered)
5478 return WERR_INSUFFICIENT_BUFFER;
5483 /****************************************************************************
5484 ****************************************************************************/
5486 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5493 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5494 if (!W_ERROR_IS_OK(status)) {
5498 /* check the required size. */
5499 *needed += spoolss_size_printer_driver_info_6(&info);
5501 if (!alloc_buffer_size(buffer, *needed)) {
5502 free_printer_driver_info_6(&info);
5503 return WERR_INSUFFICIENT_BUFFER;
5506 /* fill the buffer with the structures */
5507 smb_io_printer_driver_info_6("", buffer, &info, 0);
5509 free_printer_driver_info_6(&info);
5511 if (*needed > offered)
5512 return WERR_INSUFFICIENT_BUFFER;
5517 /****************************************************************************
5518 ****************************************************************************/
5520 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5522 POLICY_HND *handle = &q_u->handle;
5523 UNISTR2 *uni_arch = &q_u->architecture;
5524 uint32 level = q_u->level;
5525 uint32 clientmajorversion = q_u->clientmajorversion;
5526 NEW_BUFFER *buffer = NULL;
5527 uint32 offered = q_u->offered;
5528 uint32 *needed = &r_u->needed;
5529 uint32 *servermajorversion = &r_u->servermajorversion;
5530 uint32 *serverminorversion = &r_u->serverminorversion;
5533 fstring architecture;
5536 /* that's an [in out] buffer */
5537 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5538 buffer = r_u->buffer;
5540 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5543 *servermajorversion = 0;
5544 *serverminorversion = 0;
5546 fstrcpy(servername, get_called_name());
5547 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5549 if (!get_printer_snum(p, handle, &snum))
5554 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5556 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5558 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5560 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5563 return WERR_UNKNOWN_LEVEL;
5566 /****************************************************************************
5567 ****************************************************************************/
5569 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5571 POLICY_HND *handle = &q_u->handle;
5573 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5576 DEBUG(3,("Error in startpageprinter printer handle\n"));
5580 Printer->page_started=True;
5584 /****************************************************************************
5585 ****************************************************************************/
5587 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5589 POLICY_HND *handle = &q_u->handle;
5592 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5595 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5599 if (!get_printer_snum(p, handle, &snum))
5602 Printer->page_started=False;
5603 print_job_endpage(snum, Printer->jobid);
5608 /********************************************************************
5609 * api_spoolss_getprinter
5610 * called from the spoolss dispatcher
5612 ********************************************************************/
5614 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5616 POLICY_HND *handle = &q_u->handle;
5617 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5618 uint32 *jobid = &r_u->jobid;
5620 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5624 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5625 struct current_user user;
5628 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5632 get_current_user(&user, p);
5635 * a nice thing with NT is it doesn't listen to what you tell it.
5636 * when asked to send _only_ RAW datas, it tries to send datas
5639 * So I add checks like in NT Server ...
5642 if (info_1->p_datatype != 0) {
5643 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5644 if (strcmp(datatype, "RAW") != 0) {
5646 return WERR_INVALID_DATATYPE;
5650 /* get the share number of the printer */
5651 if (!get_printer_snum(p, handle, &snum)) {
5655 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5657 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5659 /* An error occured in print_job_start() so return an appropriate
5662 if (Printer->jobid == -1) {
5663 return map_werror_from_unix(errno);
5666 Printer->document_started=True;
5667 (*jobid) = Printer->jobid;
5672 /********************************************************************
5673 * api_spoolss_getprinter
5674 * called from the spoolss dispatcher
5676 ********************************************************************/
5678 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5680 POLICY_HND *handle = &q_u->handle;
5682 return _spoolss_enddocprinter_internal(p, handle);
5685 /****************************************************************************
5686 ****************************************************************************/
5688 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5690 POLICY_HND *handle = &q_u->handle;
5691 uint32 buffer_size = q_u->buffer_size;
5692 uint8 *buffer = q_u->buffer;
5693 uint32 *buffer_written = &q_u->buffer_size2;
5695 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5698 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5699 r_u->buffer_written = q_u->buffer_size2;
5703 if (!get_printer_snum(p, handle, &snum))
5706 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5707 if (*buffer_written == -1) {
5708 r_u->buffer_written = 0;
5709 if (errno == ENOSPC)
5710 return WERR_NO_SPOOL_SPACE;
5712 return WERR_ACCESS_DENIED;
5715 r_u->buffer_written = q_u->buffer_size2;
5720 /********************************************************************
5721 * api_spoolss_getprinter
5722 * called from the spoolss dispatcher
5724 ********************************************************************/
5726 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5729 struct current_user user;
5731 WERROR errcode = WERR_BADFUNC;
5732 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5734 get_current_user(&user, p);
5737 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5741 if (!get_printer_snum(p, handle, &snum))
5745 case PRINTER_CONTROL_PAUSE:
5746 if (print_queue_pause(&user, snum, &errcode)) {
5750 case PRINTER_CONTROL_RESUME:
5751 case PRINTER_CONTROL_UNPAUSE:
5752 if (print_queue_resume(&user, snum, &errcode)) {
5756 case PRINTER_CONTROL_PURGE:
5757 if (print_queue_purge(&user, snum, &errcode)) {
5762 return WERR_UNKNOWN_LEVEL;
5768 /********************************************************************
5769 * api_spoolss_abortprinter
5770 * From MSDN: "Deletes printer's spool file if printer is configured
5772 ********************************************************************/
5774 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5776 POLICY_HND *handle = &q_u->handle;
5777 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5779 struct current_user user;
5780 WERROR errcode = WERR_OK;
5783 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5787 if (!get_printer_snum(p, handle, &snum))
5790 get_current_user( &user, p );
5792 print_job_delete( &user, snum, Printer->jobid, &errcode );
5797 /********************************************************************
5798 * called by spoolss_api_setprinter
5799 * when updating a printer description
5800 ********************************************************************/
5802 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5803 const SPOOL_PRINTER_INFO_LEVEL *info,
5804 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5806 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5807 struct current_user user;
5811 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5813 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5814 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5815 OUR_HANDLE(handle)));
5817 result = WERR_BADFID;
5821 /* NT seems to like setting the security descriptor even though
5822 nothing may have actually changed. This causes annoying
5823 dialog boxes when the user doesn't have permission to change
5824 the security descriptor. */
5826 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5828 if (DEBUGLEVEL >= 10) {
5832 the_acl = old_secdesc_ctr->sec->dacl;
5833 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5834 PRINTERNAME(snum), the_acl->num_aces));
5836 for (i = 0; i < the_acl->num_aces; i++) {
5839 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5841 DEBUG(10, ("%s 0x%08x\n", sid_str,
5842 the_acl->ace[i].info.mask));
5845 the_acl = secdesc_ctr->sec->dacl;
5848 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5849 PRINTERNAME(snum), the_acl->num_aces));
5851 for (i = 0; i < the_acl->num_aces; i++) {
5854 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5856 DEBUG(10, ("%s 0x%08x\n", sid_str,
5857 the_acl->ace[i].info.mask));
5860 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5864 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5866 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5871 /* Work out which user is performing the operation */
5873 get_current_user(&user, p);
5875 /* Check the user has permissions to change the security
5876 descriptor. By experimentation with two NT machines, the user
5877 requires Full Access to the printer to change security
5880 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5881 result = WERR_ACCESS_DENIED;
5885 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5892 /********************************************************************
5893 Do Samba sanity checks on a printer info struct.
5894 this has changed purpose: it now "canonicalises" printer
5895 info from a client rather than just checking it is correct
5896 ********************************************************************/
5898 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5900 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5901 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5903 /* we force some elements to "correct" values */
5904 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5905 fstrcpy(info->sharename, lp_servicename(snum));
5906 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5907 get_called_name(), info->sharename);
5908 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5914 /****************************************************************************
5915 ****************************************************************************/
5917 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5919 extern userdom_struct current_user_info;
5920 char *cmd = lp_addprinter_cmd();
5926 fstring remote_machine = "%m";
5928 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5930 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5931 cmd, printer->info_2->printername, printer->info_2->sharename,
5932 printer->info_2->portname, printer->info_2->drivername,
5933 printer->info_2->location, printer->info_2->comment, remote_machine);
5935 DEBUG(10,("Running [%s]\n", command));
5936 ret = smbrun(command, &fd);
5937 DEBUGADD(10,("returned [%d]\n", ret));
5946 /* Get lines and convert them back to dos-codepage */
5947 qlines = fd_lines_load(fd, &numlines);
5948 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5952 /* Set the portname to what the script says the portname should be. */
5953 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5954 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5956 /* Send SIGHUP to process group... is there a better way? */
5959 /* reload our services immediately */
5960 reload_services( False );
5963 file_lines_free(qlines);
5967 /********************************************************************
5968 * Called by spoolss_api_setprinter
5969 * when updating a printer description.
5970 ********************************************************************/
5972 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5973 const SPOOL_PRINTER_INFO_LEVEL *info,
5974 DEVICEMODE *devmode)
5977 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5978 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5983 DEBUG(8,("update_printer\n"));
5988 result = WERR_BADFID;
5992 if (!get_printer_snum(p, handle, &snum)) {
5993 result = WERR_BADFID;
5997 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5998 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5999 result = WERR_BADFID;
6003 DEBUGADD(8,("Converting info_2 struct\n"));
6006 * convert_printer_info converts the incoming
6007 * info from the client and overwrites the info
6008 * just read from the tdb in the pointer 'printer'.
6011 if (!convert_printer_info(info, printer, level)) {
6012 result = WERR_NOMEM;
6017 /* we have a valid devmode
6018 convert it and link it*/
6020 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6021 if (!convert_devicemode(printer->info_2->printername, devmode,
6022 &printer->info_2->devmode)) {
6023 result = WERR_NOMEM;
6028 /* Do sanity check on the requested changes for Samba */
6030 if (!check_printer_ok(printer->info_2, snum)) {
6031 result = WERR_INVALID_PARAM;
6035 /* FIXME!!! If the driver has changed we really should verify that
6036 it is installed before doing much else --jerry */
6038 /* Check calling user has permission to update printer description */
6040 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6041 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6042 result = WERR_ACCESS_DENIED;
6046 /* Call addprinter hook */
6047 /* Check changes to see if this is really needed */
6049 if ( *lp_addprinter_cmd()
6050 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6051 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6052 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6053 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6055 if ( !add_printer_hook(printer) ) {
6056 result = WERR_ACCESS_DENIED;
6061 * make sure we actually reload the services after
6062 * this as smb.conf could have a new section in it
6063 * .... shouldn't .... but could
6065 reload_services(False);
6069 * When a *new* driver is bound to a printer, the drivername is used to
6070 * lookup previously saved driver initialization info, which is then
6071 * bound to the printer, simulating what happens in the Windows arch.
6073 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6075 if (!set_driver_init(printer, 2))
6077 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6078 printer->info_2->drivername));
6081 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6082 printer->info_2->drivername));
6084 notify_printer_driver(snum, printer->info_2->drivername);
6088 * flag which changes actually occured. This is a small subset of
6089 * all the possible changes. We also have to update things in the
6093 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6094 init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 );
6095 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6096 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6098 notify_printer_comment(snum, printer->info_2->comment);
6101 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6102 init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 );
6103 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6104 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6105 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6106 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6108 notify_printer_sharename(snum, printer->info_2->sharename);
6111 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6112 init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 );
6113 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6114 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6116 notify_printer_port(snum, printer->info_2->portname);
6119 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6120 init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 );
6121 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6122 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6124 notify_printer_location(snum, printer->info_2->location);
6127 /* here we need to update some more DsSpooler keys */
6128 /* uNCName, serverName, shortServerName */
6130 init_unistr2( &buffer, global_myname(), strlen(global_myname())+1 );
6131 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6132 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6133 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6134 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6136 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6137 global_myname(), printer->info_2->sharename );
6138 init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 );
6139 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6140 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6142 /* Update printer info */
6143 result = mod_a_printer(*printer, 2);
6146 free_a_printer(&printer, 2);
6147 free_a_printer(&old_printer, 2);
6153 /****************************************************************************
6154 ****************************************************************************/
6155 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6156 const SPOOL_PRINTER_INFO_LEVEL *info)
6159 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6161 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6164 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6171 if (!get_printer_snum(p, handle, &snum))
6174 nt_printer_publish(Printer, snum, info7->action);
6178 return WERR_UNKNOWN_LEVEL;
6181 /****************************************************************************
6182 ****************************************************************************/
6184 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6186 POLICY_HND *handle = &q_u->handle;
6187 uint32 level = q_u->level;
6188 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6189 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6190 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6191 uint32 command = q_u->command;
6193 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6196 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6200 /* check the level */
6203 return control_printer(handle, command, p);
6205 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6207 return update_printer_sec(handle, level, info, p,
6210 return publish_or_unpublish_printer(p, handle, info);
6212 return WERR_UNKNOWN_LEVEL;
6216 /****************************************************************************
6217 ****************************************************************************/
6219 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6221 POLICY_HND *handle = &q_u->handle;
6222 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6225 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6229 if (Printer->notify.client_connected==True) {
6232 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6234 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6235 !get_printer_snum(p, handle, &snum) )
6238 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6241 Printer->notify.flags=0;
6242 Printer->notify.options=0;
6243 Printer->notify.localmachine[0]='\0';
6244 Printer->notify.printerlocal=0;
6245 if (Printer->notify.option)
6246 free_spool_notify_option(&Printer->notify.option);
6247 Printer->notify.client_connected=False;
6252 /****************************************************************************
6253 ****************************************************************************/
6255 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6257 /* that's an [in out] buffer (despite appearences to the contrary) */
6258 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6261 return WERR_INVALID_PARAM; /* this is what a NT server
6262 returns for AddJob. AddJob
6263 must fail on non-local
6267 /****************************************************************************
6268 ****************************************************************************/
6270 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6271 int position, int snum)
6277 t=gmtime(&queue->time);
6278 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6280 job_info->jobid=queue->job;
6281 init_unistr(&job_info->printername, lp_servicename(snum));
6282 init_unistr(&job_info->machinename, temp_name);
6283 init_unistr(&job_info->username, queue->fs_user);
6284 init_unistr(&job_info->document, queue->fs_file);
6285 init_unistr(&job_info->datatype, "RAW");
6286 init_unistr(&job_info->text_status, "");
6287 job_info->status=nt_printj_status(queue->status);
6288 job_info->priority=queue->priority;
6289 job_info->position=position;
6290 job_info->totalpages=queue->page_count;
6291 job_info->pagesprinted=0;
6293 make_systemtime(&job_info->submitted, t);
6296 /****************************************************************************
6297 ****************************************************************************/
6299 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6300 int position, int snum,
6301 NT_PRINTER_INFO_LEVEL *ntprinter,
6302 DEVICEMODE *devmode)
6307 t=gmtime(&queue->time);
6308 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6310 job_info->jobid=queue->job;
6312 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6314 init_unistr(&job_info->machinename, temp_name);
6315 init_unistr(&job_info->username, queue->fs_user);
6316 init_unistr(&job_info->document, queue->fs_file);
6317 init_unistr(&job_info->notifyname, queue->fs_user);
6318 init_unistr(&job_info->datatype, "RAW");
6319 init_unistr(&job_info->printprocessor, "winprint");
6320 init_unistr(&job_info->parameters, "");
6321 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6322 init_unistr(&job_info->text_status, "");
6324 /* and here the security descriptor */
6326 job_info->status=nt_printj_status(queue->status);
6327 job_info->priority=queue->priority;
6328 job_info->position=position;
6329 job_info->starttime=0;
6330 job_info->untiltime=0;
6331 job_info->totalpages=queue->page_count;
6332 job_info->size=queue->size;
6333 make_systemtime(&(job_info->submitted), t);
6334 job_info->timeelapsed=0;
6335 job_info->pagesprinted=0;
6337 job_info->devmode = devmode;
6342 /****************************************************************************
6343 Enumjobs at level 1.
6344 ****************************************************************************/
6346 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6347 NEW_BUFFER *buffer, uint32 offered,
6348 uint32 *needed, uint32 *returned)
6353 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6360 for (i=0; i<*returned; i++)
6361 fill_job_info_1(&info[i], &queue[i], i, snum);
6365 /* check the required size. */
6366 for (i=0; i<*returned; i++)
6367 (*needed) += spoolss_size_job_info_1(&info[i]);
6369 if (!alloc_buffer_size(buffer, *needed)) {
6371 return WERR_INSUFFICIENT_BUFFER;
6374 /* fill the buffer with the structures */
6375 for (i=0; i<*returned; i++)
6376 smb_io_job_info_1("", buffer, &info[i], 0);
6381 if (*needed > offered) {
6383 return WERR_INSUFFICIENT_BUFFER;
6389 /****************************************************************************
6390 Enumjobs at level 2.
6391 ****************************************************************************/
6393 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6394 NEW_BUFFER *buffer, uint32 offered,
6395 uint32 *needed, uint32 *returned)
6397 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6398 JOB_INFO_2 *info = NULL;
6401 DEVICEMODE *devmode = NULL;
6403 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6406 result = WERR_NOMEM;
6410 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6411 if (!W_ERROR_IS_OK(result)) {
6416 /* this should not be a failure condition if the devmode is NULL */
6418 devmode = construct_dev_mode(snum);
6420 for (i=0; i<*returned; i++)
6421 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6424 free_a_printer(&ntprinter, 2);
6427 /* check the required size. */
6428 for (i=0; i<*returned; i++)
6429 (*needed) += spoolss_size_job_info_2(&info[i]);
6431 if (*needed > offered) {
6433 result = WERR_INSUFFICIENT_BUFFER;
6437 if (!alloc_buffer_size(buffer, *needed)) {
6439 result = WERR_INSUFFICIENT_BUFFER;
6443 /* fill the buffer with the structures */
6444 for (i=0; i<*returned; i++)
6445 smb_io_job_info_2("", buffer, &info[i], 0);
6450 free_a_printer(&ntprinter, 2);
6451 free_devmode(devmode);
6459 /****************************************************************************
6461 ****************************************************************************/
6463 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6465 POLICY_HND *handle = &q_u->handle;
6466 uint32 level = q_u->level;
6467 NEW_BUFFER *buffer = NULL;
6468 uint32 offered = q_u->offered;
6469 uint32 *needed = &r_u->needed;
6470 uint32 *returned = &r_u->returned;
6474 print_status_struct prt_status;
6475 print_queue_struct *queue=NULL;
6477 /* that's an [in out] buffer */
6478 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6479 buffer = r_u->buffer;
6481 DEBUG(4,("_spoolss_enumjobs\n"));
6486 if (!get_printer_snum(p, handle, &snum))
6489 *returned = print_queue_status(snum, &queue, &prt_status);
6490 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6492 if (*returned == 0) {
6493 set_enumjobs_timestamp(snum);
6500 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6501 set_enumjobs_timestamp(snum);
6504 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6505 set_enumjobs_timestamp(snum);
6510 return WERR_UNKNOWN_LEVEL;
6514 /****************************************************************************
6515 ****************************************************************************/
6517 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6522 /****************************************************************************
6523 ****************************************************************************/
6525 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6527 POLICY_HND *handle = &q_u->handle;
6528 uint32 jobid = q_u->jobid;
6529 uint32 command = q_u->command;
6531 struct current_user user;
6533 WERROR errcode = WERR_BADFUNC;
6535 if (!get_printer_snum(p, handle, &snum)) {
6539 if (!print_job_exists(snum, jobid)) {
6540 return WERR_INVALID_PRINTER_NAME;
6543 get_current_user(&user, p);
6546 case JOB_CONTROL_CANCEL:
6547 case JOB_CONTROL_DELETE:
6548 if (print_job_delete(&user, snum, jobid, &errcode)) {
6552 case JOB_CONTROL_PAUSE:
6553 if (print_job_pause(&user, snum, jobid, &errcode)) {
6557 case JOB_CONTROL_RESTART:
6558 case JOB_CONTROL_RESUME:
6559 if (print_job_resume(&user, snum, jobid, &errcode)) {
6564 return WERR_UNKNOWN_LEVEL;
6570 /****************************************************************************
6571 Enumerates all printer drivers at level 1.
6572 ****************************************************************************/
6574 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6579 fstring *list = NULL;
6581 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6582 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6586 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6588 ndrivers=get_ntdrivers(&list, architecture, version);
6589 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6595 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6596 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6597 SAFE_FREE(driver_info_1);
6601 else driver_info_1 = tdi1;
6604 for (i=0; i<ndrivers; i++) {
6606 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6607 ZERO_STRUCT(driver);
6608 status = get_a_printer_driver(&driver, 3, list[i],
6609 architecture, version);
6610 if (!W_ERROR_IS_OK(status)) {
6614 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6615 free_a_printer_driver(driver, 3);
6618 *returned+=ndrivers;
6622 /* check the required size. */
6623 for (i=0; i<*returned; i++) {
6624 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6625 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6628 if (!alloc_buffer_size(buffer, *needed)) {
6629 SAFE_FREE(driver_info_1);
6630 return WERR_INSUFFICIENT_BUFFER;
6633 /* fill the buffer with the driver structures */
6634 for (i=0; i<*returned; i++) {
6635 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6636 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6639 SAFE_FREE(driver_info_1);
6641 if (*needed > offered) {
6643 return WERR_INSUFFICIENT_BUFFER;
6649 /****************************************************************************
6650 Enumerates all printer drivers at level 2.
6651 ****************************************************************************/
6653 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6658 fstring *list = NULL;
6660 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6661 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6665 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6667 ndrivers=get_ntdrivers(&list, architecture, version);
6668 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6674 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6675 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6676 SAFE_FREE(driver_info_2);
6680 else driver_info_2 = tdi2;
6683 for (i=0; i<ndrivers; i++) {
6686 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6687 ZERO_STRUCT(driver);
6688 status = get_a_printer_driver(&driver, 3, list[i],
6689 architecture, version);
6690 if (!W_ERROR_IS_OK(status)) {
6694 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6695 free_a_printer_driver(driver, 3);
6698 *returned+=ndrivers;
6702 /* check the required size. */
6703 for (i=0; i<*returned; i++) {
6704 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6705 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6708 if (!alloc_buffer_size(buffer, *needed)) {
6709 SAFE_FREE(driver_info_2);
6710 return WERR_INSUFFICIENT_BUFFER;
6713 /* fill the buffer with the form structures */
6714 for (i=0; i<*returned; i++) {
6715 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6716 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6719 SAFE_FREE(driver_info_2);
6721 if (*needed > offered) {
6723 return WERR_INSUFFICIENT_BUFFER;
6729 /****************************************************************************
6730 Enumerates all printer drivers at level 3.
6731 ****************************************************************************/
6733 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6738 fstring *list = NULL;
6740 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6741 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6745 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6747 ndrivers=get_ntdrivers(&list, architecture, version);
6748 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6754 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6755 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6756 SAFE_FREE(driver_info_3);
6760 else driver_info_3 = tdi3;
6763 for (i=0; i<ndrivers; i++) {
6766 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6767 ZERO_STRUCT(driver);
6768 status = get_a_printer_driver(&driver, 3, list[i],
6769 architecture, version);
6770 if (!W_ERROR_IS_OK(status)) {
6774 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6775 free_a_printer_driver(driver, 3);
6778 *returned+=ndrivers;
6782 /* check the required size. */
6783 for (i=0; i<*returned; i++) {
6784 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6785 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6788 if (!alloc_buffer_size(buffer, *needed)) {
6789 SAFE_FREE(driver_info_3);
6790 return WERR_INSUFFICIENT_BUFFER;
6793 /* fill the buffer with the driver structures */
6794 for (i=0; i<*returned; i++) {
6795 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6796 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6799 for (i=0; i<*returned; i++)
6800 SAFE_FREE(driver_info_3[i].dependentfiles);
6802 SAFE_FREE(driver_info_3);
6804 if (*needed > offered) {
6806 return WERR_INSUFFICIENT_BUFFER;
6812 /****************************************************************************
6813 Enumerates all printer drivers.
6814 ****************************************************************************/
6816 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6818 UNISTR2 *environment = &q_u->environment;
6819 uint32 level = q_u->level;
6820 NEW_BUFFER *buffer = NULL;
6821 uint32 offered = q_u->offered;
6822 uint32 *needed = &r_u->needed;
6823 uint32 *returned = &r_u->returned;
6825 fstring *list = NULL;
6827 fstring architecture;
6829 /* that's an [in out] buffer */
6830 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6831 buffer = r_u->buffer;
6833 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6834 fstrcpy(servername, get_called_name());
6838 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6842 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6844 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6846 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6850 return WERR_UNKNOWN_LEVEL;
6854 /****************************************************************************
6855 ****************************************************************************/
6857 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6859 form->flag=list->flag;
6860 init_unistr(&form->name, list->name);
6861 form->width=list->width;
6862 form->length=list->length;
6863 form->left=list->left;
6864 form->top=list->top;
6865 form->right=list->right;
6866 form->bottom=list->bottom;
6869 /****************************************************************************
6870 ****************************************************************************/
6872 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6874 uint32 level = q_u->level;
6875 NEW_BUFFER *buffer = NULL;
6876 uint32 offered = q_u->offered;
6877 uint32 *needed = &r_u->needed;
6878 uint32 *numofforms = &r_u->numofforms;
6879 uint32 numbuiltinforms;
6881 nt_forms_struct *list=NULL;
6882 nt_forms_struct *builtinlist=NULL;
6887 /* that's an [in out] buffer */
6888 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6889 buffer = r_u->buffer;
6891 DEBUG(4,("_spoolss_enumforms\n"));
6892 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6893 DEBUGADD(5,("Info level [%d]\n", level));
6895 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6896 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6897 *numofforms = get_ntforms(&list);
6898 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6899 *numofforms += numbuiltinforms;
6901 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6905 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6910 /* construct the list of form structures */
6911 for (i=0; i<numbuiltinforms; i++) {
6912 DEBUGADD(6,("Filling form number [%d]\n",i));
6913 fill_form_1(&forms_1[i], &builtinlist[i]);
6916 SAFE_FREE(builtinlist);
6918 for (; i<*numofforms; i++) {
6919 DEBUGADD(6,("Filling form number [%d]\n",i));
6920 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6925 /* check the required size. */
6926 for (i=0; i<numbuiltinforms; i++) {
6927 DEBUGADD(6,("adding form [%d]'s size\n",i));
6928 buffer_size += spoolss_size_form_1(&forms_1[i]);
6930 for (; i<*numofforms; i++) {
6931 DEBUGADD(6,("adding form [%d]'s size\n",i));
6932 buffer_size += spoolss_size_form_1(&forms_1[i]);
6935 *needed=buffer_size;
6937 if (!alloc_buffer_size(buffer, buffer_size)){
6939 return WERR_INSUFFICIENT_BUFFER;
6942 /* fill the buffer with the form structures */
6943 for (i=0; i<numbuiltinforms; i++) {
6944 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6945 smb_io_form_1("", buffer, &forms_1[i], 0);
6947 for (; i<*numofforms; i++) {
6948 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6949 smb_io_form_1("", buffer, &forms_1[i], 0);
6954 if (*needed > offered) {
6956 return WERR_INSUFFICIENT_BUFFER;
6963 SAFE_FREE(builtinlist);
6964 return WERR_UNKNOWN_LEVEL;
6969 /****************************************************************************
6970 ****************************************************************************/
6972 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6974 uint32 level = q_u->level;
6975 UNISTR2 *uni_formname = &q_u->formname;
6976 NEW_BUFFER *buffer = NULL;
6977 uint32 offered = q_u->offered;
6978 uint32 *needed = &r_u->needed;
6980 nt_forms_struct *list=NULL;
6981 nt_forms_struct builtin_form;
6986 int numofforms=0, i=0;
6988 /* that's an [in out] buffer */
6989 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6990 buffer = r_u->buffer;
6992 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6994 DEBUG(4,("_spoolss_getform\n"));
6995 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6996 DEBUGADD(5,("Info level [%d]\n", level));
6998 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6999 if (!foundBuiltin) {
7000 numofforms = get_ntforms(&list);
7001 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7003 if (numofforms == 0)
7010 fill_form_1(&form_1, &builtin_form);
7013 /* Check if the requested name is in the list of form structures */
7014 for (i=0; i<numofforms; i++) {
7016 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7018 if (strequal(form_name, list[i].name)) {
7019 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7020 fill_form_1(&form_1, &list[i]);
7026 if (i == numofforms) {
7030 /* check the required size. */
7032 *needed=spoolss_size_form_1(&form_1);
7034 if (!alloc_buffer_size(buffer, buffer_size)){
7035 return WERR_INSUFFICIENT_BUFFER;
7038 if (*needed > offered) {
7039 return WERR_INSUFFICIENT_BUFFER;
7042 /* fill the buffer with the form structures */
7043 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7044 smb_io_form_1("", buffer, &form_1, 0);
7050 return WERR_UNKNOWN_LEVEL;
7054 /****************************************************************************
7055 ****************************************************************************/
7057 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7059 init_unistr(&port->port_name, name);
7062 /****************************************************************************
7063 ****************************************************************************/
7065 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7067 init_unistr(&port->port_name, name);
7068 init_unistr(&port->monitor_name, "Local Monitor");
7069 init_unistr(&port->description, "Local Port");
7070 #define PORT_TYPE_WRITE 1
7071 port->port_type=PORT_TYPE_WRITE;
7075 /****************************************************************************
7077 ****************************************************************************/
7079 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7081 PORT_INFO_1 *ports=NULL;
7084 if (*lp_enumports_cmd()) {
7085 char *cmd = lp_enumports_cmd();
7092 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7094 DEBUG(10,("Running [%s]\n", command));
7095 ret = smbrun(command, &fd);
7096 DEBUG(10,("Returned [%d]\n", ret));
7100 /* Is this the best error to return here? */
7101 return WERR_ACCESS_DENIED;
7105 qlines = fd_lines_load(fd, &numlines);
7106 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7110 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7111 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7112 dos_errstr(WERR_NOMEM)));
7113 file_lines_free(qlines);
7117 for (i=0; i<numlines; i++) {
7118 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7119 fill_port_1(&ports[i], qlines[i]);
7122 file_lines_free(qlines);
7125 *returned = numlines;
7128 *returned = 1; /* Sole Samba port returned. */
7130 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7133 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7135 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7138 /* check the required size. */
7139 for (i=0; i<*returned; i++) {
7140 DEBUGADD(6,("adding port [%d]'s size\n", i));
7141 *needed += spoolss_size_port_info_1(&ports[i]);
7144 if (!alloc_buffer_size(buffer, *needed)) {
7146 return WERR_INSUFFICIENT_BUFFER;
7149 /* fill the buffer with the ports structures */
7150 for (i=0; i<*returned; i++) {
7151 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7152 smb_io_port_1("", buffer, &ports[i], 0);
7157 if (*needed > offered) {
7159 return WERR_INSUFFICIENT_BUFFER;
7165 /****************************************************************************
7167 ****************************************************************************/
7169 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7171 PORT_INFO_2 *ports=NULL;
7174 if (*lp_enumports_cmd()) {
7175 char *cmd = lp_enumports_cmd();
7184 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7185 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7187 path = lp_lockdir();
7189 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7190 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7193 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7194 ret = smbrun(command, &fd);
7195 DEBUGADD(10,("returned [%d]\n", ret));
7199 /* Is this the best error to return here? */
7200 return WERR_ACCESS_DENIED;
7204 qlines = fd_lines_load(fd, &numlines);
7205 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7209 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7210 file_lines_free(qlines);
7214 for (i=0; i<numlines; i++) {
7215 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7216 fill_port_2(&(ports[i]), qlines[i]);
7219 file_lines_free(qlines);
7222 *returned = numlines;
7228 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7231 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7233 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7236 /* check the required size. */
7237 for (i=0; i<*returned; i++) {
7238 DEBUGADD(6,("adding port [%d]'s size\n", i));
7239 *needed += spoolss_size_port_info_2(&ports[i]);
7242 if (!alloc_buffer_size(buffer, *needed)) {
7244 return WERR_INSUFFICIENT_BUFFER;
7247 /* fill the buffer with the ports structures */
7248 for (i=0; i<*returned; i++) {
7249 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7250 smb_io_port_2("", buffer, &ports[i], 0);
7255 if (*needed > offered) {
7257 return WERR_INSUFFICIENT_BUFFER;
7263 /****************************************************************************
7265 ****************************************************************************/
7267 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7269 uint32 level = q_u->level;
7270 NEW_BUFFER *buffer = NULL;
7271 uint32 offered = q_u->offered;
7272 uint32 *needed = &r_u->needed;
7273 uint32 *returned = &r_u->returned;
7275 /* that's an [in out] buffer */
7276 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7277 buffer = r_u->buffer;
7279 DEBUG(4,("_spoolss_enumports\n"));
7286 return enumports_level_1(buffer, offered, needed, returned);
7288 return enumports_level_2(buffer, offered, needed, returned);
7290 return WERR_UNKNOWN_LEVEL;
7294 /****************************************************************************
7295 ****************************************************************************/
7297 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7298 const SPOOL_PRINTER_INFO_LEVEL *info,
7299 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7300 uint32 user_switch, const SPOOL_USER_CTR *user,
7303 NT_PRINTER_INFO_LEVEL *printer = NULL;
7306 WERROR err = WERR_OK;
7308 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7309 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7313 ZERO_STRUCTP(printer);
7315 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7316 if (!convert_printer_info(info, printer, 2)) {
7317 free_a_printer(&printer, 2);
7321 /* check to see if the printer already exists */
7323 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7324 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7325 printer->info_2->sharename));
7326 free_a_printer(&printer, 2);
7327 return WERR_PRINTER_ALREADY_EXISTS;
7330 /* FIXME!!! smbd should check to see if the driver is installed before
7331 trying to add a printer like this --jerry */
7333 if (*lp_addprinter_cmd() ) {
7334 if ( !add_printer_hook(printer) ) {
7335 free_a_printer(&printer,2);
7336 return WERR_ACCESS_DENIED;
7340 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7341 printer->info_2->sharename);
7344 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7345 free_a_printer(&printer,2);
7346 return WERR_ACCESS_DENIED;
7349 /* you must be a printer admin to add a new printer */
7350 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7351 free_a_printer(&printer,2);
7352 return WERR_ACCESS_DENIED;
7356 * Do sanity check on the requested changes for Samba.
7359 if (!check_printer_ok(printer->info_2, snum)) {
7360 free_a_printer(&printer,2);
7361 return WERR_INVALID_PARAM;
7365 * When a printer is created, the drivername bound to the printer is used
7366 * to lookup previously saved driver initialization info, which is then
7367 * bound to the new printer, simulating what happens in the Windows arch.
7372 set_driver_init(printer, 2);
7376 /* A valid devmode was included, convert and link it
7378 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7380 if (!convert_devicemode(printer->info_2->printername, devmode,
7381 &printer->info_2->devmode))
7385 /* write the ASCII on disk */
7386 err = mod_a_printer(*printer, 2);
7387 if (!W_ERROR_IS_OK(err)) {
7388 free_a_printer(&printer,2);
7392 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7393 /* Handle open failed - remove addition. */
7394 del_a_printer(printer->info_2->sharename);
7395 free_a_printer(&printer,2);
7396 return WERR_ACCESS_DENIED;
7399 update_c_setprinter(False);
7400 free_a_printer(&printer,2);
7405 /****************************************************************************
7406 ****************************************************************************/
7408 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7410 UNISTR2 *uni_srv_name = &q_u->server_name;
7411 uint32 level = q_u->level;
7412 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7413 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7414 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7415 uint32 user_switch = q_u->user_switch;
7416 SPOOL_USER_CTR *user = &q_u->user_ctr;
7417 POLICY_HND *handle = &r_u->handle;
7421 /* we don't handle yet */
7422 /* but I know what to do ... */
7423 return WERR_UNKNOWN_LEVEL;
7425 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7427 user_switch, user, handle);
7429 return WERR_UNKNOWN_LEVEL;
7433 /****************************************************************************
7434 ****************************************************************************/
7436 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7438 uint32 level = q_u->level;
7439 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7440 WERROR err = WERR_OK;
7441 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7442 struct current_user user;
7443 fstring driver_name;
7446 ZERO_STRUCT(driver);
7448 get_current_user(&user, p);
7450 if (!convert_printer_driver_info(info, &driver, level)) {
7455 DEBUG(5,("Cleaning driver's information\n"));
7456 err = clean_up_driver_struct(driver, level, &user);
7457 if (!W_ERROR_IS_OK(err))
7460 DEBUG(5,("Moving driver to final destination\n"));
7461 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7462 if (W_ERROR_IS_OK(err))
7463 err = WERR_ACCESS_DENIED;
7467 if (add_a_printer_driver(driver, level)!=0) {
7468 err = WERR_ACCESS_DENIED;
7472 /* BEGIN_ADMIN_LOG */
7475 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7476 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7477 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7480 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7481 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7482 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7488 * I think this is where he DrvUpgradePrinter() hook would be
7489 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7490 * server. Right now, we just need to send ourselves a message
7491 * to update each printer bound to this driver. --jerry
7494 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7495 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7500 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7501 * decide if the driver init data should be deleted. The rules are:
7502 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7503 * 2) delete init data only if there is no 2k/Xp driver
7504 * 3) always delete init data
7505 * The generalized rule is always use init data from the highest order driver.
7506 * It is necessary to follow the driver install by an initialization step to
7507 * finish off this process.
7510 version = driver.info_3->cversion;
7511 else if (level == 6)
7512 version = driver.info_6->version;
7517 * 9x printer driver - never delete init data
7520 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7525 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7526 * there is no 2k/Xp driver init data for this driver name.
7530 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7532 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7534 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7536 if (!del_driver_init(driver_name))
7537 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7540 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7542 free_a_printer_driver(driver1,3);
7543 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7550 * 2k or Xp printer driver - always delete init data
7553 if (!del_driver_init(driver_name))
7554 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7558 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7564 free_a_printer_driver(driver, level);
7568 /********************************************************************
7569 * spoolss_addprinterdriverex
7570 ********************************************************************/
7572 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7574 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7575 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7578 * we only support the semantics of AddPrinterDriver()
7579 * i.e. only copy files that are newer than existing ones
7582 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7583 return WERR_ACCESS_DENIED;
7585 ZERO_STRUCT(q_u_local);
7586 ZERO_STRUCT(r_u_local);
7588 /* just pass the information off to _spoolss_addprinterdriver() */
7589 q_u_local.server_name_ptr = q_u->server_name_ptr;
7590 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7591 q_u_local.level = q_u->level;
7592 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7594 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7597 /****************************************************************************
7598 ****************************************************************************/
7600 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7602 init_unistr(&info->name, name);
7605 /****************************************************************************
7606 ****************************************************************************/
7608 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7612 const char *short_archi;
7613 DRIVER_DIRECTORY_1 *info=NULL;
7615 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7617 if (!(short_archi = get_short_archi(long_archi)))
7618 return WERR_INVALID_ENVIRONMENT;
7620 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7623 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7625 DEBUG(4,("printer driver directory: [%s]\n", path));
7627 fill_driverdir_1(info, path);
7629 *needed += spoolss_size_driverdir_info_1(info);
7631 if (!alloc_buffer_size(buffer, *needed)) {
7633 return WERR_INSUFFICIENT_BUFFER;
7636 smb_io_driverdir_1("", buffer, info, 0);
7640 if (*needed > offered)
7641 return WERR_INSUFFICIENT_BUFFER;
7646 /****************************************************************************
7647 ****************************************************************************/
7649 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7651 UNISTR2 *name = &q_u->name;
7652 UNISTR2 *uni_environment = &q_u->environment;
7653 uint32 level = q_u->level;
7654 NEW_BUFFER *buffer = NULL;
7655 uint32 offered = q_u->offered;
7656 uint32 *needed = &r_u->needed;
7658 /* that's an [in out] buffer */
7659 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7660 buffer = r_u->buffer;
7662 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7668 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7670 return WERR_UNKNOWN_LEVEL;
7674 /****************************************************************************
7675 ****************************************************************************/
7677 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7679 POLICY_HND *handle = &q_u->handle;
7680 uint32 idx = q_u->index;
7681 uint32 in_value_len = q_u->valuesize;
7682 uint32 in_data_len = q_u->datasize;
7683 uint32 *out_max_value_len = &r_u->valuesize;
7684 uint16 **out_value = &r_u->value;
7685 uint32 *out_value_len = &r_u->realvaluesize;
7686 uint32 *out_type = &r_u->type;
7687 uint32 *out_max_data_len = &r_u->datasize;
7688 uint8 **data_out = &r_u->data;
7689 uint32 *out_data_len = &r_u->realdatasize;
7691 NT_PRINTER_INFO_LEVEL *printer = NULL;
7694 uint32 biggest_valuesize;
7695 uint32 biggest_datasize;
7697 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7700 REGISTRY_VALUE *val = NULL;
7701 NT_PRINTER_DATA *p_data;
7702 int i, key_index, num_values;
7705 ZERO_STRUCT( printer );
7709 *out_max_data_len = 0;
7713 DEBUG(5,("spoolss_enumprinterdata\n"));
7716 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7720 if (!get_printer_snum(p,handle, &snum))
7723 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7724 if (!W_ERROR_IS_OK(result))
7727 p_data = &printer->info_2->data;
7728 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7733 * The NT machine wants to know the biggest size of value and data
7735 * cf: MSDN EnumPrinterData remark section
7738 if ( !in_value_len && !in_data_len && (key_index != -1) )
7740 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7743 biggest_valuesize = 0;
7744 biggest_datasize = 0;
7746 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7748 for ( i=0; i<num_values; i++ )
7750 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7752 name_length = strlen(val->valuename);
7753 if ( strlen(val->valuename) > biggest_valuesize )
7754 biggest_valuesize = name_length;
7756 if ( val->size > biggest_datasize )
7757 biggest_datasize = val->size;
7759 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7763 /* the value is an UNICODE string but real_value_size is the length
7764 in bytes including the trailing 0 */
7766 *out_value_len = 2 * (1+biggest_valuesize);
7767 *out_data_len = biggest_datasize;
7769 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7775 * the value len is wrong in NT sp3
7776 * that's the number of bytes not the number of unicode chars
7779 if ( key_index != -1 )
7780 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7785 /* out_value should default to "" or else NT4 has
7786 problems unmarshalling the response */
7788 *out_max_value_len=(in_value_len/sizeof(uint16));
7790 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7792 result = WERR_NOMEM;
7796 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7798 /* the data is counted in bytes */
7800 *out_max_data_len = in_data_len;
7801 *out_data_len = in_data_len;
7803 /* only allocate when given a non-zero data_len */
7805 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7807 result = WERR_NOMEM;
7811 result = WERR_NO_MORE_ITEMS;
7817 * - counted in bytes in the request
7818 * - counted in UNICODE chars in the max reply
7819 * - counted in bytes in the real size
7821 * take a pause *before* coding not *during* coding
7825 *out_max_value_len=(in_value_len/sizeof(uint16));
7826 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7828 result = WERR_NOMEM;
7832 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7836 *out_type = regval_type( val );
7838 /* data - counted in bytes */
7840 *out_max_data_len = in_data_len;
7841 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7843 result = WERR_NOMEM;
7846 data_len = (size_t)regval_size(val);
7847 memcpy( *data_out, regval_data_p(val), data_len );
7848 *out_data_len = data_len;
7852 free_a_printer(&printer, 2);
7856 /****************************************************************************
7857 ****************************************************************************/
7859 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7861 POLICY_HND *handle = &q_u->handle;
7862 UNISTR2 *value = &q_u->value;
7863 uint32 type = q_u->type;
7864 uint8 *data = q_u->data;
7865 uint32 real_len = q_u->real_len;
7867 NT_PRINTER_INFO_LEVEL *printer = NULL;
7869 WERROR status = WERR_OK;
7870 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7873 DEBUG(5,("spoolss_setprinterdata\n"));
7876 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7880 if (!get_printer_snum(p,handle, &snum))
7884 * Access check : NT returns "access denied" if you make a
7885 * SetPrinterData call without the necessary privildge.
7886 * we were originally returning OK if nothing changed
7887 * which made Win2k issue **a lot** of SetPrinterData
7888 * when connecting to a printer --jerry
7891 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7893 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7894 status = WERR_ACCESS_DENIED;
7898 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7899 if (!W_ERROR_IS_OK(status))
7902 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7905 * When client side code sets a magic printer data key, detect it and save
7906 * the current printer data and the magic key's data (its the DEVMODE) for
7907 * future printer/driver initializations.
7909 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7911 /* Set devmode and printer initialization info */
7912 status = save_driver_init( printer, 2, data, real_len );
7914 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7918 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7919 type, data, real_len );
7920 if ( W_ERROR_IS_OK(status) )
7921 status = mod_a_printer(*printer, 2);
7925 free_a_printer(&printer, 2);
7930 /****************************************************************************
7931 ****************************************************************************/
7933 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7935 POLICY_HND *handle = &q_u->handle;
7936 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7939 DEBUG(5,("_spoolss_resetprinter\n"));
7942 * All we do is to check to see if the handle and queue is valid.
7943 * This call really doesn't mean anything to us because we only
7944 * support RAW printing. --jerry
7948 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7952 if (!get_printer_snum(p,handle, &snum))
7956 /* blindly return success */
7961 /****************************************************************************
7962 ****************************************************************************/
7964 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7966 POLICY_HND *handle = &q_u->handle;
7967 UNISTR2 *value = &q_u->valuename;
7969 NT_PRINTER_INFO_LEVEL *printer = NULL;
7971 WERROR status = WERR_OK;
7972 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7975 DEBUG(5,("spoolss_deleteprinterdata\n"));
7978 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7982 if (!get_printer_snum(p, handle, &snum))
7985 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7986 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7987 return WERR_ACCESS_DENIED;
7990 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7991 if (!W_ERROR_IS_OK(status))
7994 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7996 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7998 free_a_printer(&printer, 2);
8003 /****************************************************************************
8004 ****************************************************************************/
8006 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8008 POLICY_HND *handle = &q_u->handle;
8009 FORM *form = &q_u->form;
8010 nt_forms_struct tmpForm;
8012 WERROR status = WERR_OK;
8013 NT_PRINTER_INFO_LEVEL *printer = NULL;
8016 nt_forms_struct *list=NULL;
8017 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8019 DEBUG(5,("spoolss_addform\n"));
8022 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8027 /* forms can be added on printer of on the print server handle */
8029 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8031 if (!get_printer_snum(p,handle, &snum))
8034 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8035 if (!W_ERROR_IS_OK(status))
8039 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8040 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8041 status = WERR_ACCESS_DENIED;
8045 /* can't add if builtin */
8047 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8048 status = WERR_ALREADY_EXISTS;
8052 count = get_ntforms(&list);
8054 if(!add_a_form(&list, form, &count)) {
8055 status = WERR_NOMEM;
8059 write_ntforms(&list, count);
8062 * ChangeID must always be set if this is a printer
8065 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8066 status = mod_a_printer(*printer, 2);
8070 free_a_printer(&printer, 2);
8076 /****************************************************************************
8077 ****************************************************************************/
8079 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8081 POLICY_HND *handle = &q_u->handle;
8082 UNISTR2 *form_name = &q_u->name;
8083 nt_forms_struct tmpForm;
8085 nt_forms_struct *list=NULL;
8086 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8088 WERROR status = WERR_OK;
8089 NT_PRINTER_INFO_LEVEL *printer = NULL;
8091 DEBUG(5,("spoolss_deleteform\n"));
8094 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8098 /* forms can be deleted on printer of on the print server handle */
8100 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8102 if (!get_printer_snum(p,handle, &snum))
8105 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8106 if (!W_ERROR_IS_OK(status))
8110 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8111 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8112 status = WERR_ACCESS_DENIED;
8116 /* can't delete if builtin */
8118 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8119 status = WERR_INVALID_PARAM;
8123 count = get_ntforms(&list);
8125 if ( !delete_a_form(&list, form_name, &count, &status ))
8129 * ChangeID must always be set if this is a printer
8132 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8133 status = mod_a_printer(*printer, 2);
8137 free_a_printer(&printer, 2);
8143 /****************************************************************************
8144 ****************************************************************************/
8146 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8148 POLICY_HND *handle = &q_u->handle;
8149 FORM *form = &q_u->form;
8150 nt_forms_struct tmpForm;
8152 WERROR status = WERR_OK;
8153 NT_PRINTER_INFO_LEVEL *printer = NULL;
8156 nt_forms_struct *list=NULL;
8157 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8159 DEBUG(5,("spoolss_setform\n"));
8162 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8166 /* forms can be modified on printer of on the print server handle */
8168 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8170 if (!get_printer_snum(p,handle, &snum))
8173 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8174 if (!W_ERROR_IS_OK(status))
8178 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8179 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8180 status = WERR_ACCESS_DENIED;
8184 /* can't set if builtin */
8185 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8186 status = WERR_INVALID_PARAM;
8190 count = get_ntforms(&list);
8191 update_a_form(&list, form, count);
8192 write_ntforms(&list, count);
8195 * ChangeID must always be set if this is a printer
8198 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8199 status = mod_a_printer(*printer, 2);
8204 free_a_printer(&printer, 2);
8210 /****************************************************************************
8211 enumprintprocessors level 1.
8212 ****************************************************************************/
8214 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8216 PRINTPROCESSOR_1 *info_1=NULL;
8218 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8223 init_unistr(&info_1->name, "winprint");
8225 *needed += spoolss_size_printprocessor_info_1(info_1);
8227 if (!alloc_buffer_size(buffer, *needed))
8228 return WERR_INSUFFICIENT_BUFFER;
8230 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8234 if (*needed > offered) {
8236 return WERR_INSUFFICIENT_BUFFER;
8242 /****************************************************************************
8243 ****************************************************************************/
8245 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8247 uint32 level = q_u->level;
8248 NEW_BUFFER *buffer = NULL;
8249 uint32 offered = q_u->offered;
8250 uint32 *needed = &r_u->needed;
8251 uint32 *returned = &r_u->returned;
8253 /* that's an [in out] buffer */
8254 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8255 buffer = r_u->buffer;
8257 DEBUG(5,("spoolss_enumprintprocessors\n"));
8260 * Enumerate the print processors ...
8262 * Just reply with "winprint", to keep NT happy
8263 * and I can use my nice printer checker.
8271 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8273 return WERR_UNKNOWN_LEVEL;
8277 /****************************************************************************
8278 enumprintprocdatatypes level 1.
8279 ****************************************************************************/
8281 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8283 PRINTPROCDATATYPE_1 *info_1=NULL;
8285 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8290 init_unistr(&info_1->name, "RAW");
8292 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8294 if (!alloc_buffer_size(buffer, *needed))
8295 return WERR_INSUFFICIENT_BUFFER;
8297 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8301 if (*needed > offered) {
8303 return WERR_INSUFFICIENT_BUFFER;
8309 /****************************************************************************
8310 ****************************************************************************/
8312 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8314 uint32 level = q_u->level;
8315 NEW_BUFFER *buffer = NULL;
8316 uint32 offered = q_u->offered;
8317 uint32 *needed = &r_u->needed;
8318 uint32 *returned = &r_u->returned;
8320 /* that's an [in out] buffer */
8321 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8322 buffer = r_u->buffer;
8324 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8331 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8333 return WERR_UNKNOWN_LEVEL;
8337 /****************************************************************************
8338 enumprintmonitors level 1.
8339 ****************************************************************************/
8341 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8343 PRINTMONITOR_1 *info_1=NULL;
8345 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8350 init_unistr(&info_1->name, "Local Port");
8352 *needed += spoolss_size_printmonitor_info_1(info_1);
8354 if (!alloc_buffer_size(buffer, *needed))
8355 return WERR_INSUFFICIENT_BUFFER;
8357 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8361 if (*needed > offered) {
8363 return WERR_INSUFFICIENT_BUFFER;
8369 /****************************************************************************
8370 enumprintmonitors level 2.
8371 ****************************************************************************/
8373 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8375 PRINTMONITOR_2 *info_2=NULL;
8377 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8382 init_unistr(&info_2->name, "Local Port");
8383 init_unistr(&info_2->environment, "Windows NT X86");
8384 init_unistr(&info_2->dll_name, "localmon.dll");
8386 *needed += spoolss_size_printmonitor_info_2(info_2);
8388 if (!alloc_buffer_size(buffer, *needed))
8389 return WERR_INSUFFICIENT_BUFFER;
8391 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8395 if (*needed > offered) {
8397 return WERR_INSUFFICIENT_BUFFER;
8403 /****************************************************************************
8404 ****************************************************************************/
8406 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8408 uint32 level = q_u->level;
8409 NEW_BUFFER *buffer = NULL;
8410 uint32 offered = q_u->offered;
8411 uint32 *needed = &r_u->needed;
8412 uint32 *returned = &r_u->returned;
8414 /* that's an [in out] buffer */
8415 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8416 buffer = r_u->buffer;
8418 DEBUG(5,("spoolss_enumprintmonitors\n"));
8421 * Enumerate the print monitors ...
8423 * Just reply with "Local Port", to keep NT happy
8424 * and I can use my nice printer checker.
8432 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8434 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8436 return WERR_UNKNOWN_LEVEL;
8440 /****************************************************************************
8441 ****************************************************************************/
8443 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8447 JOB_INFO_1 *info_1=NULL;
8449 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8451 if (info_1 == NULL) {
8455 for (i=0; i<count && found==False; i++) {
8456 if ((*queue)[i].job==(int)jobid)
8462 /* NT treats not found as bad param... yet another bad choice */
8463 return WERR_INVALID_PARAM;
8466 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8468 *needed += spoolss_size_job_info_1(info_1);
8470 if (!alloc_buffer_size(buffer, *needed)) {
8472 return WERR_INSUFFICIENT_BUFFER;
8475 smb_io_job_info_1("", buffer, info_1, 0);
8479 if (*needed > offered)
8480 return WERR_INSUFFICIENT_BUFFER;
8485 /****************************************************************************
8486 ****************************************************************************/
8488 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8493 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8495 DEVICEMODE *devmode = NULL;
8496 NT_DEVICEMODE *nt_devmode = NULL;
8498 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8500 ZERO_STRUCTP(info_2);
8502 if (info_2 == NULL) {
8507 for ( i=0; i<count && found==False; i++ )
8509 if ((*queue)[i].job == (int)jobid)
8515 /* NT treats not found as bad param... yet another bad
8517 ret = WERR_INVALID_PARAM;
8521 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8522 if (!W_ERROR_IS_OK(ret))
8526 * if the print job does not have a DEVMODE associated with it,
8527 * just use the one for the printer. A NULL devicemode is not
8528 * a failure condition
8531 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8532 devmode = construct_dev_mode(snum);
8534 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8535 ZERO_STRUCTP( devmode );
8536 convert_nt_devicemode( devmode, nt_devmode );
8540 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8542 *needed += spoolss_size_job_info_2(info_2);
8544 if (!alloc_buffer_size(buffer, *needed)) {
8545 ret = WERR_INSUFFICIENT_BUFFER;
8549 smb_io_job_info_2("", buffer, info_2, 0);
8551 if (*needed > offered) {
8552 ret = WERR_INSUFFICIENT_BUFFER;
8559 /* Cleanup allocated memory */
8561 free_job_info_2(info_2); /* Also frees devmode */
8563 free_a_printer(&ntprinter, 2);
8568 /****************************************************************************
8569 ****************************************************************************/
8571 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8573 POLICY_HND *handle = &q_u->handle;
8574 uint32 jobid = q_u->jobid;
8575 uint32 level = q_u->level;
8576 NEW_BUFFER *buffer = NULL;
8577 uint32 offered = q_u->offered;
8578 uint32 *needed = &r_u->needed;
8579 WERROR wstatus = WERR_OK;
8583 print_queue_struct *queue = NULL;
8584 print_status_struct prt_status;
8586 /* that's an [in out] buffer */
8587 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8588 buffer = r_u->buffer;
8590 DEBUG(5,("spoolss_getjob\n"));
8594 if (!get_printer_snum(p, handle, &snum))
8597 count = print_queue_status(snum, &queue, &prt_status);
8599 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8600 count, prt_status.status, prt_status.message));
8604 wstatus = getjob_level_1(&queue, count, snum, jobid,
8605 buffer, offered, needed);
8608 wstatus = getjob_level_2(&queue, count, snum, jobid,
8609 buffer, offered, needed);
8612 wstatus = WERR_UNKNOWN_LEVEL;
8620 /********************************************************************
8621 spoolss_getprinterdataex
8623 From MSDN documentation of GetPrinterDataEx: pass request
8624 to GetPrinterData if key is "PrinterDriverData".
8625 ********************************************************************/
8627 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8629 POLICY_HND *handle = &q_u->handle;
8630 uint32 in_size = q_u->size;
8631 uint32 *type = &r_u->type;
8632 uint32 *out_size = &r_u->size;
8633 uint8 **data = &r_u->data;
8634 uint32 *needed = &r_u->needed;
8635 fstring keyname, valuename;
8637 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8639 NT_PRINTER_INFO_LEVEL *printer = NULL;
8641 WERROR status = WERR_OK;
8643 DEBUG(4,("_spoolss_getprinterdataex\n"));
8645 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8646 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8648 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8649 keyname, valuename));
8651 /* in case of problem, return some default values */
8655 *out_size = in_size;
8658 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8659 status = WERR_BADFID;
8663 /* Is the handle to a printer or to the server? */
8665 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8666 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8667 status = WERR_INVALID_PARAM;
8671 if ( !get_printer_snum(p,handle, &snum) )
8674 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8675 if ( !W_ERROR_IS_OK(status) )
8678 /* check to see if the keyname is valid */
8679 if ( !strlen(keyname) ) {
8680 status = WERR_INVALID_PARAM;
8684 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8685 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8686 free_a_printer( &printer, 2 );
8687 status = WERR_BADFILE;
8691 /* When given a new keyname, we should just create it */
8693 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8695 if (*needed > *out_size)
8696 status = WERR_MORE_DATA;
8699 if ( !W_ERROR_IS_OK(status) )
8701 DEBUG(5, ("error: allocating %d\n", *out_size));
8703 /* reply this param doesn't exist */
8707 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8708 status = WERR_NOMEM;
8718 free_a_printer( &printer, 2 );
8723 /********************************************************************
8724 * spoolss_setprinterdataex
8725 ********************************************************************/
8727 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8729 POLICY_HND *handle = &q_u->handle;
8730 uint32 type = q_u->type;
8731 uint8 *data = q_u->data;
8732 uint32 real_len = q_u->real_len;
8734 NT_PRINTER_INFO_LEVEL *printer = NULL;
8736 WERROR status = WERR_OK;
8737 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8742 DEBUG(4,("_spoolss_setprinterdataex\n"));
8744 /* From MSDN documentation of SetPrinterDataEx: pass request to
8745 SetPrinterData if key is "PrinterDriverData" */
8748 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8752 if ( !get_printer_snum(p,handle, &snum) )
8756 * Access check : NT returns "access denied" if you make a
8757 * SetPrinterData call without the necessary privildge.
8758 * we were originally returning OK if nothing changed
8759 * which made Win2k issue **a lot** of SetPrinterData
8760 * when connecting to a printer --jerry
8763 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8765 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8766 return WERR_ACCESS_DENIED;
8769 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8770 if (!W_ERROR_IS_OK(status))
8773 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8774 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8776 /* check for OID in valuename */
8778 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8784 /* save the registry data */
8786 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8788 if ( W_ERROR_IS_OK(status) )
8790 /* save the OID if one was specified */
8792 fstrcat( keyname, "\\" );
8793 fstrcat( keyname, SPOOL_OID_KEY );
8796 * I'm not checking the status here on purpose. Don't know
8797 * if this is right, but I'm returning the status from the
8798 * previous set_printer_dataex() call. I have no idea if
8799 * this is right. --jerry
8802 set_printer_dataex( printer, keyname, valuename,
8803 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8806 status = mod_a_printer(*printer, 2);
8809 free_a_printer(&printer, 2);
8815 /********************************************************************
8816 * spoolss_deleteprinterdataex
8817 ********************************************************************/
8819 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8821 POLICY_HND *handle = &q_u->handle;
8822 UNISTR2 *value = &q_u->valuename;
8823 UNISTR2 *key = &q_u->keyname;
8825 NT_PRINTER_INFO_LEVEL *printer = NULL;
8827 WERROR status = WERR_OK;
8828 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8829 pstring valuename, keyname;
8831 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8834 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8838 if (!get_printer_snum(p, handle, &snum))
8841 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8842 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8843 return WERR_ACCESS_DENIED;
8846 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8847 if (!W_ERROR_IS_OK(status))
8850 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8851 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8853 status = delete_printer_dataex( printer, keyname, valuename );
8855 free_a_printer(&printer, 2);
8860 /********************************************************************
8861 * spoolss_enumprinterkey
8862 ********************************************************************/
8865 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8868 fstring *keynames = NULL;
8869 uint16 *enumkeys = NULL;
8872 POLICY_HND *handle = &q_u->handle;
8873 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8874 NT_PRINTER_DATA *data;
8875 NT_PRINTER_INFO_LEVEL *printer = NULL;
8877 WERROR status = WERR_BADFILE;
8880 DEBUG(4,("_spoolss_enumprinterkey\n"));
8883 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8887 if ( !get_printer_snum(p,handle, &snum) )
8890 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8891 if (!W_ERROR_IS_OK(status))
8894 /* get the list of subkey names */
8896 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8897 data = &printer->info_2->data;
8899 num_keys = get_printer_subkeys( data, key, &keynames );
8901 if ( num_keys == -1 ) {
8902 status = WERR_BADFILE;
8906 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8908 r_u->needed = printerkey_len*2;
8910 if ( q_u->size < r_u->needed ) {
8911 status = WERR_MORE_DATA;
8915 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8916 status = WERR_NOMEM;
8922 if ( q_u->size < r_u->needed )
8923 status = WERR_MORE_DATA;
8926 free_a_printer( &printer, 2 );
8927 SAFE_FREE( keynames );
8932 /********************************************************************
8933 * spoolss_deleteprinterkey
8934 ********************************************************************/
8936 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8938 POLICY_HND *handle = &q_u->handle;
8939 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8941 NT_PRINTER_INFO_LEVEL *printer = NULL;
8945 DEBUG(5,("spoolss_deleteprinterkey\n"));
8948 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8952 /* if keyname == NULL, return error */
8954 if ( !q_u->keyname.buffer )
8955 return WERR_INVALID_PARAM;
8957 if (!get_printer_snum(p, handle, &snum))
8960 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8961 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8962 return WERR_ACCESS_DENIED;
8965 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8966 if (!W_ERROR_IS_OK(status))
8969 /* delete the key and all subneys */
8971 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8973 status = delete_all_printer_data( printer->info_2, key );
8975 if ( W_ERROR_IS_OK(status) )
8976 status = mod_a_printer(*printer, 2);
8978 free_a_printer( &printer, 2 );
8984 /********************************************************************
8985 * spoolss_enumprinterdataex
8986 ********************************************************************/
8988 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8990 POLICY_HND *handle = &q_u->handle;
8991 uint32 in_size = q_u->size;
8994 NT_PRINTER_INFO_LEVEL *printer = NULL;
8995 PRINTER_ENUM_VALUES *enum_values = NULL;
8996 NT_PRINTER_DATA *p_data;
8998 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9003 REGISTRY_VALUE *val;
9008 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9011 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9016 * first check for a keyname of NULL or "". Win2k seems to send
9017 * this a lot and we should send back WERR_INVALID_PARAM
9018 * no need to spend time looking up the printer in this case.
9022 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9023 if ( !strlen(key) ) {
9024 result = WERR_INVALID_PARAM;
9028 /* get the printer off of disk */
9030 if (!get_printer_snum(p,handle, &snum))
9033 ZERO_STRUCT(printer);
9034 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9035 if (!W_ERROR_IS_OK(result))
9038 /* now look for a match on the key name */
9040 p_data = &printer->info_2->data;
9042 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9043 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9045 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9046 result = WERR_INVALID_PARAM;
9053 /* allocate the memory for the array of pointers -- if necessary */
9055 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9058 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9060 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
9061 num_entries*sizeof(PRINTER_ENUM_VALUES)));
9062 result = WERR_NOMEM;
9066 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9070 * loop through all params and build the array to pass
9071 * back to the client
9074 for ( i=0; i<num_entries; i++ )
9076 /* lookup the registry value */
9078 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9079 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9083 value_name = regval_name( val );
9084 init_unistr( &enum_values[i].valuename, value_name );
9085 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9086 enum_values[i].type = regval_type( val );
9088 data_len = regval_size( val );
9090 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9092 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9094 result = WERR_NOMEM;
9098 enum_values[i].data_len = data_len;
9100 /* keep track of the size of the array in bytes */
9102 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9105 /* housekeeping information in the reply */
9107 r_u->needed = needed;
9108 r_u->returned = num_entries;
9110 if (needed > in_size) {
9111 result = WERR_MORE_DATA;
9115 /* copy data into the reply */
9117 r_u->ctr.size = r_u->needed;
9118 r_u->ctr.size_of_array = r_u->returned;
9119 r_u->ctr.values = enum_values;
9125 free_a_printer(&printer, 2);
9130 /****************************************************************************
9131 ****************************************************************************/
9133 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9135 init_unistr(&info->name, name);
9138 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9139 UNISTR2 *environment,
9146 const char *short_archi;
9147 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9149 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9151 if (!(short_archi = get_short_archi(long_archi)))
9152 return WERR_INVALID_ENVIRONMENT;
9154 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9157 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9159 fill_printprocessordirectory_1(info, path);
9161 *needed += spoolss_size_printprocessordirectory_info_1(info);
9163 if (!alloc_buffer_size(buffer, *needed)) {
9165 return WERR_INSUFFICIENT_BUFFER;
9168 smb_io_printprocessordirectory_1("", buffer, info, 0);
9172 if (*needed > offered)
9173 return WERR_INSUFFICIENT_BUFFER;
9178 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9180 uint32 level = q_u->level;
9181 NEW_BUFFER *buffer = NULL;
9182 uint32 offered = q_u->offered;
9183 uint32 *needed = &r_u->needed;
9186 /* that's an [in out] buffer */
9187 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9188 buffer = r_u->buffer;
9190 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9196 result = getprintprocessordirectory_level_1
9197 (&q_u->name, &q_u->environment, buffer, offered, needed);
9200 result = WERR_UNKNOWN_LEVEL;
9208 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9209 SPOOL_R_REPLYOPENPRINTER *r_u)
9211 DEBUG(5,("_spoolss_replyopenprinter\n"));
9213 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9218 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9219 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9221 DEBUG(5,("_spoolss_replycloseprinter\n"));