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()) )
1787 /****************************************************************************
1788 ****************************************************************************/
1790 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1791 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1797 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1806 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1807 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1813 printer->info_3=NULL;
1814 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1818 printer->info_6=NULL;
1819 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1829 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1830 NT_DEVICEMODE **pp_nt_devmode)
1832 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1835 * Ensure nt_devmode is a valid pointer
1836 * as we will be overwriting it.
1839 if (nt_devmode == NULL) {
1840 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1841 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1845 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1846 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1848 nt_devmode->specversion=devmode->specversion;
1849 nt_devmode->driverversion=devmode->driverversion;
1850 nt_devmode->size=devmode->size;
1851 nt_devmode->fields=devmode->fields;
1852 nt_devmode->orientation=devmode->orientation;
1853 nt_devmode->papersize=devmode->papersize;
1854 nt_devmode->paperlength=devmode->paperlength;
1855 nt_devmode->paperwidth=devmode->paperwidth;
1856 nt_devmode->scale=devmode->scale;
1857 nt_devmode->copies=devmode->copies;
1858 nt_devmode->defaultsource=devmode->defaultsource;
1859 nt_devmode->printquality=devmode->printquality;
1860 nt_devmode->color=devmode->color;
1861 nt_devmode->duplex=devmode->duplex;
1862 nt_devmode->yresolution=devmode->yresolution;
1863 nt_devmode->ttoption=devmode->ttoption;
1864 nt_devmode->collate=devmode->collate;
1866 nt_devmode->logpixels=devmode->logpixels;
1867 nt_devmode->bitsperpel=devmode->bitsperpel;
1868 nt_devmode->pelswidth=devmode->pelswidth;
1869 nt_devmode->pelsheight=devmode->pelsheight;
1870 nt_devmode->displayflags=devmode->displayflags;
1871 nt_devmode->displayfrequency=devmode->displayfrequency;
1872 nt_devmode->icmmethod=devmode->icmmethod;
1873 nt_devmode->icmintent=devmode->icmintent;
1874 nt_devmode->mediatype=devmode->mediatype;
1875 nt_devmode->dithertype=devmode->dithertype;
1876 nt_devmode->reserved1=devmode->reserved1;
1877 nt_devmode->reserved2=devmode->reserved2;
1878 nt_devmode->panningwidth=devmode->panningwidth;
1879 nt_devmode->panningheight=devmode->panningheight;
1882 * Only change private and driverextra if the incoming devmode
1883 * has a new one. JRA.
1886 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1887 SAFE_FREE(nt_devmode->private);
1888 nt_devmode->driverextra=devmode->driverextra;
1889 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1891 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1894 *pp_nt_devmode = nt_devmode;
1899 /********************************************************************
1900 * _spoolss_enddocprinter_internal.
1901 ********************************************************************/
1903 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1905 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1909 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1913 if (!get_printer_snum(p, handle, &snum))
1916 Printer->document_started=False;
1917 print_job_end(snum, Printer->jobid,True);
1918 /* error codes unhandled so far ... */
1923 /********************************************************************
1924 * api_spoolss_closeprinter
1925 ********************************************************************/
1927 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1929 POLICY_HND *handle = &q_u->handle;
1931 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1933 if (Printer && Printer->document_started)
1934 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1936 if (!close_printer_handle(p, handle))
1939 /* clear the returned printer handle. Observed behavior
1940 from Win2k server. Don't think this really matters.
1941 Previous code just copied the value of the closed
1944 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1949 /********************************************************************
1950 * api_spoolss_deleteprinter
1952 ********************************************************************/
1954 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1956 POLICY_HND *handle = &q_u->handle;
1957 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1960 if (Printer && Printer->document_started)
1961 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1963 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1965 result = delete_printer_handle(p, handle);
1967 update_c_setprinter(False);
1972 /*******************************************************************
1973 * static function to lookup the version id corresponding to an
1974 * long architecture string
1975 ******************************************************************/
1977 static int get_version_id (char * arch)
1980 struct table_node archi_table[]= {
1982 {"Windows 4.0", "WIN40", 0 },
1983 {"Windows NT x86", "W32X86", 2 },
1984 {"Windows NT R4000", "W32MIPS", 2 },
1985 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1986 {"Windows NT PowerPC", "W32PPC", 2 },
1990 for (i=0; archi_table[i].long_archi != NULL; i++)
1992 if (strcmp(arch, archi_table[i].long_archi) == 0)
1993 return (archi_table[i].version);
1999 /********************************************************************
2000 * _spoolss_deleteprinterdriver
2001 ********************************************************************/
2003 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2007 NT_PRINTER_DRIVER_INFO_LEVEL info;
2008 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2010 struct current_user user;
2012 WERROR status_win2k = WERR_ACCESS_DENIED;
2014 get_current_user(&user, p);
2016 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2017 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2019 /* check that we have a valid driver name first */
2021 if ((version=get_version_id(arch)) == -1)
2022 return WERR_INVALID_ENVIRONMENT;
2025 ZERO_STRUCT(info_win2k);
2027 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2029 /* try for Win2k driver if "Windows NT x86" */
2031 if ( version == 2 ) {
2033 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2034 status = WERR_UNKNOWN_PRINTER_DRIVER;
2038 /* otherwise it was a failure */
2040 status = WERR_UNKNOWN_PRINTER_DRIVER;
2046 if (printer_driver_in_use(info.info_3)) {
2047 status = WERR_PRINTER_DRIVER_IN_USE;
2053 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2055 /* if we get to here, we now have 2 driver info structures to remove */
2056 /* remove the Win2k driver first*/
2058 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2059 free_a_printer_driver( info_win2k, 3 );
2061 /* this should not have failed---if it did, report to client */
2062 if ( !W_ERROR_IS_OK(status_win2k) )
2067 status = delete_printer_driver(info.info_3, &user, version, False);
2069 /* if at least one of the deletes succeeded return OK */
2071 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2075 free_a_printer_driver( info, 3 );
2080 /********************************************************************
2081 * spoolss_deleteprinterdriverex
2082 ********************************************************************/
2084 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2088 NT_PRINTER_DRIVER_INFO_LEVEL info;
2089 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2091 uint32 flags = q_u->delete_flags;
2093 struct current_user user;
2095 WERROR status_win2k = WERR_ACCESS_DENIED;
2097 get_current_user(&user, p);
2099 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2100 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2102 /* check that we have a valid driver name first */
2103 if ((version=get_version_id(arch)) == -1) {
2104 /* this is what NT returns */
2105 return WERR_INVALID_ENVIRONMENT;
2108 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2109 version = q_u->version;
2112 ZERO_STRUCT(info_win2k);
2114 status = get_a_printer_driver(&info, 3, driver, arch, version);
2116 if ( !W_ERROR_IS_OK(status) )
2119 * if the client asked for a specific version,
2120 * or this is something other than Windows NT x86,
2124 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2127 /* try for Win2k driver if "Windows NT x86" */
2130 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2131 status = WERR_UNKNOWN_PRINTER_DRIVER;
2136 if ( printer_driver_in_use(info.info_3) ) {
2137 status = WERR_PRINTER_DRIVER_IN_USE;
2142 * we have a couple of cases to consider.
2143 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2144 * then the delete should fail if **any** files overlap with
2146 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2147 * non-overlapping files
2148 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2149 * is set, the do not delete any files
2150 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2153 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2155 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2157 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2158 /* no idea of the correct error here */
2159 status = WERR_ACCESS_DENIED;
2164 /* also check for W32X86/3 if necessary; maybe we already have? */
2166 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2167 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2170 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2171 /* no idea of the correct error here */
2172 free_a_printer_driver( info_win2k, 3 );
2173 status = WERR_ACCESS_DENIED;
2177 /* if we get to here, we now have 2 driver info structures to remove */
2178 /* remove the Win2k driver first*/
2180 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2181 free_a_printer_driver( info_win2k, 3 );
2183 /* this should not have failed---if it did, report to client */
2185 if ( !W_ERROR_IS_OK(status_win2k) )
2190 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2192 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2195 free_a_printer_driver( info, 3 );
2201 /****************************************************************************
2202 Internal routine for retreiving printerdata
2203 ***************************************************************************/
2205 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2206 const char *key, const char *value, uint32 *type, uint8 **data,
2207 uint32 *needed, uint32 in_size )
2209 REGISTRY_VALUE *val;
2212 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2213 return WERR_BADFILE;
2215 *type = regval_type( val );
2217 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2219 size = regval_size( val );
2221 /* copy the min(in_size, len) */
2224 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2226 /* special case for 0 length values */
2228 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2232 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2241 DEBUG(5,("get_printer_dataex: copy done\n"));
2246 /****************************************************************************
2247 Internal routine for removing printerdata
2248 ***************************************************************************/
2250 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2252 return delete_printer_data( printer->info_2, key, value );
2255 /****************************************************************************
2256 Internal routine for storing printerdata
2257 ***************************************************************************/
2259 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2260 uint32 type, uint8 *data, int real_len )
2262 delete_printer_data( printer->info_2, key, value );
2264 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2267 /********************************************************************
2268 GetPrinterData on a printer server Handle.
2269 ********************************************************************/
2271 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2275 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2277 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2279 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2285 if (!StrCaseCmp(value, "BeepEnabled")) {
2287 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2289 SIVAL(*data, 0, 0x00);
2294 if (!StrCaseCmp(value, "EventLog")) {
2296 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2298 /* formally was 0x1b */
2299 SIVAL(*data, 0, 0x0);
2304 if (!StrCaseCmp(value, "NetPopup")) {
2306 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2308 SIVAL(*data, 0, 0x00);
2313 if (!StrCaseCmp(value, "MajorVersion")) {
2315 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2318 /* Windows NT 4.0 seems to not allow uploading of drivers
2319 to a server that reports 0x3 as the MajorVersion.
2320 need to investigate more how Win2k gets around this .
2323 if ( RA_WINNT == get_remote_arch() )
2332 if (!StrCaseCmp(value, "MinorVersion")) {
2334 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2343 * uint32 size = 0x114
2345 * uint32 minor = [0|1]
2346 * uint32 build = [2195|2600]
2347 * extra unicode string = e.g. "Service Pack 3"
2349 if (!StrCaseCmp(value, "OSVersion")) {
2351 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2359 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2362 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2364 *needed = 2*(strlen(string)+1);
2365 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2367 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2369 /* it's done by hand ready to go on the wire */
2370 for (i=0; i<strlen(string); i++) {
2371 (*data)[2*i]=string[i];
2372 (*data)[2*i+1]='\0';
2377 if (!StrCaseCmp(value, "Architecture")) {
2378 pstring string="Windows NT x86";
2380 *needed = 2*(strlen(string)+1);
2381 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2383 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2384 for (i=0; i<strlen(string); i++) {
2385 (*data)[2*i]=string[i];
2386 (*data)[2*i+1]='\0';
2391 if (!StrCaseCmp(value, "DsPresent")) {
2393 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2395 SIVAL(*data, 0, 0x01);
2400 if (!StrCaseCmp(value, "DNSMachineName")) {
2403 if (!get_myfullname(hostname))
2404 return WERR_BADFILE;
2406 *needed = 2*(strlen(hostname)+1);
2407 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2409 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2410 for (i=0; i<strlen(hostname); i++) {
2411 (*data)[2*i]=hostname[i];
2412 (*data)[2*i+1]='\0';
2418 return WERR_BADFILE;
2421 /********************************************************************
2422 * spoolss_getprinterdata
2423 ********************************************************************/
2425 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2427 POLICY_HND *handle = &q_u->handle;
2428 UNISTR2 *valuename = &q_u->valuename;
2429 uint32 in_size = q_u->size;
2430 uint32 *type = &r_u->type;
2431 uint32 *out_size = &r_u->size;
2432 uint8 **data = &r_u->data;
2433 uint32 *needed = &r_u->needed;
2436 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2437 NT_PRINTER_INFO_LEVEL *printer = NULL;
2441 * Reminder: when it's a string, the length is in BYTES
2442 * even if UNICODE is negociated.
2447 *out_size = in_size;
2449 /* in case of problem, return some default values */
2454 DEBUG(4,("_spoolss_getprinterdata\n"));
2457 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2458 status = WERR_BADFID;
2462 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2464 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2465 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2468 if ( !get_printer_snum(p,handle, &snum) ) {
2469 status = WERR_BADFID;
2473 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2474 if ( !W_ERROR_IS_OK(status) )
2477 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2479 if ( strequal(value, "ChangeId") ) {
2481 *needed = sizeof(uint32);
2482 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2483 status = WERR_NOMEM;
2486 SIVAL( *data, 0, printer->info_2->changeid );
2490 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2493 if (*needed > *out_size)
2494 status = WERR_MORE_DATA;
2497 if ( !W_ERROR_IS_OK(status) )
2499 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2501 /* reply this param doesn't exist */
2504 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2506 free_a_printer( &printer, 2 );
2515 /* cleanup & exit */
2518 free_a_printer( &printer, 2 );
2523 /*********************************************************
2524 Connect to the client machine.
2525 **********************************************************/
2527 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2528 struct in_addr *client_ip, const char *remote_machine)
2530 ZERO_STRUCTP(the_cli);
2532 if(cli_initialise(the_cli) == NULL) {
2533 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2537 if ( is_zero_ip(*client_ip) ) {
2538 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2539 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2540 cli_shutdown(the_cli);
2544 if (ismyip(the_cli->dest_ip)) {
2545 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2546 cli_shutdown(the_cli);
2551 the_cli->dest_ip.s_addr = client_ip->s_addr;
2552 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2553 inet_ntoa(*client_ip) ));
2556 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2557 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) ));
2558 cli_shutdown(the_cli);
2562 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2563 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2565 cli_shutdown(the_cli);
2569 the_cli->protocol = PROTOCOL_NT1;
2571 if (!cli_negprot(the_cli)) {
2572 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2573 cli_shutdown(the_cli);
2577 if (the_cli->protocol != PROTOCOL_NT1) {
2578 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2579 cli_shutdown(the_cli);
2584 * Do an anonymous session setup.
2587 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2588 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2589 cli_shutdown(the_cli);
2593 if (!(the_cli->sec_mode & 1)) {
2594 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2595 cli_shutdown(the_cli);
2599 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2600 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) ));
2601 cli_shutdown(the_cli);
2606 * Ok - we have an anonymous connection to the IPC$ share.
2607 * Now start the NT Domain stuff :-).
2610 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2611 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)));
2612 cli_nt_session_close(the_cli);
2613 cli_ulogoff(the_cli);
2614 cli_shutdown(the_cli);
2621 /***************************************************************************
2622 Connect to the client.
2623 ****************************************************************************/
2625 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2626 uint32 localprinter, uint32 type,
2627 POLICY_HND *handle, struct in_addr *client_ip)
2632 * If it's the first connection, contact the client
2633 * and connect to the IPC$ share anonymously
2635 if (smb_connections==0) {
2636 fstring unix_printer;
2638 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2640 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2643 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2644 /* Tell the connections db we're now interested in printer
2645 * notify messages. */
2646 register_message_flags( True, FLAG_MSG_PRINTING );
2650 * Tell the specific printing tdb we want messages for this printer
2651 * by registering our PID.
2654 if (!print_notify_register_pid(snum))
2655 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2659 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2662 if (!W_ERROR_IS_OK(result))
2663 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2664 dos_errstr(result)));
2666 return (W_ERROR_IS_OK(result));
2669 /********************************************************************
2671 * ReplyFindFirstPrinterChangeNotifyEx
2673 * before replying OK: status=0 a rpc call is made to the workstation
2674 * asking ReplyOpenPrinter
2676 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2677 * called from api_spoolss_rffpcnex
2678 ********************************************************************/
2680 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2682 POLICY_HND *handle = &q_u->handle;
2683 uint32 flags = q_u->flags;
2684 uint32 options = q_u->options;
2685 UNISTR2 *localmachine = &q_u->localmachine;
2686 uint32 printerlocal = q_u->printerlocal;
2688 SPOOL_NOTIFY_OPTION *option = q_u->option;
2689 struct in_addr client_ip;
2691 /* store the notify value in the printer struct */
2693 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2696 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2700 Printer->notify.flags=flags;
2701 Printer->notify.options=options;
2702 Printer->notify.printerlocal=printerlocal;
2704 if (Printer->notify.option)
2705 free_spool_notify_option(&Printer->notify.option);
2707 Printer->notify.option=dup_spool_notify_option(option);
2709 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2710 sizeof(Printer->notify.localmachine)-1);
2712 /* Connect to the client machine and send a ReplyOpenPrinter */
2714 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2716 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2717 !get_printer_snum(p, handle, &snum) )
2720 client_ip.s_addr = inet_addr(p->conn->client_address);
2722 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2723 Printer->notify.printerlocal, 1,
2724 &Printer->notify.client_hnd, &client_ip))
2725 return WERR_SERVER_UNAVAILABLE;
2727 Printer->notify.client_connected=True;
2732 /*******************************************************************
2733 * fill a notify_info_data with the servername
2734 ********************************************************************/
2736 void spoolss_notify_server_name(int snum,
2737 SPOOL_NOTIFY_INFO_DATA *data,
2738 print_queue_struct *queue,
2739 NT_PRINTER_INFO_LEVEL *printer,
2740 TALLOC_CTX *mem_ctx)
2742 pstring temp_name, temp;
2745 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2747 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2749 data->notify_data.data.length = len;
2750 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2752 if (!data->notify_data.data.string) {
2753 data->notify_data.data.length = 0;
2757 memcpy(data->notify_data.data.string, temp, len);
2760 /*******************************************************************
2761 * fill a notify_info_data with the printername (not including the servername).
2762 ********************************************************************/
2764 void spoolss_notify_printer_name(int snum,
2765 SPOOL_NOTIFY_INFO_DATA *data,
2766 print_queue_struct *queue,
2767 NT_PRINTER_INFO_LEVEL *printer,
2768 TALLOC_CTX *mem_ctx)
2773 /* the notify name should not contain the \\server\ part */
2774 char *p = strrchr(printer->info_2->printername, '\\');
2777 p = printer->info_2->printername;
2782 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2784 data->notify_data.data.length = len;
2785 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2787 if (!data->notify_data.data.string) {
2788 data->notify_data.data.length = 0;
2792 memcpy(data->notify_data.data.string, temp, len);
2795 /*******************************************************************
2796 * fill a notify_info_data with the servicename
2797 ********************************************************************/
2799 void spoolss_notify_share_name(int snum,
2800 SPOOL_NOTIFY_INFO_DATA *data,
2801 print_queue_struct *queue,
2802 NT_PRINTER_INFO_LEVEL *printer,
2803 TALLOC_CTX *mem_ctx)
2808 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2810 data->notify_data.data.length = len;
2811 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2813 if (!data->notify_data.data.string) {
2814 data->notify_data.data.length = 0;
2818 memcpy(data->notify_data.data.string, temp, len);
2821 /*******************************************************************
2822 * fill a notify_info_data with the port name
2823 ********************************************************************/
2825 void spoolss_notify_port_name(int snum,
2826 SPOOL_NOTIFY_INFO_DATA *data,
2827 print_queue_struct *queue,
2828 NT_PRINTER_INFO_LEVEL *printer,
2829 TALLOC_CTX *mem_ctx)
2834 /* even if it's strange, that's consistant in all the code */
2836 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2838 data->notify_data.data.length = len;
2839 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2841 if (!data->notify_data.data.string) {
2842 data->notify_data.data.length = 0;
2846 memcpy(data->notify_data.data.string, temp, len);
2849 /*******************************************************************
2850 * fill a notify_info_data with the printername
2851 * but it doesn't exist, have to see what to do
2852 ********************************************************************/
2854 void spoolss_notify_driver_name(int snum,
2855 SPOOL_NOTIFY_INFO_DATA *data,
2856 print_queue_struct *queue,
2857 NT_PRINTER_INFO_LEVEL *printer,
2858 TALLOC_CTX *mem_ctx)
2863 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2865 data->notify_data.data.length = len;
2866 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2868 if (!data->notify_data.data.string) {
2869 data->notify_data.data.length = 0;
2873 memcpy(data->notify_data.data.string, temp, len);
2876 /*******************************************************************
2877 * fill a notify_info_data with the comment
2878 ********************************************************************/
2880 void spoolss_notify_comment(int snum,
2881 SPOOL_NOTIFY_INFO_DATA *data,
2882 print_queue_struct *queue,
2883 NT_PRINTER_INFO_LEVEL *printer,
2884 TALLOC_CTX *mem_ctx)
2889 if (*printer->info_2->comment == '\0')
2890 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2892 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2894 data->notify_data.data.length = len;
2895 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2897 if (!data->notify_data.data.string) {
2898 data->notify_data.data.length = 0;
2902 memcpy(data->notify_data.data.string, temp, len);
2905 /*******************************************************************
2906 * fill a notify_info_data with the comment
2907 * location = "Room 1, floor 2, building 3"
2908 ********************************************************************/
2910 void spoolss_notify_location(int snum,
2911 SPOOL_NOTIFY_INFO_DATA *data,
2912 print_queue_struct *queue,
2913 NT_PRINTER_INFO_LEVEL *printer,
2914 TALLOC_CTX *mem_ctx)
2919 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2921 data->notify_data.data.length = len;
2922 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2924 if (!data->notify_data.data.string) {
2925 data->notify_data.data.length = 0;
2929 memcpy(data->notify_data.data.string, temp, len);
2932 /*******************************************************************
2933 * fill a notify_info_data with the device mode
2934 * jfm:xxxx don't to it for know but that's a real problem !!!
2935 ********************************************************************/
2937 static void spoolss_notify_devmode(int snum,
2938 SPOOL_NOTIFY_INFO_DATA *data,
2939 print_queue_struct *queue,
2940 NT_PRINTER_INFO_LEVEL *printer,
2941 TALLOC_CTX *mem_ctx)
2945 /*******************************************************************
2946 * fill a notify_info_data with the separator file name
2947 ********************************************************************/
2949 void spoolss_notify_sepfile(int snum,
2950 SPOOL_NOTIFY_INFO_DATA *data,
2951 print_queue_struct *queue,
2952 NT_PRINTER_INFO_LEVEL *printer,
2953 TALLOC_CTX *mem_ctx)
2958 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2960 data->notify_data.data.length = len;
2961 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2963 if (!data->notify_data.data.string) {
2964 data->notify_data.data.length = 0;
2968 memcpy(data->notify_data.data.string, temp, len);
2971 /*******************************************************************
2972 * fill a notify_info_data with the print processor
2973 * jfm:xxxx return always winprint to indicate we don't do anything to it
2974 ********************************************************************/
2976 void spoolss_notify_print_processor(int snum,
2977 SPOOL_NOTIFY_INFO_DATA *data,
2978 print_queue_struct *queue,
2979 NT_PRINTER_INFO_LEVEL *printer,
2980 TALLOC_CTX *mem_ctx)
2985 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2987 data->notify_data.data.length = len;
2988 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2990 if (!data->notify_data.data.string) {
2991 data->notify_data.data.length = 0;
2995 memcpy(data->notify_data.data.string, temp, len);
2998 /*******************************************************************
2999 * fill a notify_info_data with the print processor options
3000 * jfm:xxxx send an empty string
3001 ********************************************************************/
3003 void spoolss_notify_parameters(int snum,
3004 SPOOL_NOTIFY_INFO_DATA *data,
3005 print_queue_struct *queue,
3006 NT_PRINTER_INFO_LEVEL *printer,
3007 TALLOC_CTX *mem_ctx)
3012 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3014 data->notify_data.data.length = len;
3015 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3017 if (!data->notify_data.data.string) {
3018 data->notify_data.data.length = 0;
3022 memcpy(data->notify_data.data.string, temp, len);
3025 /*******************************************************************
3026 * fill a notify_info_data with the data type
3027 * jfm:xxxx always send RAW as data type
3028 ********************************************************************/
3030 void spoolss_notify_datatype(int snum,
3031 SPOOL_NOTIFY_INFO_DATA *data,
3032 print_queue_struct *queue,
3033 NT_PRINTER_INFO_LEVEL *printer,
3034 TALLOC_CTX *mem_ctx)
3039 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3041 data->notify_data.data.length = len;
3042 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3044 if (!data->notify_data.data.string) {
3045 data->notify_data.data.length = 0;
3049 memcpy(data->notify_data.data.string, temp, len);
3052 /*******************************************************************
3053 * fill a notify_info_data with the security descriptor
3054 * jfm:xxxx send an null pointer to say no security desc
3055 * have to implement security before !
3056 ********************************************************************/
3058 static void spoolss_notify_security_desc(int snum,
3059 SPOOL_NOTIFY_INFO_DATA *data,
3060 print_queue_struct *queue,
3061 NT_PRINTER_INFO_LEVEL *printer,
3062 TALLOC_CTX *mem_ctx)
3064 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3065 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3068 /*******************************************************************
3069 * fill a notify_info_data with the attributes
3070 * jfm:xxxx a samba printer is always shared
3071 ********************************************************************/
3073 void spoolss_notify_attributes(int snum,
3074 SPOOL_NOTIFY_INFO_DATA *data,
3075 print_queue_struct *queue,
3076 NT_PRINTER_INFO_LEVEL *printer,
3077 TALLOC_CTX *mem_ctx)
3079 data->notify_data.value[0] = printer->info_2->attributes;
3080 data->notify_data.value[1] = 0;
3083 /*******************************************************************
3084 * fill a notify_info_data with the priority
3085 ********************************************************************/
3087 static void spoolss_notify_priority(int snum,
3088 SPOOL_NOTIFY_INFO_DATA *data,
3089 print_queue_struct *queue,
3090 NT_PRINTER_INFO_LEVEL *printer,
3091 TALLOC_CTX *mem_ctx)
3093 data->notify_data.value[0] = printer->info_2->priority;
3094 data->notify_data.value[1] = 0;
3097 /*******************************************************************
3098 * fill a notify_info_data with the default priority
3099 ********************************************************************/
3101 static void spoolss_notify_default_priority(int snum,
3102 SPOOL_NOTIFY_INFO_DATA *data,
3103 print_queue_struct *queue,
3104 NT_PRINTER_INFO_LEVEL *printer,
3105 TALLOC_CTX *mem_ctx)
3107 data->notify_data.value[0] = printer->info_2->default_priority;
3108 data->notify_data.value[1] = 0;
3111 /*******************************************************************
3112 * fill a notify_info_data with the start time
3113 ********************************************************************/
3115 static void spoolss_notify_start_time(int snum,
3116 SPOOL_NOTIFY_INFO_DATA *data,
3117 print_queue_struct *queue,
3118 NT_PRINTER_INFO_LEVEL *printer,
3119 TALLOC_CTX *mem_ctx)
3121 data->notify_data.value[0] = printer->info_2->starttime;
3122 data->notify_data.value[1] = 0;
3125 /*******************************************************************
3126 * fill a notify_info_data with the until time
3127 ********************************************************************/
3129 static void spoolss_notify_until_time(int snum,
3130 SPOOL_NOTIFY_INFO_DATA *data,
3131 print_queue_struct *queue,
3132 NT_PRINTER_INFO_LEVEL *printer,
3133 TALLOC_CTX *mem_ctx)
3135 data->notify_data.value[0] = printer->info_2->untiltime;
3136 data->notify_data.value[1] = 0;
3139 /*******************************************************************
3140 * fill a notify_info_data with the status
3141 ********************************************************************/
3143 static void spoolss_notify_status(int snum,
3144 SPOOL_NOTIFY_INFO_DATA *data,
3145 print_queue_struct *queue,
3146 NT_PRINTER_INFO_LEVEL *printer,
3147 TALLOC_CTX *mem_ctx)
3149 print_status_struct status;
3151 print_queue_length(snum, &status);
3152 data->notify_data.value[0]=(uint32) status.status;
3153 data->notify_data.value[1] = 0;
3156 /*******************************************************************
3157 * fill a notify_info_data with the number of jobs queued
3158 ********************************************************************/
3160 void spoolss_notify_cjobs(int snum,
3161 SPOOL_NOTIFY_INFO_DATA *data,
3162 print_queue_struct *queue,
3163 NT_PRINTER_INFO_LEVEL *printer,
3164 TALLOC_CTX *mem_ctx)
3166 data->notify_data.value[0] = print_queue_length(snum, NULL);
3167 data->notify_data.value[1] = 0;
3170 /*******************************************************************
3171 * fill a notify_info_data with the average ppm
3172 ********************************************************************/
3174 static void spoolss_notify_average_ppm(int snum,
3175 SPOOL_NOTIFY_INFO_DATA *data,
3176 print_queue_struct *queue,
3177 NT_PRINTER_INFO_LEVEL *printer,
3178 TALLOC_CTX *mem_ctx)
3180 /* always respond 8 pages per minutes */
3181 /* a little hard ! */
3182 data->notify_data.value[0] = printer->info_2->averageppm;
3183 data->notify_data.value[1] = 0;
3186 /*******************************************************************
3187 * fill a notify_info_data with username
3188 ********************************************************************/
3190 static void spoolss_notify_username(int snum,
3191 SPOOL_NOTIFY_INFO_DATA *data,
3192 print_queue_struct *queue,
3193 NT_PRINTER_INFO_LEVEL *printer,
3194 TALLOC_CTX *mem_ctx)
3199 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3201 data->notify_data.data.length = len;
3202 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3204 if (!data->notify_data.data.string) {
3205 data->notify_data.data.length = 0;
3209 memcpy(data->notify_data.data.string, temp, len);
3212 /*******************************************************************
3213 * fill a notify_info_data with job status
3214 ********************************************************************/
3216 static void spoolss_notify_job_status(int snum,
3217 SPOOL_NOTIFY_INFO_DATA *data,
3218 print_queue_struct *queue,
3219 NT_PRINTER_INFO_LEVEL *printer,
3220 TALLOC_CTX *mem_ctx)
3222 data->notify_data.value[0]=nt_printj_status(queue->status);
3223 data->notify_data.value[1] = 0;
3226 /*******************************************************************
3227 * fill a notify_info_data with job name
3228 ********************************************************************/
3230 static void spoolss_notify_job_name(int snum,
3231 SPOOL_NOTIFY_INFO_DATA *data,
3232 print_queue_struct *queue,
3233 NT_PRINTER_INFO_LEVEL *printer,
3234 TALLOC_CTX *mem_ctx)
3239 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3241 data->notify_data.data.length = len;
3242 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3244 if (!data->notify_data.data.string) {
3245 data->notify_data.data.length = 0;
3249 memcpy(data->notify_data.data.string, temp, len);
3252 /*******************************************************************
3253 * fill a notify_info_data with job status
3254 ********************************************************************/
3256 static void spoolss_notify_job_status_string(int snum,
3257 SPOOL_NOTIFY_INFO_DATA *data,
3258 print_queue_struct *queue,
3259 NT_PRINTER_INFO_LEVEL *printer,
3260 TALLOC_CTX *mem_ctx)
3263 * Now we're returning job status codes we just return a "" here. JRA.
3270 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3273 switch (queue->status) {
3278 p = ""; /* NT provides the paused string */
3287 #endif /* NO LONGER NEEDED. */
3289 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3291 data->notify_data.data.length = len;
3292 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3294 if (!data->notify_data.data.string) {
3295 data->notify_data.data.length = 0;
3299 memcpy(data->notify_data.data.string, temp, len);
3302 /*******************************************************************
3303 * fill a notify_info_data with job time
3304 ********************************************************************/
3306 static void spoolss_notify_job_time(int snum,
3307 SPOOL_NOTIFY_INFO_DATA *data,
3308 print_queue_struct *queue,
3309 NT_PRINTER_INFO_LEVEL *printer,
3310 TALLOC_CTX *mem_ctx)
3312 data->notify_data.value[0]=0x0;
3313 data->notify_data.value[1]=0;
3316 /*******************************************************************
3317 * fill a notify_info_data with job size
3318 ********************************************************************/
3320 static void spoolss_notify_job_size(int snum,
3321 SPOOL_NOTIFY_INFO_DATA *data,
3322 print_queue_struct *queue,
3323 NT_PRINTER_INFO_LEVEL *printer,
3324 TALLOC_CTX *mem_ctx)
3326 data->notify_data.value[0]=queue->size;
3327 data->notify_data.value[1]=0;
3330 /*******************************************************************
3331 * fill a notify_info_data with page info
3332 ********************************************************************/
3333 static void spoolss_notify_total_pages(int snum,
3334 SPOOL_NOTIFY_INFO_DATA *data,
3335 print_queue_struct *queue,
3336 NT_PRINTER_INFO_LEVEL *printer,
3337 TALLOC_CTX *mem_ctx)
3339 data->notify_data.value[0]=queue->page_count;
3340 data->notify_data.value[1]=0;
3343 /*******************************************************************
3344 * fill a notify_info_data with pages printed info.
3345 ********************************************************************/
3346 static void spoolss_notify_pages_printed(int snum,
3347 SPOOL_NOTIFY_INFO_DATA *data,
3348 print_queue_struct *queue,
3349 NT_PRINTER_INFO_LEVEL *printer,
3350 TALLOC_CTX *mem_ctx)
3352 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3353 data->notify_data.value[1]=0;
3356 /*******************************************************************
3357 Fill a notify_info_data with job position.
3358 ********************************************************************/
3360 static void spoolss_notify_job_position(int snum,
3361 SPOOL_NOTIFY_INFO_DATA *data,
3362 print_queue_struct *queue,
3363 NT_PRINTER_INFO_LEVEL *printer,
3364 TALLOC_CTX *mem_ctx)
3366 data->notify_data.value[0]=queue->job;
3367 data->notify_data.value[1]=0;
3370 /*******************************************************************
3371 Fill a notify_info_data with submitted time.
3372 ********************************************************************/
3374 static void spoolss_notify_submitted_time(int snum,
3375 SPOOL_NOTIFY_INFO_DATA *data,
3376 print_queue_struct *queue,
3377 NT_PRINTER_INFO_LEVEL *printer,
3378 TALLOC_CTX *mem_ctx)
3385 t=gmtime(&queue->time);
3387 len = sizeof(SYSTEMTIME);
3389 data->notify_data.data.length = len;
3390 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3392 if (!data->notify_data.data.string) {
3393 data->notify_data.data.length = 0;
3397 make_systemtime(&st, t);
3400 * Systemtime must be linearized as a set of UINT16's.
3401 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3404 p = (char *)data->notify_data.data.string;
3405 SSVAL(p, 0, st.year);
3406 SSVAL(p, 2, st.month);
3407 SSVAL(p, 4, st.dayofweek);
3408 SSVAL(p, 6, st.day);
3409 SSVAL(p, 8, st.hour);
3410 SSVAL(p, 10, st.minute);
3411 SSVAL(p, 12, st.second);
3412 SSVAL(p, 14, st.milliseconds);
3415 struct s_notify_info_data_table
3421 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3422 print_queue_struct *queue,
3423 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3426 /* A table describing the various print notification constants and
3427 whether the notification data is a pointer to a variable sized
3428 buffer, a one value uint32 or a two value uint32. */
3430 static const struct s_notify_info_data_table notify_info_data_table[] =
3432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3458 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3463 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3483 /*******************************************************************
3484 Return the size of info_data structure.
3485 ********************************************************************/
3487 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3491 for (i = 0; i < sizeof(notify_info_data_table); i++)
3493 if ( (notify_info_data_table[i].type == type)
3494 && (notify_info_data_table[i].field == field) )
3496 switch(notify_info_data_table[i].size)
3498 case NOTIFY_ONE_VALUE:
3499 case NOTIFY_TWO_VALUE:
3504 /* The only pointer notify data I have seen on
3505 the wire is the submitted time and this has
3506 the notify size set to 4. -tpot */
3508 case NOTIFY_POINTER:
3511 case NOTIFY_SECDESC:
3517 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3522 /*******************************************************************
3523 Return the type of notify_info_data.
3524 ********************************************************************/
3526 static int type_of_notify_info_data(uint16 type, uint16 field)
3530 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3531 if (notify_info_data_table[i].type == type &&
3532 notify_info_data_table[i].field == field)
3533 return notify_info_data_table[i].size;
3539 /****************************************************************************
3540 ****************************************************************************/
3542 static int search_notify(uint16 type, uint16 field, int *value)
3546 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3547 if (notify_info_data_table[i].type == type &&
3548 notify_info_data_table[i].field == field &&
3549 notify_info_data_table[i].fn != NULL) {
3558 /****************************************************************************
3559 ****************************************************************************/
3561 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3563 info_data->type = type;
3564 info_data->field = field;
3565 info_data->reserved = 0;
3567 info_data->size = size_of_notify_info_data(type, field);
3568 info_data->enc_type = type_of_notify_info_data(type, field);
3575 /*******************************************************************
3577 * fill a notify_info struct with info asked
3579 ********************************************************************/
3581 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3582 snum, SPOOL_NOTIFY_OPTION_TYPE
3583 *option_type, uint32 id,
3584 TALLOC_CTX *mem_ctx)
3590 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3591 NT_PRINTER_INFO_LEVEL *printer = NULL;
3592 print_queue_struct *queue=NULL;
3594 type=option_type->type;
3596 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3597 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3598 option_type->count, lp_servicename(snum)));
3600 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3603 for(field_num=0; field_num<option_type->count; field_num++) {
3604 field = option_type->fields[field_num];
3606 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3608 if (!search_notify(type, field, &j) )
3611 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3612 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3617 current_data = &info->data[info->count];
3619 construct_info_data(current_data, type, field, id);
3621 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3622 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3624 notify_info_data_table[j].fn(snum, current_data, queue,
3630 free_a_printer(&printer, 2);
3634 /*******************************************************************
3636 * fill a notify_info struct with info asked
3638 ********************************************************************/
3640 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3641 SPOOL_NOTIFY_INFO *info,
3642 NT_PRINTER_INFO_LEVEL *printer,
3643 int snum, SPOOL_NOTIFY_OPTION_TYPE
3644 *option_type, uint32 id,
3645 TALLOC_CTX *mem_ctx)
3651 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3653 DEBUG(4,("construct_notify_jobs_info\n"));
3655 type = option_type->type;
3657 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3658 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3659 option_type->count));
3661 for(field_num=0; field_num<option_type->count; field_num++) {
3662 field = option_type->fields[field_num];
3664 if (!search_notify(type, field, &j) )
3667 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3668 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3671 else info->data = tid;
3673 current_data=&(info->data[info->count]);
3675 construct_info_data(current_data, type, field, id);
3676 notify_info_data_table[j].fn(snum, current_data, queue,
3685 * JFM: The enumeration is not that simple, it's even non obvious.
3687 * let's take an example: I want to monitor the PRINTER SERVER for
3688 * the printer's name and the number of jobs currently queued.
3689 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3690 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3692 * I have 3 printers on the back of my server.
3694 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3697 * 1 printer 1 name 1
3698 * 2 printer 1 cjob 1
3699 * 3 printer 2 name 2
3700 * 4 printer 2 cjob 2
3701 * 5 printer 3 name 3
3702 * 6 printer 3 name 3
3704 * that's the print server case, the printer case is even worse.
3707 /*******************************************************************
3709 * enumerate all printers on the printserver
3710 * fill a notify_info struct with info asked
3712 ********************************************************************/
3714 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3715 SPOOL_NOTIFY_INFO *info,
3716 TALLOC_CTX *mem_ctx)
3719 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3720 int n_services=lp_numservices();
3723 SPOOL_NOTIFY_OPTION *option;
3724 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3726 DEBUG(4,("printserver_notify_info\n"));
3731 option=Printer->notify.option;
3737 for (i=0; i<option->count; i++) {
3738 option_type=&(option->ctr.type[i]);
3740 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3743 for (snum=0; snum<n_services; snum++)
3745 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3746 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3752 * Debugging information, don't delete.
3755 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3756 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3757 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3759 for (i=0; i<info->count; i++) {
3760 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3761 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3762 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3769 /*******************************************************************
3771 * fill a notify_info struct with info asked
3773 ********************************************************************/
3775 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3776 TALLOC_CTX *mem_ctx)
3779 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3782 SPOOL_NOTIFY_OPTION *option;
3783 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3785 print_queue_struct *queue=NULL;
3786 print_status_struct status;
3788 DEBUG(4,("printer_notify_info\n"));
3793 option=Printer->notify.option;
3799 get_printer_snum(p, hnd, &snum);
3801 for (i=0; i<option->count; i++) {
3802 option_type=&option->ctr.type[i];
3804 switch ( option_type->type ) {
3805 case PRINTER_NOTIFY_TYPE:
3806 if(construct_notify_printer_info(Printer, info, snum,
3812 case JOB_NOTIFY_TYPE: {
3813 NT_PRINTER_INFO_LEVEL *printer = NULL;
3815 count = print_queue_status(snum, &queue, &status);
3817 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3820 for (j=0; j<count; j++) {
3821 construct_notify_jobs_info(&queue[j], info,
3828 free_a_printer(&printer, 2);
3838 * Debugging information, don't delete.
3841 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3842 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3843 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3845 for (i=0; i<info->count; i++) {
3846 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3847 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3848 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3854 /********************************************************************
3856 ********************************************************************/
3858 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3860 POLICY_HND *handle = &q_u->handle;
3861 SPOOL_NOTIFY_INFO *info = &r_u->info;
3863 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3864 WERROR result = WERR_BADFID;
3866 /* we always have a NOTIFY_INFO struct */
3870 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3871 OUR_HANDLE(handle)));
3875 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3878 * We are now using the change value, and
3879 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3880 * I don't have a global notification system, I'm sending back all the
3881 * informations even when _NOTHING_ has changed.
3884 /* We need to keep track of the change value to send back in
3885 RRPCN replies otherwise our updates are ignored. */
3887 Printer->notify.fnpcn = True;
3889 if (Printer->notify.client_connected) {
3890 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3891 Printer->notify.change = q_u->change;
3894 /* just ignore the SPOOL_NOTIFY_OPTION */
3896 switch (Printer->printer_type) {
3897 case PRINTER_HANDLE_IS_PRINTSERVER:
3898 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3901 case PRINTER_HANDLE_IS_PRINTER:
3902 result = printer_notify_info(p, handle, info, p->mem_ctx);
3906 Printer->notify.fnpcn = False;
3912 /********************************************************************
3913 * construct_printer_info_0
3914 * fill a printer_info_0 struct
3915 ********************************************************************/
3917 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3921 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3922 counter_printer_0 *session_counter;
3923 uint32 global_counter;
3926 print_status_struct status;
3928 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3931 count = print_queue_length(snum, &status);
3933 /* check if we already have a counter for this printer */
3934 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3936 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3937 if (session_counter->snum == snum)
3941 /* it's the first time, add it to the list */
3942 if (session_counter==NULL) {
3943 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3944 free_a_printer(&ntprinter, 2);
3947 ZERO_STRUCTP(session_counter);
3948 session_counter->snum=snum;
3949 session_counter->counter=0;
3950 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3954 session_counter->counter++;
3957 * the global_counter should be stored in a TDB as it's common to all the clients
3958 * and should be zeroed on samba startup
3960 global_counter=session_counter->counter;
3962 pstrcpy(chaine,ntprinter->info_2->printername);
3964 init_unistr(&printer->printername, chaine);
3966 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3967 init_unistr(&printer->servername, chaine);
3969 printer->cjobs = count;
3970 printer->total_jobs = 0;
3971 printer->total_bytes = 0;
3973 setuptime = (time_t)ntprinter->info_2->setuptime;
3974 t=gmtime(&setuptime);
3976 printer->year = t->tm_year+1900;
3977 printer->month = t->tm_mon+1;
3978 printer->dayofweek = t->tm_wday;
3979 printer->day = t->tm_mday;
3980 printer->hour = t->tm_hour;
3981 printer->minute = t->tm_min;
3982 printer->second = t->tm_sec;
3983 printer->milliseconds = 0;
3985 printer->global_counter = global_counter;
3986 printer->total_pages = 0;
3988 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3989 printer->major_version = 0x0005; /* NT 5 */
3990 printer->build_version = 0x0893; /* build 2195 */
3992 printer->unknown7 = 0x1;
3993 printer->unknown8 = 0x0;
3994 printer->unknown9 = 0x0;
3995 printer->session_counter = session_counter->counter;
3996 printer->unknown11 = 0x0;
3997 printer->printer_errors = 0x0; /* number of print failure */
3998 printer->unknown13 = 0x0;
3999 printer->unknown14 = 0x1;
4000 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4001 printer->unknown16 = 0x0;
4002 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4003 printer->unknown18 = 0x0;
4004 printer->status = nt_printq_status(status.status);
4005 printer->unknown20 = 0x0;
4006 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4007 printer->unknown22 = 0x0;
4008 printer->unknown23 = 0x6; /* 6 ???*/
4009 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4010 printer->unknown25 = 0;
4011 printer->unknown26 = 0;
4012 printer->unknown27 = 0;
4013 printer->unknown28 = 0;
4014 printer->unknown29 = 0;
4016 free_a_printer(&ntprinter,2);
4020 /********************************************************************
4021 * construct_printer_info_1
4022 * fill a printer_info_1 struct
4023 ********************************************************************/
4024 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4028 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4030 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4033 printer->flags=flags;
4035 if (*ntprinter->info_2->comment == '\0') {
4036 init_unistr(&printer->comment, lp_comment(snum));
4037 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4038 ntprinter->info_2->drivername, lp_comment(snum));
4041 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4042 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4043 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4046 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4048 init_unistr(&printer->description, chaine);
4049 init_unistr(&printer->name, chaine2);
4051 free_a_printer(&ntprinter,2);
4056 /****************************************************************************
4057 Free a DEVMODE struct.
4058 ****************************************************************************/
4060 static void free_dev_mode(DEVICEMODE *dev)
4065 SAFE_FREE(dev->private);
4070 /****************************************************************************
4071 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4072 should be valid upon entry
4073 ****************************************************************************/
4075 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4077 if ( !devmode || !ntdevmode )
4080 init_unistr(&devmode->devicename, ntdevmode->devicename);
4082 init_unistr(&devmode->formname, ntdevmode->formname);
4084 devmode->specversion = ntdevmode->specversion;
4085 devmode->driverversion = ntdevmode->driverversion;
4086 devmode->size = ntdevmode->size;
4087 devmode->driverextra = ntdevmode->driverextra;
4088 devmode->fields = ntdevmode->fields;
4090 devmode->orientation = ntdevmode->orientation;
4091 devmode->papersize = ntdevmode->papersize;
4092 devmode->paperlength = ntdevmode->paperlength;
4093 devmode->paperwidth = ntdevmode->paperwidth;
4094 devmode->scale = ntdevmode->scale;
4095 devmode->copies = ntdevmode->copies;
4096 devmode->defaultsource = ntdevmode->defaultsource;
4097 devmode->printquality = ntdevmode->printquality;
4098 devmode->color = ntdevmode->color;
4099 devmode->duplex = ntdevmode->duplex;
4100 devmode->yresolution = ntdevmode->yresolution;
4101 devmode->ttoption = ntdevmode->ttoption;
4102 devmode->collate = ntdevmode->collate;
4103 devmode->icmmethod = ntdevmode->icmmethod;
4104 devmode->icmintent = ntdevmode->icmintent;
4105 devmode->mediatype = ntdevmode->mediatype;
4106 devmode->dithertype = ntdevmode->dithertype;
4108 if (ntdevmode->private != NULL) {
4109 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4116 /****************************************************************************
4117 Create a DEVMODE struct. Returns malloced memory.
4118 ****************************************************************************/
4120 DEVICEMODE *construct_dev_mode(int snum)
4122 NT_PRINTER_INFO_LEVEL *printer = NULL;
4123 DEVICEMODE *devmode = NULL;
4125 DEBUG(7,("construct_dev_mode\n"));
4127 DEBUGADD(8,("getting printer characteristics\n"));
4129 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4132 if ( !printer->info_2->devmode ) {
4133 DEBUG(5, ("BONG! There was no device mode!\n"));
4137 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4138 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4142 ZERO_STRUCTP(devmode);
4144 DEBUGADD(8,("loading DEVICEMODE\n"));
4146 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4147 free_dev_mode( devmode );
4152 free_a_printer(&printer,2);
4157 /********************************************************************
4158 * construct_printer_info_2
4159 * fill a printer_info_2 struct
4160 ********************************************************************/
4162 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4165 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4167 print_status_struct status;
4169 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4172 count = print_queue_length(snum, &status);
4174 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4175 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4176 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4177 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4178 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4180 if (*ntprinter->info_2->comment == '\0')
4181 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4183 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4185 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4186 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4187 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4188 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4189 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4191 printer->attributes = ntprinter->info_2->attributes;
4193 printer->priority = ntprinter->info_2->priority; /* priority */
4194 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4195 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4196 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4197 printer->status = nt_printq_status(status.status); /* status */
4198 printer->cjobs = count; /* jobs */
4199 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4201 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4202 DEBUG(8, ("Returning NULL Devicemode!\n"));
4205 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4206 /* steal the printer info sec_desc structure. [badly done]. */
4207 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4208 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4209 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4210 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4213 printer->secdesc = NULL;
4216 free_a_printer(&ntprinter, 2);
4220 /********************************************************************
4221 * construct_printer_info_3
4222 * fill a printer_info_3 struct
4223 ********************************************************************/
4225 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4227 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4228 PRINTER_INFO_3 *printer = NULL;
4230 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4234 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4235 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4239 ZERO_STRUCTP(printer);
4241 printer->flags = 4; /* These are the components of the SD we are returning. */
4242 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4243 /* steal the printer info sec_desc structure. [badly done]. */
4244 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4248 * Set the flags for the components we are returning.
4251 if (printer->secdesc->owner_sid)
4252 printer->flags |= OWNER_SECURITY_INFORMATION;
4254 if (printer->secdesc->grp_sid)
4255 printer->flags |= GROUP_SECURITY_INFORMATION;
4257 if (printer->secdesc->dacl)
4258 printer->flags |= DACL_SECURITY_INFORMATION;
4260 if (printer->secdesc->sacl)
4261 printer->flags |= SACL_SECURITY_INFORMATION;
4264 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4265 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4266 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4269 free_a_printer(&ntprinter, 2);
4271 *pp_printer = printer;
4275 /********************************************************************
4276 * construct_printer_info_4
4277 * fill a printer_info_4 struct
4278 ********************************************************************/
4280 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4282 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4284 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4287 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4288 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4289 printer->attributes = ntprinter->info_2->attributes;
4291 free_a_printer(&ntprinter, 2);
4295 /********************************************************************
4296 * construct_printer_info_5
4297 * fill a printer_info_5 struct
4298 ********************************************************************/
4300 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4302 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4304 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4307 init_unistr(&printer->printername, ntprinter->info_2->printername);
4308 init_unistr(&printer->portname, ntprinter->info_2->portname);
4309 printer->attributes = ntprinter->info_2->attributes;
4311 /* these two are not used by NT+ according to MSDN */
4313 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4314 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4316 free_a_printer(&ntprinter, 2);
4321 /********************************************************************
4322 * construct_printer_info_7
4323 * fill a printer_info_7 struct
4324 ********************************************************************/
4326 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4328 char *guid_str = NULL;
4331 if (is_printer_published(print_hnd, snum, &guid)) {
4332 asprintf(&guid_str, "{%s}", uuid_string_static(guid));
4334 init_unistr(&printer->guid, guid_str);
4335 printer->action = SPOOL_DS_PUBLISH;
4337 init_unistr(&printer->guid, "");
4338 printer->action = SPOOL_DS_UNPUBLISH;
4344 /********************************************************************
4345 Spoolss_enumprinters.
4346 ********************************************************************/
4348 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4352 int n_services=lp_numservices();
4353 PRINTER_INFO_1 *tp, *printers=NULL;
4354 PRINTER_INFO_1 current_prt;
4356 DEBUG(4,("enum_all_printers_info_1\n"));
4358 for (snum=0; snum<n_services; snum++) {
4359 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4360 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4362 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4363 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4364 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4365 SAFE_FREE(printers);
4370 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4372 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4378 /* check the required size. */
4379 for (i=0; i<*returned; i++)
4380 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4382 if (!alloc_buffer_size(buffer, *needed))
4383 return WERR_INSUFFICIENT_BUFFER;
4385 /* fill the buffer with the structures */
4386 for (i=0; i<*returned; i++)
4387 smb_io_printer_info_1("", buffer, &printers[i], 0);
4390 SAFE_FREE(printers);
4392 if (*needed > offered) {
4394 return WERR_INSUFFICIENT_BUFFER;
4400 /********************************************************************
4401 enum_all_printers_info_1_local.
4402 *********************************************************************/
4404 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4406 DEBUG(4,("enum_all_printers_info_1_local\n"));
4408 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4411 /********************************************************************
4412 enum_all_printers_info_1_name.
4413 *********************************************************************/
4415 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4419 DEBUG(4,("enum_all_printers_info_1_name\n"));
4421 if ((name[0] == '\\') && (name[1] == '\\'))
4424 if (is_myname_or_ipaddr(s)) {
4425 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4428 return WERR_INVALID_NAME;
4431 /********************************************************************
4432 enum_all_printers_info_1_remote.
4433 *********************************************************************/
4435 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4437 PRINTER_INFO_1 *printer;
4438 fstring printername;
4441 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4443 /* JFM: currently it's more a place holder than anything else.
4444 * In the spooler world there is a notion of server registration.
4445 * the print servers are registring (sp ?) on the PDC (in the same domain)
4447 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4450 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4455 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4456 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4457 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4459 init_unistr(&printer->description, desc);
4460 init_unistr(&printer->name, printername);
4461 init_unistr(&printer->comment, comment);
4462 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4464 /* check the required size. */
4465 *needed += spoolss_size_printer_info_1(printer);
4467 if (!alloc_buffer_size(buffer, *needed)) {
4469 return WERR_INSUFFICIENT_BUFFER;
4472 /* fill the buffer with the structures */
4473 smb_io_printer_info_1("", buffer, printer, 0);
4478 if (*needed > offered) {
4480 return WERR_INSUFFICIENT_BUFFER;
4486 /********************************************************************
4487 enum_all_printers_info_1_network.
4488 *********************************************************************/
4490 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4494 DEBUG(4,("enum_all_printers_info_1_network\n"));
4496 /* If we respond to a enum_printers level 1 on our name with flags
4497 set to PRINTER_ENUM_REMOTE with a list of printers then these
4498 printers incorrectly appear in the APW browse list.
4499 Specifically the printers for the server appear at the workgroup
4500 level where all the other servers in the domain are
4501 listed. Windows responds to this call with a
4502 WERR_CAN_NOT_COMPLETE so we should do the same. */
4504 if (name[0] == '\\' && name[1] == '\\')
4507 if (is_myname_or_ipaddr(s))
4508 return WERR_CAN_NOT_COMPLETE;
4510 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4513 /********************************************************************
4514 * api_spoolss_enumprinters
4516 * called from api_spoolss_enumprinters (see this to understand)
4517 ********************************************************************/
4519 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4523 int n_services=lp_numservices();
4524 PRINTER_INFO_2 *tp, *printers=NULL;
4525 PRINTER_INFO_2 current_prt;
4527 for (snum=0; snum<n_services; snum++) {
4528 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4529 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4531 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4532 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4533 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4534 SAFE_FREE(printers);
4539 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4540 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4546 /* check the required size. */
4547 for (i=0; i<*returned; i++)
4548 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4550 if (!alloc_buffer_size(buffer, *needed)) {
4551 for (i=0; i<*returned; i++) {
4552 free_devmode(printers[i].devmode);
4554 SAFE_FREE(printers);
4555 return WERR_INSUFFICIENT_BUFFER;
4558 /* fill the buffer with the structures */
4559 for (i=0; i<*returned; i++)
4560 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4563 for (i=0; i<*returned; i++) {
4564 free_devmode(printers[i].devmode);
4566 SAFE_FREE(printers);
4568 if (*needed > offered) {
4570 return WERR_INSUFFICIENT_BUFFER;
4576 /********************************************************************
4577 * handle enumeration of printers at level 1
4578 ********************************************************************/
4580 static WERROR enumprinters_level1( uint32 flags, fstring name,
4581 NEW_BUFFER *buffer, uint32 offered,
4582 uint32 *needed, uint32 *returned)
4584 /* Not all the flags are equals */
4586 if (flags & PRINTER_ENUM_LOCAL)
4587 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4589 if (flags & PRINTER_ENUM_NAME)
4590 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4592 if (flags & PRINTER_ENUM_REMOTE)
4593 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4595 if (flags & PRINTER_ENUM_NETWORK)
4596 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4598 return WERR_OK; /* NT4sp5 does that */
4601 /********************************************************************
4602 * handle enumeration of printers at level 2
4603 ********************************************************************/
4605 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4606 NEW_BUFFER *buffer, uint32 offered,
4607 uint32 *needed, uint32 *returned)
4609 char *s = servername;
4611 if (flags & PRINTER_ENUM_LOCAL) {
4612 return enum_all_printers_info_2(buffer, offered, needed, returned);
4615 if (flags & PRINTER_ENUM_NAME) {
4616 if ((servername[0] == '\\') && (servername[1] == '\\'))
4618 if (is_myname_or_ipaddr(s))
4619 return enum_all_printers_info_2(buffer, offered, needed, returned);
4621 return WERR_INVALID_NAME;
4624 if (flags & PRINTER_ENUM_REMOTE)
4625 return WERR_UNKNOWN_LEVEL;
4630 /********************************************************************
4631 * handle enumeration of printers at level 5
4632 ********************************************************************/
4634 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4635 NEW_BUFFER *buffer, uint32 offered,
4636 uint32 *needed, uint32 *returned)
4638 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4642 /********************************************************************
4643 * api_spoolss_enumprinters
4645 * called from api_spoolss_enumprinters (see this to understand)
4646 ********************************************************************/
4648 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4650 uint32 flags = q_u->flags;
4651 UNISTR2 *servername = &q_u->servername;
4652 uint32 level = q_u->level;
4653 NEW_BUFFER *buffer = NULL;
4654 uint32 offered = q_u->offered;
4655 uint32 *needed = &r_u->needed;
4656 uint32 *returned = &r_u->returned;
4660 /* that's an [in out] buffer */
4661 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4662 buffer = r_u->buffer;
4664 DEBUG(4,("_spoolss_enumprinters\n"));
4671 * flags==PRINTER_ENUM_NAME
4672 * if name=="" then enumerates all printers
4673 * if name!="" then enumerate the printer
4674 * flags==PRINTER_ENUM_REMOTE
4675 * name is NULL, enumerate printers
4676 * Level 2: name!="" enumerates printers, name can't be NULL
4677 * Level 3: doesn't exist
4678 * Level 4: does a local registry lookup
4679 * Level 5: same as Level 2
4682 unistr2_to_ascii(name, servername, sizeof(name)-1);
4687 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4689 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4691 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4696 return WERR_UNKNOWN_LEVEL;
4699 /****************************************************************************
4700 ****************************************************************************/
4702 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4704 PRINTER_INFO_0 *printer=NULL;
4706 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4709 construct_printer_info_0(print_hnd, printer, snum);
4711 /* check the required size. */
4712 *needed += spoolss_size_printer_info_0(printer);
4714 if (!alloc_buffer_size(buffer, *needed)) {
4716 return WERR_INSUFFICIENT_BUFFER;
4719 /* fill the buffer with the structures */
4720 smb_io_printer_info_0("", buffer, printer, 0);
4725 if (*needed > offered) {
4726 return WERR_INSUFFICIENT_BUFFER;
4732 /****************************************************************************
4733 ****************************************************************************/
4735 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4737 PRINTER_INFO_1 *printer=NULL;
4739 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4742 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4744 /* check the required size. */
4745 *needed += spoolss_size_printer_info_1(printer);
4747 if (!alloc_buffer_size(buffer, *needed)) {
4749 return WERR_INSUFFICIENT_BUFFER;
4752 /* fill the buffer with the structures */
4753 smb_io_printer_info_1("", buffer, printer, 0);
4758 if (*needed > offered) {
4759 return WERR_INSUFFICIENT_BUFFER;
4765 /****************************************************************************
4766 ****************************************************************************/
4768 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4770 PRINTER_INFO_2 *printer=NULL;
4772 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4775 construct_printer_info_2(print_hnd, printer, snum);
4777 /* check the required size. */
4778 *needed += spoolss_size_printer_info_2(printer);
4780 if (!alloc_buffer_size(buffer, *needed)) {
4781 free_printer_info_2(printer);
4782 return WERR_INSUFFICIENT_BUFFER;
4785 /* fill the buffer with the structures */
4786 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4787 free_printer_info_2(printer);
4792 free_printer_info_2(printer);
4794 if (*needed > offered) {
4795 return WERR_INSUFFICIENT_BUFFER;
4801 /****************************************************************************
4802 ****************************************************************************/
4804 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4806 PRINTER_INFO_3 *printer=NULL;
4808 if (!construct_printer_info_3(print_hnd, &printer, snum))
4811 /* check the required size. */
4812 *needed += spoolss_size_printer_info_3(printer);
4814 if (!alloc_buffer_size(buffer, *needed)) {
4815 free_printer_info_3(printer);
4816 return WERR_INSUFFICIENT_BUFFER;
4819 /* fill the buffer with the structures */
4820 smb_io_printer_info_3("", buffer, printer, 0);
4823 free_printer_info_3(printer);
4825 if (*needed > offered) {
4826 return WERR_INSUFFICIENT_BUFFER;
4832 /****************************************************************************
4833 ****************************************************************************/
4835 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4837 PRINTER_INFO_4 *printer=NULL;
4839 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4842 if (!construct_printer_info_4(print_hnd, printer, snum))
4845 /* check the required size. */
4846 *needed += spoolss_size_printer_info_4(printer);
4848 if (!alloc_buffer_size(buffer, *needed)) {
4849 free_printer_info_4(printer);
4850 return WERR_INSUFFICIENT_BUFFER;
4853 /* fill the buffer with the structures */
4854 smb_io_printer_info_4("", buffer, printer, 0);
4857 free_printer_info_4(printer);
4859 if (*needed > offered) {
4860 return WERR_INSUFFICIENT_BUFFER;
4866 /****************************************************************************
4867 ****************************************************************************/
4869 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4871 PRINTER_INFO_5 *printer=NULL;
4873 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4876 if (!construct_printer_info_5(print_hnd, printer, snum))
4879 /* check the required size. */
4880 *needed += spoolss_size_printer_info_5(printer);
4882 if (!alloc_buffer_size(buffer, *needed)) {
4883 free_printer_info_5(printer);
4884 return WERR_INSUFFICIENT_BUFFER;
4887 /* fill the buffer with the structures */
4888 smb_io_printer_info_5("", buffer, printer, 0);
4891 free_printer_info_5(printer);
4893 if (*needed > offered) {
4894 return WERR_INSUFFICIENT_BUFFER;
4900 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4902 PRINTER_INFO_7 *printer=NULL;
4904 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4907 if (!construct_printer_info_7(print_hnd, printer, snum))
4910 /* check the required size. */
4911 *needed += spoolss_size_printer_info_7(printer);
4913 if (!alloc_buffer_size(buffer, *needed)) {
4914 free_printer_info_7(printer);
4915 return WERR_INSUFFICIENT_BUFFER;
4918 /* fill the buffer with the structures */
4919 smb_io_printer_info_7("", buffer, printer, 0);
4922 free_printer_info_7(printer);
4924 if (*needed > offered) {
4925 return WERR_INSUFFICIENT_BUFFER;
4931 /****************************************************************************
4932 ****************************************************************************/
4934 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4936 POLICY_HND *handle = &q_u->handle;
4937 uint32 level = q_u->level;
4938 NEW_BUFFER *buffer = NULL;
4939 uint32 offered = q_u->offered;
4940 uint32 *needed = &r_u->needed;
4941 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4945 /* that's an [in out] buffer */
4946 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4947 buffer = r_u->buffer;
4951 if (!get_printer_snum(p, handle, &snum))
4956 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4958 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4960 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4962 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4964 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4966 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4968 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4970 return WERR_UNKNOWN_LEVEL;
4973 /********************************************************************
4974 * fill a DRIVER_INFO_1 struct
4975 ********************************************************************/
4977 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4979 init_unistr( &info->name, driver.info_3->name);
4982 /********************************************************************
4983 * construct_printer_driver_info_1
4984 ********************************************************************/
4986 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4988 NT_PRINTER_INFO_LEVEL *printer = NULL;
4989 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4991 ZERO_STRUCT(driver);
4993 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4994 return WERR_INVALID_PRINTER_NAME;
4996 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4997 return WERR_UNKNOWN_PRINTER_DRIVER;
4999 fill_printer_driver_info_1(info, driver, servername, architecture);
5001 free_a_printer(&printer,2);
5006 /********************************************************************
5007 * construct_printer_driver_info_2
5008 * fill a printer_info_2 struct
5009 ********************************************************************/
5011 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5015 info->version=driver.info_3->cversion;
5017 init_unistr( &info->name, driver.info_3->name );
5018 init_unistr( &info->architecture, driver.info_3->environment );
5021 if (strlen(driver.info_3->driverpath)) {
5022 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5023 init_unistr( &info->driverpath, temp );
5025 init_unistr( &info->driverpath, "" );
5027 if (strlen(driver.info_3->datafile)) {
5028 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5029 init_unistr( &info->datafile, temp );
5031 init_unistr( &info->datafile, "" );
5033 if (strlen(driver.info_3->configfile)) {
5034 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5035 init_unistr( &info->configfile, temp );
5037 init_unistr( &info->configfile, "" );
5040 /********************************************************************
5041 * construct_printer_driver_info_2
5042 * fill a printer_info_2 struct
5043 ********************************************************************/
5045 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5047 NT_PRINTER_INFO_LEVEL *printer = NULL;
5048 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5050 ZERO_STRUCT(printer);
5051 ZERO_STRUCT(driver);
5053 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5054 return WERR_INVALID_PRINTER_NAME;
5056 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5057 return WERR_UNKNOWN_PRINTER_DRIVER;
5059 fill_printer_driver_info_2(info, driver, servername);
5061 free_a_printer(&printer,2);
5066 /********************************************************************
5067 * copy a strings array and convert to UNICODE
5069 * convert an array of ascii string to a UNICODE string
5070 ********************************************************************/
5072 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5080 DEBUG(6,("init_unistr_array\n"));
5091 v = ""; /* hack to handle null lists */
5094 /* hack to allow this to be used in places other than when generating
5095 the list of dependent files */
5098 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5102 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
5104 /* add one extra unit16 for the second terminating NULL */
5106 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5107 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5115 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5120 /* special case for ""; we need to add both NULL's here */
5122 (*uni_array)[j++]=0x0000;
5123 (*uni_array)[j]=0x0000;
5126 DEBUGADD(6,("last one:done\n"));
5128 /* return size of array in uint16's */
5133 /********************************************************************
5134 * construct_printer_info_3
5135 * fill a printer_info_3 struct
5136 ********************************************************************/
5138 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5144 info->version=driver.info_3->cversion;
5146 init_unistr( &info->name, driver.info_3->name );
5147 init_unistr( &info->architecture, driver.info_3->environment );
5149 if (strlen(driver.info_3->driverpath)) {
5150 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5151 init_unistr( &info->driverpath, temp );
5153 init_unistr( &info->driverpath, "" );
5155 if (strlen(driver.info_3->datafile)) {
5156 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5157 init_unistr( &info->datafile, temp );
5159 init_unistr( &info->datafile, "" );
5161 if (strlen(driver.info_3->configfile)) {
5162 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5163 init_unistr( &info->configfile, temp );
5165 init_unistr( &info->configfile, "" );
5167 if (strlen(driver.info_3->helpfile)) {
5168 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5169 init_unistr( &info->helpfile, temp );
5171 init_unistr( &info->helpfile, "" );
5173 init_unistr( &info->monitorname, driver.info_3->monitorname );
5174 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5176 info->dependentfiles=NULL;
5177 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5180 /********************************************************************
5181 * construct_printer_info_3
5182 * fill a printer_info_3 struct
5183 ********************************************************************/
5185 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5187 NT_PRINTER_INFO_LEVEL *printer = NULL;
5188 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5190 ZERO_STRUCT(driver);
5192 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5193 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5194 if (!W_ERROR_IS_OK(status))
5195 return WERR_INVALID_PRINTER_NAME;
5197 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5198 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5203 * I put this code in during testing. Helpful when commenting out the
5204 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5205 * as win2k always queries the driver using an infor level of 6.
5206 * I've left it in (but ifdef'd out) because I'll probably
5207 * use it in experimentation again in the future. --jerry 22/01/2002
5210 if (!W_ERROR_IS_OK(status)) {
5212 * Is this a W2k client ?
5215 /* Yes - try again with a WinNT driver. */
5217 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5218 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5222 if (!W_ERROR_IS_OK(status)) {
5223 free_a_printer(&printer,2);
5224 return WERR_UNKNOWN_PRINTER_DRIVER;
5232 fill_printer_driver_info_3(info, driver, servername);
5234 free_a_printer(&printer,2);
5239 /********************************************************************
5240 * construct_printer_info_6
5241 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5242 ********************************************************************/
5244 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5250 memset(&nullstr, '\0', sizeof(fstring));
5252 info->version=driver.info_3->cversion;
5254 init_unistr( &info->name, driver.info_3->name );
5255 init_unistr( &info->architecture, driver.info_3->environment );
5257 if (strlen(driver.info_3->driverpath)) {
5258 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5259 init_unistr( &info->driverpath, temp );
5261 init_unistr( &info->driverpath, "" );
5263 if (strlen(driver.info_3->datafile)) {
5264 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5265 init_unistr( &info->datafile, temp );
5267 init_unistr( &info->datafile, "" );
5269 if (strlen(driver.info_3->configfile)) {
5270 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5271 init_unistr( &info->configfile, temp );
5273 init_unistr( &info->configfile, "" );
5275 if (strlen(driver.info_3->helpfile)) {
5276 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5277 init_unistr( &info->helpfile, temp );
5279 init_unistr( &info->helpfile, "" );
5281 init_unistr( &info->monitorname, driver.info_3->monitorname );
5282 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5284 info->dependentfiles = NULL;
5285 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5287 info->previousdrivernames=NULL;
5288 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5290 info->driver_date.low=0;
5291 info->driver_date.high=0;
5294 info->driver_version_low=0;
5295 info->driver_version_high=0;
5297 init_unistr( &info->mfgname, "");
5298 init_unistr( &info->oem_url, "");
5299 init_unistr( &info->hardware_id, "");
5300 init_unistr( &info->provider, "");
5303 /********************************************************************
5304 * construct_printer_info_6
5305 * fill a printer_info_6 struct
5306 ********************************************************************/
5308 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5309 fstring servername, fstring architecture, uint32 version)
5311 NT_PRINTER_INFO_LEVEL *printer = NULL;
5312 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5315 ZERO_STRUCT(driver);
5317 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5319 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5321 if (!W_ERROR_IS_OK(status))
5322 return WERR_INVALID_PRINTER_NAME;
5324 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5326 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5328 if (!W_ERROR_IS_OK(status))
5331 * Is this a W2k client ?
5335 free_a_printer(&printer,2);
5336 return WERR_UNKNOWN_PRINTER_DRIVER;
5339 /* Yes - try again with a WinNT driver. */
5341 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5342 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5343 if (!W_ERROR_IS_OK(status)) {
5344 free_a_printer(&printer,2);
5345 return WERR_UNKNOWN_PRINTER_DRIVER;
5349 fill_printer_driver_info_6(info, driver, servername);
5351 free_a_printer(&printer,2);
5352 free_a_printer_driver(driver, 3);
5357 /****************************************************************************
5358 ****************************************************************************/
5360 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5362 SAFE_FREE(info->dependentfiles);
5365 /****************************************************************************
5366 ****************************************************************************/
5368 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5370 SAFE_FREE(info->dependentfiles);
5374 /****************************************************************************
5375 ****************************************************************************/
5377 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5379 DRIVER_INFO_1 *info=NULL;
5382 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5385 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5386 if (!W_ERROR_IS_OK(status)) {
5391 /* check the required size. */
5392 *needed += spoolss_size_printer_driver_info_1(info);
5394 if (!alloc_buffer_size(buffer, *needed)) {
5396 return WERR_INSUFFICIENT_BUFFER;
5399 /* fill the buffer with the structures */
5400 smb_io_printer_driver_info_1("", buffer, info, 0);
5405 if (*needed > offered)
5406 return WERR_INSUFFICIENT_BUFFER;
5411 /****************************************************************************
5412 ****************************************************************************/
5414 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5416 DRIVER_INFO_2 *info=NULL;
5419 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5422 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5423 if (!W_ERROR_IS_OK(status)) {
5428 /* check the required size. */
5429 *needed += spoolss_size_printer_driver_info_2(info);
5431 if (!alloc_buffer_size(buffer, *needed)) {
5433 return WERR_INSUFFICIENT_BUFFER;
5436 /* fill the buffer with the structures */
5437 smb_io_printer_driver_info_2("", buffer, info, 0);
5442 if (*needed > offered)
5443 return WERR_INSUFFICIENT_BUFFER;
5448 /****************************************************************************
5449 ****************************************************************************/
5451 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5458 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5459 if (!W_ERROR_IS_OK(status)) {
5463 /* check the required size. */
5464 *needed += spoolss_size_printer_driver_info_3(&info);
5466 if (!alloc_buffer_size(buffer, *needed)) {
5467 free_printer_driver_info_3(&info);
5468 return WERR_INSUFFICIENT_BUFFER;
5471 /* fill the buffer with the structures */
5472 smb_io_printer_driver_info_3("", buffer, &info, 0);
5474 free_printer_driver_info_3(&info);
5476 if (*needed > offered)
5477 return WERR_INSUFFICIENT_BUFFER;
5482 /****************************************************************************
5483 ****************************************************************************/
5485 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5492 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5493 if (!W_ERROR_IS_OK(status)) {
5497 /* check the required size. */
5498 *needed += spoolss_size_printer_driver_info_6(&info);
5500 if (!alloc_buffer_size(buffer, *needed)) {
5501 free_printer_driver_info_6(&info);
5502 return WERR_INSUFFICIENT_BUFFER;
5505 /* fill the buffer with the structures */
5506 smb_io_printer_driver_info_6("", buffer, &info, 0);
5508 free_printer_driver_info_6(&info);
5510 if (*needed > offered)
5511 return WERR_INSUFFICIENT_BUFFER;
5516 /****************************************************************************
5517 ****************************************************************************/
5519 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5521 POLICY_HND *handle = &q_u->handle;
5522 UNISTR2 *uni_arch = &q_u->architecture;
5523 uint32 level = q_u->level;
5524 uint32 clientmajorversion = q_u->clientmajorversion;
5525 NEW_BUFFER *buffer = NULL;
5526 uint32 offered = q_u->offered;
5527 uint32 *needed = &r_u->needed;
5528 uint32 *servermajorversion = &r_u->servermajorversion;
5529 uint32 *serverminorversion = &r_u->serverminorversion;
5532 fstring architecture;
5535 /* that's an [in out] buffer */
5536 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5537 buffer = r_u->buffer;
5539 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5542 *servermajorversion = 0;
5543 *serverminorversion = 0;
5545 fstrcpy(servername, get_called_name());
5546 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5548 if (!get_printer_snum(p, handle, &snum))
5553 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5555 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5557 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5559 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5562 return WERR_UNKNOWN_LEVEL;
5565 /****************************************************************************
5566 ****************************************************************************/
5568 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5570 POLICY_HND *handle = &q_u->handle;
5572 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5575 DEBUG(3,("Error in startpageprinter printer handle\n"));
5579 Printer->page_started=True;
5583 /****************************************************************************
5584 ****************************************************************************/
5586 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5588 POLICY_HND *handle = &q_u->handle;
5591 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5594 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5598 if (!get_printer_snum(p, handle, &snum))
5601 Printer->page_started=False;
5602 print_job_endpage(snum, Printer->jobid);
5607 /********************************************************************
5608 * api_spoolss_getprinter
5609 * called from the spoolss dispatcher
5611 ********************************************************************/
5613 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5615 POLICY_HND *handle = &q_u->handle;
5616 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5617 uint32 *jobid = &r_u->jobid;
5619 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5623 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5624 struct current_user user;
5627 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5631 get_current_user(&user, p);
5634 * a nice thing with NT is it doesn't listen to what you tell it.
5635 * when asked to send _only_ RAW datas, it tries to send datas
5638 * So I add checks like in NT Server ...
5641 if (info_1->p_datatype != 0) {
5642 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5643 if (strcmp(datatype, "RAW") != 0) {
5645 return WERR_INVALID_DATATYPE;
5649 /* get the share number of the printer */
5650 if (!get_printer_snum(p, handle, &snum)) {
5654 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5656 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5658 /* An error occured in print_job_start() so return an appropriate
5661 if (Printer->jobid == -1) {
5662 return map_werror_from_unix(errno);
5665 Printer->document_started=True;
5666 (*jobid) = Printer->jobid;
5671 /********************************************************************
5672 * api_spoolss_getprinter
5673 * called from the spoolss dispatcher
5675 ********************************************************************/
5677 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5679 POLICY_HND *handle = &q_u->handle;
5681 return _spoolss_enddocprinter_internal(p, handle);
5684 /****************************************************************************
5685 ****************************************************************************/
5687 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5689 POLICY_HND *handle = &q_u->handle;
5690 uint32 buffer_size = q_u->buffer_size;
5691 uint8 *buffer = q_u->buffer;
5692 uint32 *buffer_written = &q_u->buffer_size2;
5694 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5697 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5698 r_u->buffer_written = q_u->buffer_size2;
5702 if (!get_printer_snum(p, handle, &snum))
5705 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5706 if (*buffer_written == -1) {
5707 r_u->buffer_written = 0;
5708 if (errno == ENOSPC)
5709 return WERR_NO_SPOOL_SPACE;
5711 return WERR_ACCESS_DENIED;
5714 r_u->buffer_written = q_u->buffer_size2;
5719 /********************************************************************
5720 * api_spoolss_getprinter
5721 * called from the spoolss dispatcher
5723 ********************************************************************/
5725 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5728 struct current_user user;
5730 WERROR errcode = WERR_BADFUNC;
5731 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5733 get_current_user(&user, p);
5736 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5740 if (!get_printer_snum(p, handle, &snum))
5744 case PRINTER_CONTROL_PAUSE:
5745 if (print_queue_pause(&user, snum, &errcode)) {
5749 case PRINTER_CONTROL_RESUME:
5750 case PRINTER_CONTROL_UNPAUSE:
5751 if (print_queue_resume(&user, snum, &errcode)) {
5755 case PRINTER_CONTROL_PURGE:
5756 if (print_queue_purge(&user, snum, &errcode)) {
5761 return WERR_UNKNOWN_LEVEL;
5767 /********************************************************************
5768 * api_spoolss_abortprinter
5769 * From MSDN: "Deletes printer's spool file if printer is configured
5771 ********************************************************************/
5773 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5775 POLICY_HND *handle = &q_u->handle;
5776 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5778 struct current_user user;
5779 WERROR errcode = WERR_OK;
5782 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5786 if (!get_printer_snum(p, handle, &snum))
5789 get_current_user( &user, p );
5791 print_job_delete( &user, snum, Printer->jobid, &errcode );
5796 /********************************************************************
5797 * called by spoolss_api_setprinter
5798 * when updating a printer description
5799 ********************************************************************/
5801 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5802 const SPOOL_PRINTER_INFO_LEVEL *info,
5803 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5805 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5806 struct current_user user;
5810 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5812 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5813 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5814 OUR_HANDLE(handle)));
5816 result = WERR_BADFID;
5820 /* NT seems to like setting the security descriptor even though
5821 nothing may have actually changed. This causes annoying
5822 dialog boxes when the user doesn't have permission to change
5823 the security descriptor. */
5825 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5827 if (DEBUGLEVEL >= 10) {
5831 the_acl = old_secdesc_ctr->sec->dacl;
5832 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5833 PRINTERNAME(snum), the_acl->num_aces));
5835 for (i = 0; i < the_acl->num_aces; i++) {
5838 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5840 DEBUG(10, ("%s 0x%08x\n", sid_str,
5841 the_acl->ace[i].info.mask));
5844 the_acl = secdesc_ctr->sec->dacl;
5847 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5848 PRINTERNAME(snum), the_acl->num_aces));
5850 for (i = 0; i < the_acl->num_aces; i++) {
5853 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5855 DEBUG(10, ("%s 0x%08x\n", sid_str,
5856 the_acl->ace[i].info.mask));
5859 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5863 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5865 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5870 /* Work out which user is performing the operation */
5872 get_current_user(&user, p);
5874 /* Check the user has permissions to change the security
5875 descriptor. By experimentation with two NT machines, the user
5876 requires Full Access to the printer to change security
5879 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5880 result = WERR_ACCESS_DENIED;
5884 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5891 /********************************************************************
5892 Do Samba sanity checks on a printer info struct.
5893 this has changed purpose: it now "canonicalises" printer
5894 info from a client rather than just checking it is correct
5895 ********************************************************************/
5897 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5899 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5900 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5902 /* we force some elements to "correct" values */
5903 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5904 fstrcpy(info->sharename, lp_servicename(snum));
5905 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5906 get_called_name(), info->sharename);
5907 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5913 /****************************************************************************
5914 ****************************************************************************/
5916 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5918 extern userdom_struct current_user_info;
5919 char *cmd = lp_addprinter_cmd();
5925 fstring remote_machine = "%m";
5927 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5929 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5930 cmd, printer->info_2->printername, printer->info_2->sharename,
5931 printer->info_2->portname, printer->info_2->drivername,
5932 printer->info_2->location, printer->info_2->comment, remote_machine);
5934 DEBUG(10,("Running [%s]\n", command));
5935 ret = smbrun(command, &fd);
5936 DEBUGADD(10,("returned [%d]\n", ret));
5945 /* Get lines and convert them back to dos-codepage */
5946 qlines = fd_lines_load(fd, &numlines);
5947 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5951 /* Set the portname to what the script says the portname should be. */
5952 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5953 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5955 /* Send SIGHUP to process group... is there a better way? */
5958 /* reload our services immediately */
5959 reload_services( False );
5962 file_lines_free(qlines);
5966 /********************************************************************
5967 * Called by spoolss_api_setprinter
5968 * when updating a printer description.
5969 ********************************************************************/
5971 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5972 const SPOOL_PRINTER_INFO_LEVEL *info,
5973 DEVICEMODE *devmode)
5976 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5977 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5982 DEBUG(8,("update_printer\n"));
5987 result = WERR_BADFID;
5991 if (!get_printer_snum(p, handle, &snum)) {
5992 result = WERR_BADFID;
5996 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5997 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5998 result = WERR_BADFID;
6002 DEBUGADD(8,("Converting info_2 struct\n"));
6005 * convert_printer_info converts the incoming
6006 * info from the client and overwrites the info
6007 * just read from the tdb in the pointer 'printer'.
6010 if (!convert_printer_info(info, printer, level)) {
6011 result = WERR_NOMEM;
6016 /* we have a valid devmode
6017 convert it and link it*/
6019 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6020 if (!convert_devicemode(printer->info_2->printername, devmode,
6021 &printer->info_2->devmode)) {
6022 result = WERR_NOMEM;
6027 /* Do sanity check on the requested changes for Samba */
6029 if (!check_printer_ok(printer->info_2, snum)) {
6030 result = WERR_INVALID_PARAM;
6034 /* FIXME!!! If the driver has changed we really should verify that
6035 it is installed before doing much else --jerry */
6037 /* Check calling user has permission to update printer description */
6039 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6040 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6041 result = WERR_ACCESS_DENIED;
6045 /* Call addprinter hook */
6046 /* Check changes to see if this is really needed */
6048 if ( *lp_addprinter_cmd()
6049 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6050 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6051 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6052 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6054 if ( !add_printer_hook(printer) ) {
6055 result = WERR_ACCESS_DENIED;
6060 * make sure we actually reload the services after
6061 * this as smb.conf could have a new section in it
6062 * .... shouldn't .... but could
6064 reload_services(False);
6068 * When a *new* driver is bound to a printer, the drivername is used to
6069 * lookup previously saved driver initialization info, which is then
6070 * bound to the printer, simulating what happens in the Windows arch.
6072 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6074 if (!set_driver_init(printer, 2))
6076 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6077 printer->info_2->drivername));
6080 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6081 printer->info_2->drivername));
6083 notify_printer_driver(snum, printer->info_2->drivername);
6087 * flag which changes actually occured. This is a small subset of
6088 * all the possible changes. We also have to update things in the
6092 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6093 init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 );
6094 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6095 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6097 notify_printer_comment(snum, printer->info_2->comment);
6100 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6101 init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 );
6102 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6103 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6104 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6105 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6107 notify_printer_sharename(snum, printer->info_2->sharename);
6110 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6111 init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 );
6112 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6113 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6115 notify_printer_port(snum, printer->info_2->portname);
6118 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6119 init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 );
6120 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6121 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6123 notify_printer_location(snum, printer->info_2->location);
6126 /* here we need to update some more DsSpooler keys */
6127 /* uNCName, serverName, shortServerName */
6129 init_unistr2( &buffer, global_myname(), strlen(global_myname())+1 );
6130 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6131 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6132 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6133 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6135 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6136 global_myname(), printer->info_2->sharename );
6137 init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 );
6138 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6139 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6141 /* Update printer info */
6142 result = mod_a_printer(*printer, 2);
6145 free_a_printer(&printer, 2);
6146 free_a_printer(&old_printer, 2);
6152 /****************************************************************************
6153 ****************************************************************************/
6154 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6155 const SPOOL_PRINTER_INFO_LEVEL *info)
6158 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6160 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6163 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6170 if (!get_printer_snum(p, handle, &snum))
6173 nt_printer_publish(Printer, snum, info7->action);
6177 return WERR_UNKNOWN_LEVEL;
6180 /****************************************************************************
6181 ****************************************************************************/
6183 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6185 POLICY_HND *handle = &q_u->handle;
6186 uint32 level = q_u->level;
6187 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6188 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6189 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6190 uint32 command = q_u->command;
6192 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6195 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6199 /* check the level */
6202 return control_printer(handle, command, p);
6204 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6206 return update_printer_sec(handle, level, info, p,
6209 return publish_or_unpublish_printer(p, handle, info);
6211 return WERR_UNKNOWN_LEVEL;
6215 /****************************************************************************
6216 ****************************************************************************/
6218 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6220 POLICY_HND *handle = &q_u->handle;
6221 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6224 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6228 if (Printer->notify.client_connected==True) {
6231 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6233 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6234 !get_printer_snum(p, handle, &snum) )
6237 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6240 Printer->notify.flags=0;
6241 Printer->notify.options=0;
6242 Printer->notify.localmachine[0]='\0';
6243 Printer->notify.printerlocal=0;
6244 if (Printer->notify.option)
6245 free_spool_notify_option(&Printer->notify.option);
6246 Printer->notify.client_connected=False;
6251 /****************************************************************************
6252 ****************************************************************************/
6254 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6256 /* that's an [in out] buffer (despite appearences to the contrary) */
6257 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6260 return WERR_INVALID_PARAM; /* this is what a NT server
6261 returns for AddJob. AddJob
6262 must fail on non-local
6266 /****************************************************************************
6267 ****************************************************************************/
6269 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6270 int position, int snum)
6276 t=gmtime(&queue->time);
6277 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6279 job_info->jobid=queue->job;
6280 init_unistr(&job_info->printername, lp_servicename(snum));
6281 init_unistr(&job_info->machinename, temp_name);
6282 init_unistr(&job_info->username, queue->fs_user);
6283 init_unistr(&job_info->document, queue->fs_file);
6284 init_unistr(&job_info->datatype, "RAW");
6285 init_unistr(&job_info->text_status, "");
6286 job_info->status=nt_printj_status(queue->status);
6287 job_info->priority=queue->priority;
6288 job_info->position=position;
6289 job_info->totalpages=queue->page_count;
6290 job_info->pagesprinted=0;
6292 make_systemtime(&job_info->submitted, t);
6295 /****************************************************************************
6296 ****************************************************************************/
6298 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6299 int position, int snum,
6300 NT_PRINTER_INFO_LEVEL *ntprinter,
6301 DEVICEMODE *devmode)
6306 t=gmtime(&queue->time);
6307 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6309 job_info->jobid=queue->job;
6311 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6313 init_unistr(&job_info->machinename, temp_name);
6314 init_unistr(&job_info->username, queue->fs_user);
6315 init_unistr(&job_info->document, queue->fs_file);
6316 init_unistr(&job_info->notifyname, queue->fs_user);
6317 init_unistr(&job_info->datatype, "RAW");
6318 init_unistr(&job_info->printprocessor, "winprint");
6319 init_unistr(&job_info->parameters, "");
6320 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6321 init_unistr(&job_info->text_status, "");
6323 /* and here the security descriptor */
6325 job_info->status=nt_printj_status(queue->status);
6326 job_info->priority=queue->priority;
6327 job_info->position=position;
6328 job_info->starttime=0;
6329 job_info->untiltime=0;
6330 job_info->totalpages=queue->page_count;
6331 job_info->size=queue->size;
6332 make_systemtime(&(job_info->submitted), t);
6333 job_info->timeelapsed=0;
6334 job_info->pagesprinted=0;
6336 job_info->devmode = devmode;
6341 /****************************************************************************
6342 Enumjobs at level 1.
6343 ****************************************************************************/
6345 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6346 NEW_BUFFER *buffer, uint32 offered,
6347 uint32 *needed, uint32 *returned)
6352 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6359 for (i=0; i<*returned; i++)
6360 fill_job_info_1(&info[i], &queue[i], i, snum);
6364 /* check the required size. */
6365 for (i=0; i<*returned; i++)
6366 (*needed) += spoolss_size_job_info_1(&info[i]);
6368 if (!alloc_buffer_size(buffer, *needed)) {
6370 return WERR_INSUFFICIENT_BUFFER;
6373 /* fill the buffer with the structures */
6374 for (i=0; i<*returned; i++)
6375 smb_io_job_info_1("", buffer, &info[i], 0);
6380 if (*needed > offered) {
6382 return WERR_INSUFFICIENT_BUFFER;
6388 /****************************************************************************
6389 Enumjobs at level 2.
6390 ****************************************************************************/
6392 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6393 NEW_BUFFER *buffer, uint32 offered,
6394 uint32 *needed, uint32 *returned)
6396 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6397 JOB_INFO_2 *info = NULL;
6400 DEVICEMODE *devmode = NULL;
6402 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6405 result = WERR_NOMEM;
6409 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6410 if (!W_ERROR_IS_OK(result)) {
6415 /* this should not be a failure condition if the devmode is NULL */
6417 devmode = construct_dev_mode(snum);
6419 for (i=0; i<*returned; i++)
6420 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6423 free_a_printer(&ntprinter, 2);
6426 /* check the required size. */
6427 for (i=0; i<*returned; i++)
6428 (*needed) += spoolss_size_job_info_2(&info[i]);
6430 if (*needed > offered) {
6432 result = WERR_INSUFFICIENT_BUFFER;
6436 if (!alloc_buffer_size(buffer, *needed)) {
6438 result = WERR_INSUFFICIENT_BUFFER;
6442 /* fill the buffer with the structures */
6443 for (i=0; i<*returned; i++)
6444 smb_io_job_info_2("", buffer, &info[i], 0);
6449 free_a_printer(&ntprinter, 2);
6450 free_devmode(devmode);
6458 /****************************************************************************
6460 ****************************************************************************/
6462 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6464 POLICY_HND *handle = &q_u->handle;
6465 uint32 level = q_u->level;
6466 NEW_BUFFER *buffer = NULL;
6467 uint32 offered = q_u->offered;
6468 uint32 *needed = &r_u->needed;
6469 uint32 *returned = &r_u->returned;
6473 print_status_struct prt_status;
6474 print_queue_struct *queue=NULL;
6476 /* that's an [in out] buffer */
6477 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6478 buffer = r_u->buffer;
6480 DEBUG(4,("_spoolss_enumjobs\n"));
6485 if (!get_printer_snum(p, handle, &snum))
6488 *returned = print_queue_status(snum, &queue, &prt_status);
6489 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6491 if (*returned == 0) {
6492 set_enumjobs_timestamp(snum);
6499 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6500 set_enumjobs_timestamp(snum);
6503 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6504 set_enumjobs_timestamp(snum);
6509 return WERR_UNKNOWN_LEVEL;
6513 /****************************************************************************
6514 ****************************************************************************/
6516 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6521 /****************************************************************************
6522 ****************************************************************************/
6524 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6526 POLICY_HND *handle = &q_u->handle;
6527 uint32 jobid = q_u->jobid;
6528 uint32 command = q_u->command;
6530 struct current_user user;
6532 WERROR errcode = WERR_BADFUNC;
6534 if (!get_printer_snum(p, handle, &snum)) {
6538 if (!print_job_exists(snum, jobid)) {
6539 return WERR_INVALID_PRINTER_NAME;
6542 get_current_user(&user, p);
6545 case JOB_CONTROL_CANCEL:
6546 case JOB_CONTROL_DELETE:
6547 if (print_job_delete(&user, snum, jobid, &errcode)) {
6551 case JOB_CONTROL_PAUSE:
6552 if (print_job_pause(&user, snum, jobid, &errcode)) {
6556 case JOB_CONTROL_RESTART:
6557 case JOB_CONTROL_RESUME:
6558 if (print_job_resume(&user, snum, jobid, &errcode)) {
6563 return WERR_UNKNOWN_LEVEL;
6569 /****************************************************************************
6570 Enumerates all printer drivers at level 1.
6571 ****************************************************************************/
6573 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6578 fstring *list = NULL;
6580 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6581 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6585 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6587 ndrivers=get_ntdrivers(&list, architecture, version);
6588 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6594 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6595 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6596 SAFE_FREE(driver_info_1);
6600 else driver_info_1 = tdi1;
6603 for (i=0; i<ndrivers; i++) {
6605 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6606 ZERO_STRUCT(driver);
6607 status = get_a_printer_driver(&driver, 3, list[i],
6608 architecture, version);
6609 if (!W_ERROR_IS_OK(status)) {
6613 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6614 free_a_printer_driver(driver, 3);
6617 *returned+=ndrivers;
6621 /* check the required size. */
6622 for (i=0; i<*returned; i++) {
6623 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6624 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6627 if (!alloc_buffer_size(buffer, *needed)) {
6628 SAFE_FREE(driver_info_1);
6629 return WERR_INSUFFICIENT_BUFFER;
6632 /* fill the buffer with the driver structures */
6633 for (i=0; i<*returned; i++) {
6634 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6635 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6638 SAFE_FREE(driver_info_1);
6640 if (*needed > offered) {
6642 return WERR_INSUFFICIENT_BUFFER;
6648 /****************************************************************************
6649 Enumerates all printer drivers at level 2.
6650 ****************************************************************************/
6652 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6657 fstring *list = NULL;
6659 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6660 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6664 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6666 ndrivers=get_ntdrivers(&list, architecture, version);
6667 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6673 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6674 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6675 SAFE_FREE(driver_info_2);
6679 else driver_info_2 = tdi2;
6682 for (i=0; i<ndrivers; i++) {
6685 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6686 ZERO_STRUCT(driver);
6687 status = get_a_printer_driver(&driver, 3, list[i],
6688 architecture, version);
6689 if (!W_ERROR_IS_OK(status)) {
6693 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6694 free_a_printer_driver(driver, 3);
6697 *returned+=ndrivers;
6701 /* check the required size. */
6702 for (i=0; i<*returned; i++) {
6703 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6704 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6707 if (!alloc_buffer_size(buffer, *needed)) {
6708 SAFE_FREE(driver_info_2);
6709 return WERR_INSUFFICIENT_BUFFER;
6712 /* fill the buffer with the form structures */
6713 for (i=0; i<*returned; i++) {
6714 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6715 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6718 SAFE_FREE(driver_info_2);
6720 if (*needed > offered) {
6722 return WERR_INSUFFICIENT_BUFFER;
6728 /****************************************************************************
6729 Enumerates all printer drivers at level 3.
6730 ****************************************************************************/
6732 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6737 fstring *list = NULL;
6739 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6740 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6744 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6746 ndrivers=get_ntdrivers(&list, architecture, version);
6747 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6753 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6754 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6755 SAFE_FREE(driver_info_3);
6759 else driver_info_3 = tdi3;
6762 for (i=0; i<ndrivers; i++) {
6765 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6766 ZERO_STRUCT(driver);
6767 status = get_a_printer_driver(&driver, 3, list[i],
6768 architecture, version);
6769 if (!W_ERROR_IS_OK(status)) {
6773 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6774 free_a_printer_driver(driver, 3);
6777 *returned+=ndrivers;
6781 /* check the required size. */
6782 for (i=0; i<*returned; i++) {
6783 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6784 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6787 if (!alloc_buffer_size(buffer, *needed)) {
6788 SAFE_FREE(driver_info_3);
6789 return WERR_INSUFFICIENT_BUFFER;
6792 /* fill the buffer with the driver structures */
6793 for (i=0; i<*returned; i++) {
6794 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6795 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6798 for (i=0; i<*returned; i++)
6799 SAFE_FREE(driver_info_3[i].dependentfiles);
6801 SAFE_FREE(driver_info_3);
6803 if (*needed > offered) {
6805 return WERR_INSUFFICIENT_BUFFER;
6811 /****************************************************************************
6812 Enumerates all printer drivers.
6813 ****************************************************************************/
6815 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6817 UNISTR2 *environment = &q_u->environment;
6818 uint32 level = q_u->level;
6819 NEW_BUFFER *buffer = NULL;
6820 uint32 offered = q_u->offered;
6821 uint32 *needed = &r_u->needed;
6822 uint32 *returned = &r_u->returned;
6824 fstring *list = NULL;
6826 fstring architecture;
6828 /* that's an [in out] buffer */
6829 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6830 buffer = r_u->buffer;
6832 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6833 fstrcpy(servername, get_called_name());
6837 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6841 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6843 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6845 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6849 return WERR_UNKNOWN_LEVEL;
6853 /****************************************************************************
6854 ****************************************************************************/
6856 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6858 form->flag=list->flag;
6859 init_unistr(&form->name, list->name);
6860 form->width=list->width;
6861 form->length=list->length;
6862 form->left=list->left;
6863 form->top=list->top;
6864 form->right=list->right;
6865 form->bottom=list->bottom;
6868 /****************************************************************************
6869 ****************************************************************************/
6871 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6873 uint32 level = q_u->level;
6874 NEW_BUFFER *buffer = NULL;
6875 uint32 offered = q_u->offered;
6876 uint32 *needed = &r_u->needed;
6877 uint32 *numofforms = &r_u->numofforms;
6878 uint32 numbuiltinforms;
6880 nt_forms_struct *list=NULL;
6881 nt_forms_struct *builtinlist=NULL;
6886 /* that's an [in out] buffer */
6887 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6888 buffer = r_u->buffer;
6890 DEBUG(4,("_spoolss_enumforms\n"));
6891 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6892 DEBUGADD(5,("Info level [%d]\n", level));
6894 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6895 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6896 *numofforms = get_ntforms(&list);
6897 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6898 *numofforms += numbuiltinforms;
6900 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6904 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6909 /* construct the list of form structures */
6910 for (i=0; i<numbuiltinforms; i++) {
6911 DEBUGADD(6,("Filling form number [%d]\n",i));
6912 fill_form_1(&forms_1[i], &builtinlist[i]);
6915 SAFE_FREE(builtinlist);
6917 for (; i<*numofforms; i++) {
6918 DEBUGADD(6,("Filling form number [%d]\n",i));
6919 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6924 /* check the required size. */
6925 for (i=0; i<numbuiltinforms; i++) {
6926 DEBUGADD(6,("adding form [%d]'s size\n",i));
6927 buffer_size += spoolss_size_form_1(&forms_1[i]);
6929 for (; i<*numofforms; i++) {
6930 DEBUGADD(6,("adding form [%d]'s size\n",i));
6931 buffer_size += spoolss_size_form_1(&forms_1[i]);
6934 *needed=buffer_size;
6936 if (!alloc_buffer_size(buffer, buffer_size)){
6938 return WERR_INSUFFICIENT_BUFFER;
6941 /* fill the buffer with the form structures */
6942 for (i=0; i<numbuiltinforms; i++) {
6943 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6944 smb_io_form_1("", buffer, &forms_1[i], 0);
6946 for (; i<*numofforms; i++) {
6947 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6948 smb_io_form_1("", buffer, &forms_1[i], 0);
6953 if (*needed > offered) {
6955 return WERR_INSUFFICIENT_BUFFER;
6962 SAFE_FREE(builtinlist);
6963 return WERR_UNKNOWN_LEVEL;
6968 /****************************************************************************
6969 ****************************************************************************/
6971 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6973 uint32 level = q_u->level;
6974 UNISTR2 *uni_formname = &q_u->formname;
6975 NEW_BUFFER *buffer = NULL;
6976 uint32 offered = q_u->offered;
6977 uint32 *needed = &r_u->needed;
6979 nt_forms_struct *list=NULL;
6980 nt_forms_struct builtin_form;
6985 int numofforms=0, i=0;
6987 /* that's an [in out] buffer */
6988 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6989 buffer = r_u->buffer;
6991 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6993 DEBUG(4,("_spoolss_getform\n"));
6994 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6995 DEBUGADD(5,("Info level [%d]\n", level));
6997 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6998 if (!foundBuiltin) {
6999 numofforms = get_ntforms(&list);
7000 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7002 if (numofforms == 0)
7009 fill_form_1(&form_1, &builtin_form);
7012 /* Check if the requested name is in the list of form structures */
7013 for (i=0; i<numofforms; i++) {
7015 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7017 if (strequal(form_name, list[i].name)) {
7018 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7019 fill_form_1(&form_1, &list[i]);
7025 if (i == numofforms) {
7029 /* check the required size. */
7031 *needed=spoolss_size_form_1(&form_1);
7033 if (!alloc_buffer_size(buffer, buffer_size)){
7034 return WERR_INSUFFICIENT_BUFFER;
7037 if (*needed > offered) {
7038 return WERR_INSUFFICIENT_BUFFER;
7041 /* fill the buffer with the form structures */
7042 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7043 smb_io_form_1("", buffer, &form_1, 0);
7049 return WERR_UNKNOWN_LEVEL;
7053 /****************************************************************************
7054 ****************************************************************************/
7056 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7058 init_unistr(&port->port_name, name);
7061 /****************************************************************************
7062 ****************************************************************************/
7064 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7066 init_unistr(&port->port_name, name);
7067 init_unistr(&port->monitor_name, "Local Monitor");
7068 init_unistr(&port->description, "Local Port");
7069 #define PORT_TYPE_WRITE 1
7070 port->port_type=PORT_TYPE_WRITE;
7074 /****************************************************************************
7076 ****************************************************************************/
7078 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7080 PORT_INFO_1 *ports=NULL;
7083 if (*lp_enumports_cmd()) {
7084 char *cmd = lp_enumports_cmd();
7091 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7093 DEBUG(10,("Running [%s]\n", command));
7094 ret = smbrun(command, &fd);
7095 DEBUG(10,("Returned [%d]\n", ret));
7099 /* Is this the best error to return here? */
7100 return WERR_ACCESS_DENIED;
7104 qlines = fd_lines_load(fd, &numlines);
7105 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7109 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7110 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7111 dos_errstr(WERR_NOMEM)));
7112 file_lines_free(qlines);
7116 for (i=0; i<numlines; i++) {
7117 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7118 fill_port_1(&ports[i], qlines[i]);
7121 file_lines_free(qlines);
7124 *returned = numlines;
7127 *returned = 1; /* Sole Samba port returned. */
7129 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7132 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7134 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7137 /* check the required size. */
7138 for (i=0; i<*returned; i++) {
7139 DEBUGADD(6,("adding port [%d]'s size\n", i));
7140 *needed += spoolss_size_port_info_1(&ports[i]);
7143 if (!alloc_buffer_size(buffer, *needed)) {
7145 return WERR_INSUFFICIENT_BUFFER;
7148 /* fill the buffer with the ports structures */
7149 for (i=0; i<*returned; i++) {
7150 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7151 smb_io_port_1("", buffer, &ports[i], 0);
7156 if (*needed > offered) {
7158 return WERR_INSUFFICIENT_BUFFER;
7164 /****************************************************************************
7166 ****************************************************************************/
7168 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7170 PORT_INFO_2 *ports=NULL;
7173 if (*lp_enumports_cmd()) {
7174 char *cmd = lp_enumports_cmd();
7183 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7184 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7186 path = lp_lockdir();
7188 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7189 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7192 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7193 ret = smbrun(command, &fd);
7194 DEBUGADD(10,("returned [%d]\n", ret));
7198 /* Is this the best error to return here? */
7199 return WERR_ACCESS_DENIED;
7203 qlines = fd_lines_load(fd, &numlines);
7204 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7208 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7209 file_lines_free(qlines);
7213 for (i=0; i<numlines; i++) {
7214 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7215 fill_port_2(&(ports[i]), qlines[i]);
7218 file_lines_free(qlines);
7221 *returned = numlines;
7227 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7230 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7232 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7235 /* check the required size. */
7236 for (i=0; i<*returned; i++) {
7237 DEBUGADD(6,("adding port [%d]'s size\n", i));
7238 *needed += spoolss_size_port_info_2(&ports[i]);
7241 if (!alloc_buffer_size(buffer, *needed)) {
7243 return WERR_INSUFFICIENT_BUFFER;
7246 /* fill the buffer with the ports structures */
7247 for (i=0; i<*returned; i++) {
7248 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7249 smb_io_port_2("", buffer, &ports[i], 0);
7254 if (*needed > offered) {
7256 return WERR_INSUFFICIENT_BUFFER;
7262 /****************************************************************************
7264 ****************************************************************************/
7266 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7268 uint32 level = q_u->level;
7269 NEW_BUFFER *buffer = NULL;
7270 uint32 offered = q_u->offered;
7271 uint32 *needed = &r_u->needed;
7272 uint32 *returned = &r_u->returned;
7274 /* that's an [in out] buffer */
7275 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7276 buffer = r_u->buffer;
7278 DEBUG(4,("_spoolss_enumports\n"));
7285 return enumports_level_1(buffer, offered, needed, returned);
7287 return enumports_level_2(buffer, offered, needed, returned);
7289 return WERR_UNKNOWN_LEVEL;
7293 /****************************************************************************
7294 ****************************************************************************/
7296 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7297 const SPOOL_PRINTER_INFO_LEVEL *info,
7298 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7299 uint32 user_switch, const SPOOL_USER_CTR *user,
7302 NT_PRINTER_INFO_LEVEL *printer = NULL;
7305 WERROR err = WERR_OK;
7307 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7308 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7312 ZERO_STRUCTP(printer);
7314 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7315 if (!convert_printer_info(info, printer, 2)) {
7316 free_a_printer(&printer, 2);
7320 /* check to see if the printer already exists */
7322 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7323 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7324 printer->info_2->sharename));
7325 free_a_printer(&printer, 2);
7326 return WERR_PRINTER_ALREADY_EXISTS;
7329 /* FIXME!!! smbd should check to see if the driver is installed before
7330 trying to add a printer like this --jerry */
7332 if (*lp_addprinter_cmd() ) {
7333 if ( !add_printer_hook(printer) ) {
7334 free_a_printer(&printer,2);
7335 return WERR_ACCESS_DENIED;
7339 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7340 printer->info_2->sharename);
7343 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7344 free_a_printer(&printer,2);
7345 return WERR_ACCESS_DENIED;
7348 /* you must be a printer admin to add a new printer */
7349 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7350 free_a_printer(&printer,2);
7351 return WERR_ACCESS_DENIED;
7355 * Do sanity check on the requested changes for Samba.
7358 if (!check_printer_ok(printer->info_2, snum)) {
7359 free_a_printer(&printer,2);
7360 return WERR_INVALID_PARAM;
7364 * When a printer is created, the drivername bound to the printer is used
7365 * to lookup previously saved driver initialization info, which is then
7366 * bound to the new printer, simulating what happens in the Windows arch.
7371 set_driver_init(printer, 2);
7375 /* A valid devmode was included, convert and link it
7377 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7379 if (!convert_devicemode(printer->info_2->printername, devmode,
7380 &printer->info_2->devmode))
7384 /* write the ASCII on disk */
7385 err = mod_a_printer(*printer, 2);
7386 if (!W_ERROR_IS_OK(err)) {
7387 free_a_printer(&printer,2);
7391 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7392 /* Handle open failed - remove addition. */
7393 del_a_printer(printer->info_2->sharename);
7394 free_a_printer(&printer,2);
7395 return WERR_ACCESS_DENIED;
7398 update_c_setprinter(False);
7399 free_a_printer(&printer,2);
7404 /****************************************************************************
7405 ****************************************************************************/
7407 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7409 UNISTR2 *uni_srv_name = &q_u->server_name;
7410 uint32 level = q_u->level;
7411 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7412 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7413 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7414 uint32 user_switch = q_u->user_switch;
7415 SPOOL_USER_CTR *user = &q_u->user_ctr;
7416 POLICY_HND *handle = &r_u->handle;
7420 /* we don't handle yet */
7421 /* but I know what to do ... */
7422 return WERR_UNKNOWN_LEVEL;
7424 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7426 user_switch, user, handle);
7428 return WERR_UNKNOWN_LEVEL;
7432 /****************************************************************************
7433 ****************************************************************************/
7435 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7437 uint32 level = q_u->level;
7438 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7439 WERROR err = WERR_OK;
7440 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7441 struct current_user user;
7442 fstring driver_name;
7445 ZERO_STRUCT(driver);
7447 get_current_user(&user, p);
7449 if (!convert_printer_driver_info(info, &driver, level)) {
7454 DEBUG(5,("Cleaning driver's information\n"));
7455 err = clean_up_driver_struct(driver, level, &user);
7456 if (!W_ERROR_IS_OK(err))
7459 DEBUG(5,("Moving driver to final destination\n"));
7460 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7461 if (W_ERROR_IS_OK(err))
7462 err = WERR_ACCESS_DENIED;
7466 if (add_a_printer_driver(driver, level)!=0) {
7467 err = WERR_ACCESS_DENIED;
7471 /* BEGIN_ADMIN_LOG */
7474 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7475 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7476 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7479 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7480 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7481 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7487 * I think this is where he DrvUpgradePrinter() hook would be
7488 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7489 * server. Right now, we just need to send ourselves a message
7490 * to update each printer bound to this driver. --jerry
7493 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7494 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7499 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7500 * decide if the driver init data should be deleted. The rules are:
7501 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7502 * 2) delete init data only if there is no 2k/Xp driver
7503 * 3) always delete init data
7504 * The generalized rule is always use init data from the highest order driver.
7505 * It is necessary to follow the driver install by an initialization step to
7506 * finish off this process.
7509 version = driver.info_3->cversion;
7510 else if (level == 6)
7511 version = driver.info_6->version;
7516 * 9x printer driver - never delete init data
7519 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7524 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7525 * there is no 2k/Xp driver init data for this driver name.
7529 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7531 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7533 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7535 if (!del_driver_init(driver_name))
7536 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7539 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7541 free_a_printer_driver(driver1,3);
7542 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7549 * 2k or Xp printer driver - always delete init data
7552 if (!del_driver_init(driver_name))
7553 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7557 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7563 free_a_printer_driver(driver, level);
7567 /********************************************************************
7568 * spoolss_addprinterdriverex
7569 ********************************************************************/
7571 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7573 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7574 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7577 * we only support the semantics of AddPrinterDriver()
7578 * i.e. only copy files that are newer than existing ones
7581 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7582 return WERR_ACCESS_DENIED;
7584 ZERO_STRUCT(q_u_local);
7585 ZERO_STRUCT(r_u_local);
7587 /* just pass the information off to _spoolss_addprinterdriver() */
7588 q_u_local.server_name_ptr = q_u->server_name_ptr;
7589 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7590 q_u_local.level = q_u->level;
7591 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7593 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7596 /****************************************************************************
7597 ****************************************************************************/
7599 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7601 init_unistr(&info->name, name);
7604 /****************************************************************************
7605 ****************************************************************************/
7607 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7611 pstring short_archi;
7612 DRIVER_DIRECTORY_1 *info=NULL;
7614 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7616 if (get_short_archi(short_archi, long_archi)==False)
7617 return WERR_INVALID_ENVIRONMENT;
7619 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7622 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7624 DEBUG(4,("printer driver directory: [%s]\n", path));
7626 fill_driverdir_1(info, path);
7628 *needed += spoolss_size_driverdir_info_1(info);
7630 if (!alloc_buffer_size(buffer, *needed)) {
7632 return WERR_INSUFFICIENT_BUFFER;
7635 smb_io_driverdir_1("", buffer, info, 0);
7639 if (*needed > offered)
7640 return WERR_INSUFFICIENT_BUFFER;
7645 /****************************************************************************
7646 ****************************************************************************/
7648 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7650 UNISTR2 *name = &q_u->name;
7651 UNISTR2 *uni_environment = &q_u->environment;
7652 uint32 level = q_u->level;
7653 NEW_BUFFER *buffer = NULL;
7654 uint32 offered = q_u->offered;
7655 uint32 *needed = &r_u->needed;
7657 /* that's an [in out] buffer */
7658 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7659 buffer = r_u->buffer;
7661 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7667 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7669 return WERR_UNKNOWN_LEVEL;
7673 /****************************************************************************
7674 ****************************************************************************/
7676 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7678 POLICY_HND *handle = &q_u->handle;
7679 uint32 idx = q_u->index;
7680 uint32 in_value_len = q_u->valuesize;
7681 uint32 in_data_len = q_u->datasize;
7682 uint32 *out_max_value_len = &r_u->valuesize;
7683 uint16 **out_value = &r_u->value;
7684 uint32 *out_value_len = &r_u->realvaluesize;
7685 uint32 *out_type = &r_u->type;
7686 uint32 *out_max_data_len = &r_u->datasize;
7687 uint8 **data_out = &r_u->data;
7688 uint32 *out_data_len = &r_u->realdatasize;
7690 NT_PRINTER_INFO_LEVEL *printer = NULL;
7693 uint32 biggest_valuesize;
7694 uint32 biggest_datasize;
7696 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7699 REGISTRY_VALUE *val = NULL;
7700 NT_PRINTER_DATA *p_data;
7701 int i, key_index, num_values;
7704 ZERO_STRUCT( printer );
7708 *out_max_data_len = 0;
7712 DEBUG(5,("spoolss_enumprinterdata\n"));
7715 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7719 if (!get_printer_snum(p,handle, &snum))
7722 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7723 if (!W_ERROR_IS_OK(result))
7726 p_data = &printer->info_2->data;
7727 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7732 * The NT machine wants to know the biggest size of value and data
7734 * cf: MSDN EnumPrinterData remark section
7737 if ( !in_value_len && !in_data_len && (key_index != -1) )
7739 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7742 biggest_valuesize = 0;
7743 biggest_datasize = 0;
7745 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7747 for ( i=0; i<num_values; i++ )
7749 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7751 name_length = strlen(val->valuename);
7752 if ( strlen(val->valuename) > biggest_valuesize )
7753 biggest_valuesize = name_length;
7755 if ( val->size > biggest_datasize )
7756 biggest_datasize = val->size;
7758 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7762 /* the value is an UNICODE string but real_value_size is the length
7763 in bytes including the trailing 0 */
7765 *out_value_len = 2 * (1+biggest_valuesize);
7766 *out_data_len = biggest_datasize;
7768 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7774 * the value len is wrong in NT sp3
7775 * that's the number of bytes not the number of unicode chars
7778 if ( key_index != -1 )
7779 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7784 /* out_value should default to "" or else NT4 has
7785 problems unmarshalling the response */
7787 *out_max_value_len=(in_value_len/sizeof(uint16));
7789 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7791 result = WERR_NOMEM;
7795 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7797 /* the data is counted in bytes */
7799 *out_max_data_len = in_data_len;
7800 *out_data_len = in_data_len;
7802 /* only allocate when given a non-zero data_len */
7804 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7806 result = WERR_NOMEM;
7810 result = WERR_NO_MORE_ITEMS;
7816 * - counted in bytes in the request
7817 * - counted in UNICODE chars in the max reply
7818 * - counted in bytes in the real size
7820 * take a pause *before* coding not *during* coding
7824 *out_max_value_len=(in_value_len/sizeof(uint16));
7825 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7827 result = WERR_NOMEM;
7831 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7835 *out_type = regval_type( val );
7837 /* data - counted in bytes */
7839 *out_max_data_len = in_data_len;
7840 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7842 result = WERR_NOMEM;
7845 data_len = (size_t)regval_size(val);
7846 memcpy( *data_out, regval_data_p(val), data_len );
7847 *out_data_len = data_len;
7851 free_a_printer(&printer, 2);
7855 /****************************************************************************
7856 ****************************************************************************/
7858 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7860 POLICY_HND *handle = &q_u->handle;
7861 UNISTR2 *value = &q_u->value;
7862 uint32 type = q_u->type;
7863 uint8 *data = q_u->data;
7864 uint32 real_len = q_u->real_len;
7866 NT_PRINTER_INFO_LEVEL *printer = NULL;
7868 WERROR status = WERR_OK;
7869 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7872 DEBUG(5,("spoolss_setprinterdata\n"));
7875 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7879 if (!get_printer_snum(p,handle, &snum))
7883 * Access check : NT returns "access denied" if you make a
7884 * SetPrinterData call without the necessary privildge.
7885 * we were originally returning OK if nothing changed
7886 * which made Win2k issue **a lot** of SetPrinterData
7887 * when connecting to a printer --jerry
7890 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7892 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7893 status = WERR_ACCESS_DENIED;
7897 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7898 if (!W_ERROR_IS_OK(status))
7901 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7904 * When client side code sets a magic printer data key, detect it and save
7905 * the current printer data and the magic key's data (its the DEVMODE) for
7906 * future printer/driver initializations.
7908 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7910 /* Set devmode and printer initialization info */
7911 status = save_driver_init( printer, 2, data, real_len );
7913 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7917 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7918 type, data, real_len );
7919 if ( W_ERROR_IS_OK(status) )
7920 status = mod_a_printer(*printer, 2);
7924 free_a_printer(&printer, 2);
7929 /****************************************************************************
7930 ****************************************************************************/
7932 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7934 POLICY_HND *handle = &q_u->handle;
7935 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7938 DEBUG(5,("_spoolss_resetprinter\n"));
7941 * All we do is to check to see if the handle and queue is valid.
7942 * This call really doesn't mean anything to us because we only
7943 * support RAW printing. --jerry
7947 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7951 if (!get_printer_snum(p,handle, &snum))
7955 /* blindly return success */
7960 /****************************************************************************
7961 ****************************************************************************/
7963 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7965 POLICY_HND *handle = &q_u->handle;
7966 UNISTR2 *value = &q_u->valuename;
7968 NT_PRINTER_INFO_LEVEL *printer = NULL;
7970 WERROR status = WERR_OK;
7971 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7974 DEBUG(5,("spoolss_deleteprinterdata\n"));
7977 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7981 if (!get_printer_snum(p, handle, &snum))
7984 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7985 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7986 return WERR_ACCESS_DENIED;
7989 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7990 if (!W_ERROR_IS_OK(status))
7993 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7995 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7997 free_a_printer(&printer, 2);
8002 /****************************************************************************
8003 ****************************************************************************/
8005 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8007 POLICY_HND *handle = &q_u->handle;
8008 FORM *form = &q_u->form;
8009 nt_forms_struct tmpForm;
8011 WERROR status = WERR_OK;
8012 NT_PRINTER_INFO_LEVEL *printer = NULL;
8015 nt_forms_struct *list=NULL;
8016 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8018 DEBUG(5,("spoolss_addform\n"));
8021 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8026 /* forms can be added on printer of on the print server handle */
8028 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8030 if (!get_printer_snum(p,handle, &snum))
8033 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8034 if (!W_ERROR_IS_OK(status))
8038 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8039 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8040 status = WERR_ACCESS_DENIED;
8044 /* can't add if builtin */
8046 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8047 status = WERR_ALREADY_EXISTS;
8051 count = get_ntforms(&list);
8053 if(!add_a_form(&list, form, &count)) {
8054 status = WERR_NOMEM;
8058 write_ntforms(&list, count);
8061 * ChangeID must always be set if this is a printer
8064 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8065 status = mod_a_printer(*printer, 2);
8069 free_a_printer(&printer, 2);
8075 /****************************************************************************
8076 ****************************************************************************/
8078 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8080 POLICY_HND *handle = &q_u->handle;
8081 UNISTR2 *form_name = &q_u->name;
8082 nt_forms_struct tmpForm;
8084 nt_forms_struct *list=NULL;
8085 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8087 WERROR status = WERR_OK;
8088 NT_PRINTER_INFO_LEVEL *printer = NULL;
8090 DEBUG(5,("spoolss_deleteform\n"));
8093 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8097 /* forms can be deleted on printer of on the print server handle */
8099 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8101 if (!get_printer_snum(p,handle, &snum))
8104 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8105 if (!W_ERROR_IS_OK(status))
8109 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8110 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8111 status = WERR_ACCESS_DENIED;
8115 /* can't delete if builtin */
8117 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8118 status = WERR_INVALID_PARAM;
8122 count = get_ntforms(&list);
8124 if ( !delete_a_form(&list, form_name, &count, &status ))
8128 * ChangeID must always be set if this is a printer
8131 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8132 status = mod_a_printer(*printer, 2);
8136 free_a_printer(&printer, 2);
8142 /****************************************************************************
8143 ****************************************************************************/
8145 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8147 POLICY_HND *handle = &q_u->handle;
8148 FORM *form = &q_u->form;
8149 nt_forms_struct tmpForm;
8151 WERROR status = WERR_OK;
8152 NT_PRINTER_INFO_LEVEL *printer = NULL;
8155 nt_forms_struct *list=NULL;
8156 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8158 DEBUG(5,("spoolss_setform\n"));
8161 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8165 /* forms can be modified on printer of on the print server handle */
8167 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8169 if (!get_printer_snum(p,handle, &snum))
8172 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8173 if (!W_ERROR_IS_OK(status))
8177 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8178 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8179 status = WERR_ACCESS_DENIED;
8183 /* can't set if builtin */
8184 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8185 status = WERR_INVALID_PARAM;
8189 count = get_ntforms(&list);
8190 update_a_form(&list, form, count);
8191 write_ntforms(&list, count);
8194 * ChangeID must always be set if this is a printer
8197 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8198 status = mod_a_printer(*printer, 2);
8203 free_a_printer(&printer, 2);
8209 /****************************************************************************
8210 enumprintprocessors level 1.
8211 ****************************************************************************/
8213 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8215 PRINTPROCESSOR_1 *info_1=NULL;
8217 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8222 init_unistr(&info_1->name, "winprint");
8224 *needed += spoolss_size_printprocessor_info_1(info_1);
8226 if (!alloc_buffer_size(buffer, *needed))
8227 return WERR_INSUFFICIENT_BUFFER;
8229 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8233 if (*needed > offered) {
8235 return WERR_INSUFFICIENT_BUFFER;
8241 /****************************************************************************
8242 ****************************************************************************/
8244 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8246 uint32 level = q_u->level;
8247 NEW_BUFFER *buffer = NULL;
8248 uint32 offered = q_u->offered;
8249 uint32 *needed = &r_u->needed;
8250 uint32 *returned = &r_u->returned;
8252 /* that's an [in out] buffer */
8253 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8254 buffer = r_u->buffer;
8256 DEBUG(5,("spoolss_enumprintprocessors\n"));
8259 * Enumerate the print processors ...
8261 * Just reply with "winprint", to keep NT happy
8262 * and I can use my nice printer checker.
8270 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8272 return WERR_UNKNOWN_LEVEL;
8276 /****************************************************************************
8277 enumprintprocdatatypes level 1.
8278 ****************************************************************************/
8280 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8282 PRINTPROCDATATYPE_1 *info_1=NULL;
8284 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8289 init_unistr(&info_1->name, "RAW");
8291 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8293 if (!alloc_buffer_size(buffer, *needed))
8294 return WERR_INSUFFICIENT_BUFFER;
8296 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8300 if (*needed > offered) {
8302 return WERR_INSUFFICIENT_BUFFER;
8308 /****************************************************************************
8309 ****************************************************************************/
8311 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8313 uint32 level = q_u->level;
8314 NEW_BUFFER *buffer = NULL;
8315 uint32 offered = q_u->offered;
8316 uint32 *needed = &r_u->needed;
8317 uint32 *returned = &r_u->returned;
8319 /* that's an [in out] buffer */
8320 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8321 buffer = r_u->buffer;
8323 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8330 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8332 return WERR_UNKNOWN_LEVEL;
8336 /****************************************************************************
8337 enumprintmonitors level 1.
8338 ****************************************************************************/
8340 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8342 PRINTMONITOR_1 *info_1=NULL;
8344 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8349 init_unistr(&info_1->name, "Local Port");
8351 *needed += spoolss_size_printmonitor_info_1(info_1);
8353 if (!alloc_buffer_size(buffer, *needed))
8354 return WERR_INSUFFICIENT_BUFFER;
8356 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8360 if (*needed > offered) {
8362 return WERR_INSUFFICIENT_BUFFER;
8368 /****************************************************************************
8369 enumprintmonitors level 2.
8370 ****************************************************************************/
8372 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8374 PRINTMONITOR_2 *info_2=NULL;
8376 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8381 init_unistr(&info_2->name, "Local Port");
8382 init_unistr(&info_2->environment, "Windows NT X86");
8383 init_unistr(&info_2->dll_name, "localmon.dll");
8385 *needed += spoolss_size_printmonitor_info_2(info_2);
8387 if (!alloc_buffer_size(buffer, *needed))
8388 return WERR_INSUFFICIENT_BUFFER;
8390 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8394 if (*needed > offered) {
8396 return WERR_INSUFFICIENT_BUFFER;
8402 /****************************************************************************
8403 ****************************************************************************/
8405 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8407 uint32 level = q_u->level;
8408 NEW_BUFFER *buffer = NULL;
8409 uint32 offered = q_u->offered;
8410 uint32 *needed = &r_u->needed;
8411 uint32 *returned = &r_u->returned;
8413 /* that's an [in out] buffer */
8414 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8415 buffer = r_u->buffer;
8417 DEBUG(5,("spoolss_enumprintmonitors\n"));
8420 * Enumerate the print monitors ...
8422 * Just reply with "Local Port", to keep NT happy
8423 * and I can use my nice printer checker.
8431 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8433 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8435 return WERR_UNKNOWN_LEVEL;
8439 /****************************************************************************
8440 ****************************************************************************/
8442 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8446 JOB_INFO_1 *info_1=NULL;
8448 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8450 if (info_1 == NULL) {
8454 for (i=0; i<count && found==False; i++) {
8455 if (queue[i].job==(int)jobid)
8461 /* NT treats not found as bad param... yet another bad choice */
8462 return WERR_INVALID_PARAM;
8465 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8467 *needed += spoolss_size_job_info_1(info_1);
8469 if (!alloc_buffer_size(buffer, *needed)) {
8471 return WERR_INSUFFICIENT_BUFFER;
8474 smb_io_job_info_1("", buffer, info_1, 0);
8478 if (*needed > offered)
8479 return WERR_INSUFFICIENT_BUFFER;
8484 /****************************************************************************
8485 ****************************************************************************/
8487 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8492 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8494 DEVICEMODE *devmode = NULL;
8495 NT_DEVICEMODE *nt_devmode = NULL;
8497 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8499 ZERO_STRUCTP(info_2);
8501 if (info_2 == NULL) {
8506 for ( i=0; i<count && found==False; i++ )
8508 if (queue[i].job == (int)jobid)
8514 /* NT treats not found as bad param... yet another bad
8516 ret = WERR_INVALID_PARAM;
8520 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8521 if (!W_ERROR_IS_OK(ret))
8525 * if the print job does not have a DEVMODE associated with it,
8526 * just use the one for the printer. A NULL devicemode is not
8527 * a failure condition
8530 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8531 devmode = construct_dev_mode(snum);
8533 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8534 ZERO_STRUCTP( devmode );
8535 convert_nt_devicemode( devmode, nt_devmode );
8539 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8541 *needed += spoolss_size_job_info_2(info_2);
8543 if (!alloc_buffer_size(buffer, *needed)) {
8544 ret = WERR_INSUFFICIENT_BUFFER;
8548 smb_io_job_info_2("", buffer, info_2, 0);
8550 if (*needed > offered) {
8551 ret = WERR_INSUFFICIENT_BUFFER;
8558 /* Cleanup allocated memory */
8560 free_job_info_2(info_2); /* Also frees devmode */
8562 free_a_printer(&ntprinter, 2);
8567 /****************************************************************************
8568 ****************************************************************************/
8570 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8572 POLICY_HND *handle = &q_u->handle;
8573 uint32 jobid = q_u->jobid;
8574 uint32 level = q_u->level;
8575 NEW_BUFFER *buffer = NULL;
8576 uint32 offered = q_u->offered;
8577 uint32 *needed = &r_u->needed;
8578 WERROR wstatus = WERR_OK;
8582 print_queue_struct *queue = NULL;
8583 print_status_struct prt_status;
8585 /* that's an [in out] buffer */
8586 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8587 buffer = r_u->buffer;
8589 DEBUG(5,("spoolss_getjob\n"));
8593 if (!get_printer_snum(p, handle, &snum))
8596 count = print_queue_status(snum, &queue, &prt_status);
8598 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8599 count, prt_status.status, prt_status.message));
8603 wstatus = getjob_level_1(queue, count, snum, jobid,
8604 buffer, offered, needed);
8607 wstatus = getjob_level_2(queue, count, snum, jobid,
8608 buffer, offered, needed);
8611 wstatus = WERR_UNKNOWN_LEVEL;
8619 /********************************************************************
8620 spoolss_getprinterdataex
8622 From MSDN documentation of GetPrinterDataEx: pass request
8623 to GetPrinterData if key is "PrinterDriverData".
8624 ********************************************************************/
8626 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8628 POLICY_HND *handle = &q_u->handle;
8629 uint32 in_size = q_u->size;
8630 uint32 *type = &r_u->type;
8631 uint32 *out_size = &r_u->size;
8632 uint8 **data = &r_u->data;
8633 uint32 *needed = &r_u->needed;
8634 fstring keyname, valuename;
8636 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8638 NT_PRINTER_INFO_LEVEL *printer = NULL;
8640 WERROR status = WERR_OK;
8642 DEBUG(4,("_spoolss_getprinterdataex\n"));
8644 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8645 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8647 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8648 keyname, valuename));
8650 /* in case of problem, return some default values */
8654 *out_size = in_size;
8657 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8658 status = WERR_BADFID;
8662 /* Is the handle to a printer or to the server? */
8664 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8665 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8666 status = WERR_INVALID_PARAM;
8670 if ( !get_printer_snum(p,handle, &snum) )
8673 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8674 if ( !W_ERROR_IS_OK(status) )
8677 /* check to see if the keyname is valid */
8678 if ( !strlen(keyname) ) {
8679 status = WERR_INVALID_PARAM;
8683 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8684 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8685 free_a_printer( &printer, 2 );
8686 status = WERR_BADFILE;
8690 /* When given a new keyname, we should just create it */
8692 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8694 if (*needed > *out_size)
8695 status = WERR_MORE_DATA;
8698 if ( !W_ERROR_IS_OK(status) )
8700 DEBUG(5, ("error: allocating %d\n", *out_size));
8702 /* reply this param doesn't exist */
8706 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8707 status = WERR_NOMEM;
8717 free_a_printer( &printer, 2 );
8722 /********************************************************************
8723 * spoolss_setprinterdataex
8724 ********************************************************************/
8726 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8728 POLICY_HND *handle = &q_u->handle;
8729 uint32 type = q_u->type;
8730 uint8 *data = q_u->data;
8731 uint32 real_len = q_u->real_len;
8733 NT_PRINTER_INFO_LEVEL *printer = NULL;
8735 WERROR status = WERR_OK;
8736 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8741 DEBUG(4,("_spoolss_setprinterdataex\n"));
8743 /* From MSDN documentation of SetPrinterDataEx: pass request to
8744 SetPrinterData if key is "PrinterDriverData" */
8747 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8751 if ( !get_printer_snum(p,handle, &snum) )
8755 * Access check : NT returns "access denied" if you make a
8756 * SetPrinterData call without the necessary privildge.
8757 * we were originally returning OK if nothing changed
8758 * which made Win2k issue **a lot** of SetPrinterData
8759 * when connecting to a printer --jerry
8762 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8764 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8765 return WERR_ACCESS_DENIED;
8768 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8769 if (!W_ERROR_IS_OK(status))
8772 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8773 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8775 /* check for OID in valuename */
8777 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8783 /* save the registry data */
8785 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8787 if ( W_ERROR_IS_OK(status) )
8789 /* save the OID if one was specified */
8791 fstrcat( keyname, "\\" );
8792 fstrcat( keyname, SPOOL_OID_KEY );
8795 * I'm not checking the status here on purpose. Don't know
8796 * if this is right, but I'm returning the status from the
8797 * previous set_printer_dataex() call. I have no idea if
8798 * this is right. --jerry
8801 set_printer_dataex( printer, keyname, valuename,
8802 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8805 status = mod_a_printer(*printer, 2);
8808 free_a_printer(&printer, 2);
8814 /********************************************************************
8815 * spoolss_deleteprinterdataex
8816 ********************************************************************/
8818 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8820 POLICY_HND *handle = &q_u->handle;
8821 UNISTR2 *value = &q_u->valuename;
8822 UNISTR2 *key = &q_u->keyname;
8824 NT_PRINTER_INFO_LEVEL *printer = NULL;
8826 WERROR status = WERR_OK;
8827 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8828 pstring valuename, keyname;
8830 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8833 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8837 if (!get_printer_snum(p, handle, &snum))
8840 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8841 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8842 return WERR_ACCESS_DENIED;
8845 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8846 if (!W_ERROR_IS_OK(status))
8849 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8850 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8852 status = delete_printer_dataex( printer, keyname, valuename );
8854 free_a_printer(&printer, 2);
8859 /********************************************************************
8860 * spoolss_enumprinterkey
8861 ********************************************************************/
8864 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8867 fstring *keynames = NULL;
8868 uint16 *enumkeys = NULL;
8871 POLICY_HND *handle = &q_u->handle;
8872 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8873 NT_PRINTER_DATA *data;
8874 NT_PRINTER_INFO_LEVEL *printer = NULL;
8876 WERROR status = WERR_BADFILE;
8879 DEBUG(4,("_spoolss_enumprinterkey\n"));
8882 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8886 if ( !get_printer_snum(p,handle, &snum) )
8889 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8890 if (!W_ERROR_IS_OK(status))
8893 /* get the list of subkey names */
8895 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8896 data = &printer->info_2->data;
8898 num_keys = get_printer_subkeys( data, key, &keynames );
8900 if ( num_keys == -1 ) {
8901 status = WERR_BADFILE;
8905 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8907 r_u->needed = printerkey_len*2;
8909 if ( q_u->size < r_u->needed ) {
8910 status = WERR_MORE_DATA;
8914 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8915 status = WERR_NOMEM;
8921 if ( q_u->size < r_u->needed )
8922 status = WERR_MORE_DATA;
8925 free_a_printer( &printer, 2 );
8926 SAFE_FREE( keynames );
8931 /********************************************************************
8932 * spoolss_deleteprinterkey
8933 ********************************************************************/
8935 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8937 POLICY_HND *handle = &q_u->handle;
8938 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8940 NT_PRINTER_INFO_LEVEL *printer = NULL;
8944 DEBUG(5,("spoolss_deleteprinterkey\n"));
8947 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8951 /* if keyname == NULL, return error */
8953 if ( !q_u->keyname.buffer )
8954 return WERR_INVALID_PARAM;
8956 if (!get_printer_snum(p, handle, &snum))
8959 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8960 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8961 return WERR_ACCESS_DENIED;
8964 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8965 if (!W_ERROR_IS_OK(status))
8968 /* delete the key and all subneys */
8970 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8972 status = delete_all_printer_data( printer->info_2, key );
8974 if ( W_ERROR_IS_OK(status) )
8975 status = mod_a_printer(*printer, 2);
8977 free_a_printer( &printer, 2 );
8983 /********************************************************************
8984 * spoolss_enumprinterdataex
8985 ********************************************************************/
8987 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8989 POLICY_HND *handle = &q_u->handle;
8990 uint32 in_size = q_u->size;
8993 NT_PRINTER_INFO_LEVEL *printer = NULL;
8994 PRINTER_ENUM_VALUES *enum_values = NULL;
8995 NT_PRINTER_DATA *p_data;
8997 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9002 REGISTRY_VALUE *val;
9007 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9010 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9015 * first check for a keyname of NULL or "". Win2k seems to send
9016 * this a lot and we should send back WERR_INVALID_PARAM
9017 * no need to spend time looking up the printer in this case.
9021 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9022 if ( !strlen(key) ) {
9023 result = WERR_INVALID_PARAM;
9027 /* get the printer off of disk */
9029 if (!get_printer_snum(p,handle, &snum))
9032 ZERO_STRUCT(printer);
9033 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9034 if (!W_ERROR_IS_OK(result))
9037 /* now look for a match on the key name */
9039 p_data = &printer->info_2->data;
9041 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9042 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9044 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9045 result = WERR_INVALID_PARAM;
9052 /* allocate the memory for the array of pointers -- if necessary */
9054 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9057 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9059 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
9060 num_entries*sizeof(PRINTER_ENUM_VALUES)));
9061 result = WERR_NOMEM;
9065 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9069 * loop through all params and build the array to pass
9070 * back to the client
9073 for ( i=0; i<num_entries; i++ )
9075 /* lookup the registry value */
9077 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9078 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9082 value_name = regval_name( val );
9083 init_unistr( &enum_values[i].valuename, value_name );
9084 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9085 enum_values[i].type = regval_type( val );
9087 data_len = regval_size( val );
9089 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9091 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9093 result = WERR_NOMEM;
9097 enum_values[i].data_len = data_len;
9099 /* keep track of the size of the array in bytes */
9101 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9104 /* housekeeping information in the reply */
9106 r_u->needed = needed;
9107 r_u->returned = num_entries;
9109 if (needed > in_size) {
9110 result = WERR_MORE_DATA;
9114 /* copy data into the reply */
9116 r_u->ctr.size = r_u->needed;
9117 r_u->ctr.size_of_array = r_u->returned;
9118 r_u->ctr.values = enum_values;
9124 free_a_printer(&printer, 2);
9129 /****************************************************************************
9130 ****************************************************************************/
9132 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9134 init_unistr(&info->name, name);
9137 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9138 UNISTR2 *environment,
9145 pstring short_archi;
9146 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9148 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9150 if (get_short_archi(short_archi, long_archi)==False)
9151 return WERR_INVALID_ENVIRONMENT;
9153 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9156 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9158 fill_printprocessordirectory_1(info, path);
9160 *needed += spoolss_size_printprocessordirectory_info_1(info);
9162 if (!alloc_buffer_size(buffer, *needed)) {
9164 return WERR_INSUFFICIENT_BUFFER;
9167 smb_io_printprocessordirectory_1("", buffer, info, 0);
9171 if (*needed > offered)
9172 return WERR_INSUFFICIENT_BUFFER;
9177 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9179 uint32 level = q_u->level;
9180 NEW_BUFFER *buffer = NULL;
9181 uint32 offered = q_u->offered;
9182 uint32 *needed = &r_u->needed;
9185 /* that's an [in out] buffer */
9186 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9187 buffer = r_u->buffer;
9189 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9195 result = getprintprocessordirectory_level_1
9196 (&q_u->name, &q_u->environment, buffer, offered, needed);
9199 result = WERR_UNKNOWN_LEVEL;
9207 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9208 SPOOL_R_REPLYOPENPRINTER *r_u)
9210 DEBUG(5,("_spoolss_replyopenprinter\n"));
9212 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9217 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9218 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9220 DEBUG(5,("_spoolss_replycloseprinter\n"));