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 look for a printer object cached on an open printer handle
277 ****************************************************************************/
279 WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2,
280 const char *printername )
284 DEBUG(10,("find_printer_in_print_hnd_cache: printer [%s]\n", printername));
286 for ( p=printers_list; p; p=p->next )
288 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
290 && StrCaseCmp(p->dev.handlename, printername) == 0 )
292 DEBUG(10,("Found printer\n"));
293 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
299 return WERR_INVALID_PRINTER_NAME;
302 /****************************************************************************
303 destroy any cached printer_info_2 structures on open handles
304 ****************************************************************************/
306 void invalidate_printer_hnd_cache( char *printername )
310 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
312 for ( p=printers_list; p; p=p->next )
314 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
315 && StrCaseCmp(p->dev.handlename, printername)==0)
317 DEBUG(10,("invalidating printer_info cache for handl:\n"));
318 free_a_printer( &p->printer_info, 2 );
319 p->printer_info = NULL;
325 /****************************************************************************
326 Close printer index by handle.
327 ****************************************************************************/
329 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
331 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
334 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
338 close_policy_hnd(p, hnd);
343 /****************************************************************************
344 Delete a printer given a handle.
345 ****************************************************************************/
347 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
349 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
352 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
357 * It turns out that Windows allows delete printer on a handle
358 * opened by an admin user, then used on a pipe handle created
359 * by an anonymous user..... but they're working on security.... riiight !
363 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
364 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
365 return WERR_ACCESS_DENIED;
369 /* Check calling user has permission to delete printer. Note that
370 since we set the snum parameter to -1 only administrators can
371 delete the printer. This stops people with the Full Control
372 permission from deleting the printer. */
374 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
375 DEBUG(3, ("printer delete denied by security descriptor\n"));
376 return WERR_ACCESS_DENIED;
380 if (del_a_printer(Printer->dev.handlename) != 0) {
381 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
385 if (*lp_deleteprinter_cmd()) {
387 char *cmd = lp_deleteprinter_cmd();
392 /* Printer->dev.handlename equals portname equals sharename */
393 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
394 Printer->dev.handlename);
396 DEBUG(10,("Running [%s]\n", command));
397 ret = smbrun(command, NULL);
399 return WERR_BADFID; /* What to return here? */
401 DEBUGADD(10,("returned [%d]\n", ret));
403 /* Send SIGHUP to process group... is there a better way? */
406 /* go ahead and re-read the services immediately */
407 reload_services( False );
409 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
410 return WERR_ACCESS_DENIED;
416 /****************************************************************************
417 Return the snum of a printer corresponding to an handle.
418 ****************************************************************************/
420 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
422 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
425 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
429 switch (Printer->printer_type) {
430 case PRINTER_HANDLE_IS_PRINTER:
431 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
432 *number = print_queue_snum(Printer->dev.handlename);
433 return (*number != -1);
434 case PRINTER_HANDLE_IS_PRINTSERVER:
441 /****************************************************************************
442 Set printer handle type.
443 Check if it's \\server or \\server\printer
444 ****************************************************************************/
446 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
448 DEBUG(3,("Setting printer type=%s\n", handlename));
450 if ( strlen(handlename) < 3 ) {
451 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
455 /* it's a print server */
456 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
457 DEBUGADD(4,("Printer is a print server\n"));
458 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
462 DEBUGADD(4,("Printer is a printer\n"));
463 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
469 /****************************************************************************
470 Set printer handle name.
471 ****************************************************************************/
473 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
476 int n_services=lp_numservices();
481 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
483 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
484 ZERO_STRUCT(Printer->dev.printerservername);
485 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
489 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
492 if (*handlename=='\\') {
493 aprinter=strchr_m(handlename+2, '\\');
500 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
503 * The original code allowed smbd to store a printer name that
504 * was different from the share name. This is not possible
505 * anymore, so I've simplified this loop greatly. Here
506 * we are just verifying that the printer name is a valid
507 * printer service defined in smb.conf
508 * --jerry [Fri Feb 15 11:17:46 CST 2002]
511 for (snum=0; snum<n_services; snum++) {
513 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
516 fstrcpy(sname, lp_servicename(snum));
518 DEBUGADD(5,("share:%s\n",sname));
520 if (! StrCaseCmp(sname, aprinter)) {
529 DEBUGADD(4,("Printer not found\n"));
533 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
535 ZERO_STRUCT(Printer->dev.handlename);
536 fstrcpy(Printer->dev.handlename, sname);
541 /****************************************************************************
542 Find first available printer slot. creates a printer handle for you.
543 ****************************************************************************/
545 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
547 Printer_entry *new_printer;
549 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
551 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
554 ZERO_STRUCTP(new_printer);
556 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
557 SAFE_FREE(new_printer);
561 /* Add to the internal list. */
562 DLIST_ADD(printers_list, new_printer);
564 new_printer->notify.option=NULL;
566 if ( !(new_printer->ctx = talloc_init("Printer Entry [0x%x]", (uint32)hnd)) ) {
567 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
568 close_printer_handle(p, hnd);
572 if (!set_printer_hnd_printertype(new_printer, name)) {
573 close_printer_handle(p, hnd);
577 if (!set_printer_hnd_name(new_printer, name)) {
578 close_printer_handle(p, hnd);
582 new_printer->access_granted = access_granted;
584 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
589 /****************************************************************************
590 Allocate more memory for a BUFFER.
591 ****************************************************************************/
593 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
601 /* damn, I'm doing the reverse operation of prs_grow() :) */
602 if (buffer_size < prs_data_size(ps))
605 extra_space = buffer_size - prs_data_size(ps);
608 * save the offset and move to the end of the buffer
609 * prs_grow() checks the extra_space against the offset
611 old_offset=prs_offset(ps);
612 prs_set_offset(ps, prs_data_size(ps));
614 if (!prs_grow(ps, extra_space))
617 prs_set_offset(ps, old_offset);
619 buffer->string_at_end=prs_data_size(ps);
624 /***************************************************************************
625 check to see if the client motify handle is monitoring the notification
626 given by (notify_type, notify_field).
627 **************************************************************************/
629 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
635 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
638 SPOOL_NOTIFY_OPTION *option = p->notify.option;
642 * Flags should always be zero when the change notify
643 * is registered by the client's spooler. A user Win32 app
644 * might use the flags though instead of the NOTIFY_OPTION_INFO
649 return is_monitoring_event_flags(
650 p->notify.flags, notify_type, notify_field);
652 for (i = 0; i < option->count; i++) {
654 /* Check match for notify_type */
656 if (option->ctr.type[i].type != notify_type)
659 /* Check match for field */
661 for (j = 0; j < option->ctr.type[i].count; j++) {
662 if (option->ctr.type[i].fields[j] == notify_field) {
668 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
669 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
670 p->dev.handlename : p->dev.printerservername,
671 notify_type, notify_field));
676 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
678 static void notify_one_value(struct spoolss_notify_msg *msg,
679 SPOOL_NOTIFY_INFO_DATA *data,
682 data->notify_data.value[0] = msg->notify.value[0];
683 data->notify_data.value[1] = 0;
686 static void notify_string(struct spoolss_notify_msg *msg,
687 SPOOL_NOTIFY_INFO_DATA *data,
692 /* The length of the message includes the trailing \0 */
694 init_unistr2(&unistr, msg->notify.data, msg->len);
696 data->notify_data.data.length = msg->len * 2;
697 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
699 if (!data->notify_data.data.string) {
700 data->notify_data.data.length = 0;
704 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
707 static void notify_system_time(struct spoolss_notify_msg *msg,
708 SPOOL_NOTIFY_INFO_DATA *data,
714 if (msg->len != sizeof(time_t)) {
715 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
720 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
721 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
725 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
726 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
730 if (!spoolss_io_system_time("", &ps, 0, &systime))
733 data->notify_data.data.length = prs_offset(&ps);
734 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
736 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
741 struct notify2_message_table {
743 void (*fn)(struct spoolss_notify_msg *msg,
744 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
747 static struct notify2_message_table printer_notify_table[] = {
748 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
749 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
750 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
751 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
752 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
753 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
754 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
755 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
756 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
757 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
758 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
759 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
760 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
761 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
762 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
763 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
764 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
765 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
766 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
769 static struct notify2_message_table job_notify_table[] = {
770 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
771 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
772 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
773 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
774 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
775 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
776 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
777 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
778 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
779 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
780 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
781 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
782 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
783 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
784 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
785 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
786 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
787 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
788 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
789 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
790 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
791 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
792 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
793 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
797 /***********************************************************************
798 Allocate talloc context for container object
799 **********************************************************************/
801 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
806 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
811 /***********************************************************************
812 release all allocated memory and zero out structure
813 **********************************************************************/
815 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
821 talloc_destroy(ctr->ctx);
828 /***********************************************************************
829 **********************************************************************/
831 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
839 /***********************************************************************
840 **********************************************************************/
842 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
844 if ( !ctr || !ctr->msg_groups )
847 if ( idx >= ctr->num_groups )
850 return &ctr->msg_groups[idx];
854 /***********************************************************************
855 How many groups of change messages do we have ?
856 **********************************************************************/
858 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
863 return ctr->num_groups;
866 /***********************************************************************
867 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
868 **********************************************************************/
870 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
872 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
873 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
874 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
880 /* loop over all groups looking for a matching printer name */
882 for ( i=0; i<ctr->num_groups; i++ ) {
883 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
887 /* add a new group? */
889 if ( i == ctr->num_groups ) {
892 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
893 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
896 ctr->msg_groups = groups;
898 /* clear the new entry and set the printer name */
900 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
901 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
904 /* add the change messages; 'i' is the correct index now regardless */
906 msg_grp = &ctr->msg_groups[i];
910 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
911 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
914 msg_grp->msgs = msg_list;
916 new_slot = msg_grp->num_msgs-1;
917 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
919 /* need to allocate own copy of data */
922 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
924 return ctr->num_groups;
927 /***********************************************************************
928 Send a change notication message on all handles which have a call
930 **********************************************************************/
932 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
935 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
936 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
937 SPOOLSS_NOTIFY_MSG *messages;
938 int sending_msg_count;
941 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
945 messages = msg_group->msgs;
948 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
952 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
954 /* loop over all printers */
956 for (p = printers_list; p; p = p->next) {
957 SPOOL_NOTIFY_INFO_DATA *data;
962 /* Is there notification on this handle? */
964 if ( !p->notify.client_connected )
967 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
969 /* For this printer? Print servers always receive
972 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
973 ( !strequal(msg_group->printername, p->dev.handlename) ) )
976 DEBUG(10,("Our printer\n"));
978 /* allocate the max entries possible */
980 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
985 /* build the array of change notifications */
987 sending_msg_count = 0;
989 for ( i=0; i<msg_group->num_msgs; i++ ) {
990 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
992 /* Are we monitoring this event? */
994 if (!is_monitoring_event(p, msg->type, msg->field))
1000 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
1001 msg->type, msg->field, p->dev.handlename));
1004 * if the is a printer notification handle and not a job notification
1005 * type, then set the id to 0. Other wise just use what was specified
1008 * When registering change notification on a print server handle
1009 * we always need to send back the id (snum) matching the printer
1010 * for which the change took place. For change notify registered
1011 * on a printer handle, this does not matter and the id should be 0.
1016 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1022 /* Convert unix jobid to smb jobid */
1024 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1025 id = sysjob_to_jobid(msg->id);
1028 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1033 construct_info_data( &data[data_len], msg->type, msg->field, id );
1036 case PRINTER_NOTIFY_TYPE:
1037 if ( printer_notify_table[msg->field].fn )
1038 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1041 case JOB_NOTIFY_TYPE:
1042 if ( job_notify_table[msg->field].fn )
1043 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1047 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1054 if ( sending_msg_count ) {
1055 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1056 data_len, data, p->notify.change, 0 );
1061 DEBUG(8,("send_notify2_changes: Exit...\n"));
1065 /***********************************************************************
1066 **********************************************************************/
1068 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1071 uint32 tv_sec, tv_usec;
1074 /* Unpack message */
1076 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1079 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1081 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1084 tdb_unpack((char *)buf + offset, len - offset, "dd",
1085 &msg->notify.value[0], &msg->notify.value[1]);
1087 tdb_unpack((char *)buf + offset, len - offset, "B",
1088 &msg->len, &msg->notify.data);
1090 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1091 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1093 tv->tv_sec = tv_sec;
1094 tv->tv_usec = tv_usec;
1097 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1098 msg->notify.value[1]));
1100 dump_data(3, msg->notify.data, msg->len);
1105 /* ENUMJOB last timestamp list. */
1107 struct ejts_list *next, *prev;
1112 static struct ejts_list *ejts_head;
1114 static struct ejts_list *find_enumjobs_timestamp(const char *printer_name)
1116 struct ejts_list *ejtsl;
1118 for( ejtsl = ejts_head; ejtsl; ejtsl = ejtsl->next)
1119 if (strequal(ejtsl->printer_name, printer_name))
1124 static void set_enumjobs_timestamp(int snum)
1126 const char *printer_name = lp_const_servicename(snum);
1127 struct ejts_list *ejtsl = find_enumjobs_timestamp(printer_name);
1130 ejtsl = (struct ejts_list *)malloc(sizeof(struct ejts_list));
1133 ejtsl->printer_name = strdup(printer_name);
1134 if (!ejtsl->printer_name) {
1138 DLIST_ADD(ejts_head, ejtsl);
1141 gettimeofday(&ejtsl->tv, NULL);
1144 static int timeval_diff(struct timeval *tv1, struct timeval *tv2)
1146 if (tv1->tv_sec > tv2->tv_sec)
1148 if (tv1->tv_sec < tv2->tv_sec)
1150 if (tv1->tv_usec > tv2->tv_usec)
1152 if (tv1->tv_usec < tv2->tv_usec)
1157 /********************************************************************
1158 Receive a notify2 message list
1159 ********************************************************************/
1161 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1163 size_t msg_count, i;
1164 char *buf = (char *)msg;
1167 SPOOLSS_NOTIFY_MSG notify;
1168 SPOOLSS_NOTIFY_MSG_CTR messages;
1172 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1176 msg_count = IVAL(buf, 0);
1179 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1181 if (msg_count == 0) {
1182 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1186 /* initialize the container */
1188 ZERO_STRUCT( messages );
1189 notify_msg_ctr_init( &messages );
1192 * build message groups for each printer identified
1193 * in a change_notify msg. Remember that a PCN message
1194 * includes the handle returned for the srv_spoolss_replyopenprinter()
1195 * call. Therefore messages are grouped according to printer handle.
1198 for ( i=0; i<msg_count; i++ ) {
1199 struct timeval msg_tv;
1201 if (msg_ptr + 4 - buf > len) {
1202 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1206 msg_len = IVAL(msg_ptr,0);
1209 if (msg_ptr + msg_len - buf > len) {
1210 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1214 /* unpack messages */
1216 ZERO_STRUCT( notify );
1217 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1220 /* See if it is still relevent. */
1221 if (notify.type == JOB_NOTIFY_TYPE) {
1222 BOOL status_is_deleting = False;
1224 if (notify.field == JOB_NOTIFY_STATUS && (notify.notify.value[0] & (JOB_STATUS_DELETING|JOB_STATUS_DELETED)))
1225 status_is_deleting = True;
1227 if (!status_is_deleting) {
1228 struct ejts_list *ejtsl = find_enumjobs_timestamp(notify.printer);
1230 if (ejtsl && (timeval_diff(&ejtsl->tv, &msg_tv) > 0)) {
1232 DEBUG(10, ("receive_notify2_message_list: enumjobs ts = %u, %u, msg ts = %u, %u discarding\n",
1233 (unsigned int)ejtsl->tv.tv_sec, (unsigned int)ejtsl->tv.tv_usec,
1234 (unsigned int)msg_tv.tv_sec, (unsigned int)msg_tv.tv_usec ));
1236 /* Message no longer relevent. Ignore it. */
1237 if ( notify.len != 0 )
1238 SAFE_FREE( notify.notify.data );
1243 /* add to correct list in container */
1245 notify_msg_ctr_addmsg( &messages, ¬ify );
1247 /* free memory that might have been allocated by notify2_unpack_msg() */
1249 if ( notify.len != 0 )
1250 SAFE_FREE( notify.notify.data );
1253 /* process each group of messages */
1255 num_groups = notify_msg_ctr_numgroups( &messages );
1256 for ( i=0; i<num_groups; i++ )
1257 send_notify2_changes( &messages, i );
1262 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1264 notify_msg_ctr_destroy( &messages );
1269 /********************************************************************
1270 Send a message to ourself about new driver being installed
1271 so we can upgrade the information for each printer bound to this
1273 ********************************************************************/
1275 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1277 int len = strlen(drivername);
1282 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1285 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1290 /**********************************************************************
1291 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1292 over all printers, upgrading ones as necessary
1293 **********************************************************************/
1295 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1299 int n_services = lp_numservices();
1301 len = MIN(len,sizeof(drivername)-1);
1302 strncpy(drivername, buf, len);
1304 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1306 /* Iterate the printer list */
1308 for (snum=0; snum<n_services; snum++)
1310 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1313 NT_PRINTER_INFO_LEVEL *printer = NULL;
1315 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1316 if (!W_ERROR_IS_OK(result))
1319 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1321 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1323 /* all we care about currently is the change_id */
1325 result = mod_a_printer(*printer, 2);
1326 if (!W_ERROR_IS_OK(result)) {
1327 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1328 dos_errstr(result)));
1332 free_a_printer(&printer, 2);
1339 /********************************************************************
1340 Update the cache for all printq's with a registered client
1342 ********************************************************************/
1344 void update_monitored_printq_cache( void )
1346 Printer_entry *printer = printers_list;
1349 /* loop through all printers and update the cache where
1350 client_connected == True */
1353 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1354 && printer->notify.client_connected )
1356 snum = print_queue_snum(printer->dev.handlename);
1357 print_queue_status( snum, NULL, NULL );
1360 printer = printer->next;
1365 /********************************************************************
1366 Send a message to ourself about new driver being installed
1367 so we can upgrade the information for each printer bound to this
1369 ********************************************************************/
1371 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1373 int len = strlen(drivername);
1378 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1381 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1386 /**********************************************************************
1387 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1388 over all printers, resetting printer data as neessary
1389 **********************************************************************/
1391 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1395 int n_services = lp_numservices();
1397 len = MIN( len, sizeof(drivername)-1 );
1398 strncpy( drivername, buf, len );
1400 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1402 /* Iterate the printer list */
1404 for ( snum=0; snum<n_services; snum++ )
1406 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1409 NT_PRINTER_INFO_LEVEL *printer = NULL;
1411 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1412 if ( !W_ERROR_IS_OK(result) )
1416 * if the printer is bound to the driver,
1417 * then reset to the new driver initdata
1420 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1422 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1424 if ( !set_driver_init(printer, 2) ) {
1425 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1426 printer->info_2->printername, printer->info_2->drivername));
1429 result = mod_a_printer( *printer, 2 );
1430 if ( !W_ERROR_IS_OK(result) ) {
1431 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1432 get_dos_error_msg(result)));
1436 free_a_printer( &printer, 2 );
1445 /********************************************************************
1446 Copy routines used by convert_to_openprinterex()
1447 *******************************************************************/
1449 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1457 DEBUG (8,("dup_devmode\n"));
1459 /* bulk copy first */
1461 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1465 /* dup the pointer members separately */
1467 len = unistrlen(devmode->devicename.buffer);
1469 d->devicename.buffer = talloc(ctx, len*2);
1470 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1475 len = unistrlen(devmode->formname.buffer);
1477 d->devicename.buffer = talloc(ctx, len*2);
1478 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1482 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1487 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1489 if (!new_ctr || !ctr)
1492 DEBUG(8,("copy_devmode_ctr\n"));
1494 new_ctr->size = ctr->size;
1495 new_ctr->devmode_ptr = ctr->devmode_ptr;
1497 if(ctr->devmode_ptr)
1498 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1501 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1503 if (!new_def || !def)
1506 DEBUG(8,("copy_printer_defaults\n"));
1508 new_def->datatype_ptr = def->datatype_ptr;
1510 if (def->datatype_ptr)
1511 copy_unistr2(&new_def->datatype, &def->datatype);
1513 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1515 new_def->access_required = def->access_required;
1518 /********************************************************************
1519 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1520 * SPOOL_Q_OPEN_PRINTER_EX structure
1521 ********************************************************************/
1523 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1525 if (!q_u_ex || !q_u)
1528 DEBUG(8,("convert_to_openprinterex\n"));
1530 q_u_ex->printername_ptr = q_u->printername_ptr;
1532 if (q_u->printername_ptr)
1533 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1535 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1538 /********************************************************************
1539 * spoolss_open_printer
1541 * called from the spoolss dispatcher
1542 ********************************************************************/
1544 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1546 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1547 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1552 ZERO_STRUCT(q_u_ex);
1553 ZERO_STRUCT(r_u_ex);
1555 /* convert the OpenPrinter() call to OpenPrinterEx() */
1557 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1559 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1561 /* convert back to OpenPrinter() */
1563 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1568 /********************************************************************
1569 * spoolss_open_printer
1571 * If the openprinterex rpc call contains a devmode,
1572 * it's a per-user one. This per-user devmode is derivated
1573 * from the global devmode. Openprinterex() contains a per-user
1574 * devmode for when you do EMF printing and spooling.
1575 * In the EMF case, the NT workstation is only doing half the job
1576 * of rendering the page. The other half is done by running the printer
1577 * driver on the server.
1578 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1579 * The EMF file only contains what is to be printed on the page.
1580 * So in order for the server to know how to print, the NT client sends
1581 * a devicemode attached to the openprinterex call.
1582 * But this devicemode is short lived, it's only valid for the current print job.
1584 * If Samba would have supported EMF spooling, this devicemode would
1585 * have been attached to the handle, to sent it to the driver to correctly
1586 * rasterize the EMF file.
1588 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1589 * we just act as a pass-thru between windows and the printer.
1591 * In order to know that Samba supports only RAW spooling, NT has to call
1592 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1593 * and until NT sends a RAW job, we refuse it.
1595 * But to call getprinter() or startdoc(), you first need a valid handle,
1596 * and to get an handle you have to call openprintex(). Hence why you have
1597 * a devicemode in the openprinterex() call.
1600 * Differences between NT4 and NT 2000.
1603 * On NT4, you only have a global devicemode. This global devicemode can be changed
1604 * by the administrator (or by a user with enough privs). Everytime a user
1605 * wants to print, the devicemode is resetted to the default. In Word, everytime
1606 * you print, the printer's characteristics are always reset to the global devicemode.
1610 * In W2K, there is the notion of per-user devicemode. The first time you use
1611 * a printer, a per-user devicemode is build from the global devicemode.
1612 * If you change your per-user devicemode, it is saved in the registry, under the
1613 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1614 * printer preferences available.
1616 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1617 * on the General Tab of the printer properties windows.
1619 * To change the global devicemode: it's the "Printing Defaults..." button
1620 * on the Advanced Tab of the printer properties window.
1623 ********************************************************************/
1625 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1627 UNISTR2 *printername = NULL;
1628 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1629 POLICY_HND *handle = &r_u->handle;
1633 struct current_user user;
1634 Printer_entry *Printer=NULL;
1636 if (q_u->printername_ptr != 0)
1637 printername = &q_u->printername;
1639 if (printername == NULL)
1640 return WERR_INVALID_PRINTER_NAME;
1642 /* some sanity check because you can open a printer or a print server */
1643 /* aka: \\server\printer or \\server */
1644 unistr2_to_ascii(name, printername, sizeof(name)-1);
1646 DEBUGADD(3,("checking name: %s\n",name));
1648 if (!open_printer_hnd(p, handle, name, 0))
1649 return WERR_INVALID_PRINTER_NAME;
1651 Printer=find_printer_index_by_hnd(p, handle);
1653 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1654 Can't find printer handle we created for printer %s\n", name ));
1655 close_printer_handle(p,handle);
1656 return WERR_INVALID_PRINTER_NAME;
1659 get_current_user(&user, p);
1662 * First case: the user is opening the print server:
1664 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1665 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1667 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1668 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1669 * or if the user is listed in the smb.conf printer admin parameter.
1671 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1672 * client view printer folder, but does not show the MSAPW.
1674 * Note: this test needs code to check access rights here too. Jeremy
1675 * could you look at this?
1677 * Second case: the user is opening a printer:
1678 * NT doesn't let us connect to a printer if the connecting user
1679 * doesn't have print permission.
1682 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1684 /* Printserver handles use global struct... */
1688 /* Map standard access rights to object specific access rights */
1690 se_map_standard(&printer_default->access_required,
1691 &printserver_std_mapping);
1693 /* Deny any object specific bits that don't apply to print
1694 servers (i.e printer and job specific bits) */
1696 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1698 if (printer_default->access_required &
1699 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1700 DEBUG(3, ("access DENIED for non-printserver bits"));
1701 close_printer_handle(p, handle);
1702 return WERR_ACCESS_DENIED;
1705 /* Allow admin access */
1707 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1709 if (!lp_ms_add_printer_wizard()) {
1710 close_printer_handle(p, handle);
1711 return WERR_ACCESS_DENIED;
1714 /* if the user is not root and not a printer admin, then fail */
1717 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1719 close_printer_handle(p, handle);
1720 return WERR_ACCESS_DENIED;
1723 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1727 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1730 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1731 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1733 /* We fall through to return WERR_OK */
1738 /* NT doesn't let us connect to a printer if the connecting user
1739 doesn't have print permission. */
1741 if (!get_printer_snum(p, handle, &snum)) {
1742 close_printer_handle(p, handle);
1746 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1748 /* map an empty access mask to the minimum access mask */
1749 if (printer_default->access_required == 0x0)
1750 printer_default->access_required = PRINTER_ACCESS_USE;
1753 * If we are not serving the printer driver for this printer,
1754 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1755 * will keep NT clients happy --jerry
1758 if (lp_use_client_driver(snum)
1759 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1761 printer_default->access_required = PRINTER_ACCESS_USE;
1764 /* check smb.conf parameters and the the sec_desc */
1766 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1767 DEBUG(3, ("access DENIED for printer open\n"));
1768 close_printer_handle(p, handle);
1769 return WERR_ACCESS_DENIED;
1772 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1773 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1774 close_printer_handle(p, handle);
1775 return WERR_ACCESS_DENIED;
1778 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1779 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1781 printer_default->access_required = PRINTER_ACCESS_USE;
1783 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1784 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1788 Printer->access_granted = printer_default->access_required;
1791 * If the client sent a devmode in the OpenPrinter() call, then
1792 * save it here in case we get a job submission on this handle
1795 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1796 && q_u->printer_default.devmode_cont.devmode_ptr )
1798 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1799 &Printer->nt_devmode );
1802 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1803 optimization in Windows 2000 clients --jerry */
1805 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1806 && (RA_WIN2K == get_remote_arch()) )
1808 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1815 /****************************************************************************
1816 ****************************************************************************/
1818 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1819 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1825 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1834 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1835 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1841 printer->info_3=NULL;
1842 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1846 printer->info_6=NULL;
1847 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1857 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1858 NT_DEVICEMODE **pp_nt_devmode)
1860 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1863 * Ensure nt_devmode is a valid pointer
1864 * as we will be overwriting it.
1867 if (nt_devmode == NULL) {
1868 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1869 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1873 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1874 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1876 nt_devmode->specversion=devmode->specversion;
1877 nt_devmode->driverversion=devmode->driverversion;
1878 nt_devmode->size=devmode->size;
1879 nt_devmode->fields=devmode->fields;
1880 nt_devmode->orientation=devmode->orientation;
1881 nt_devmode->papersize=devmode->papersize;
1882 nt_devmode->paperlength=devmode->paperlength;
1883 nt_devmode->paperwidth=devmode->paperwidth;
1884 nt_devmode->scale=devmode->scale;
1885 nt_devmode->copies=devmode->copies;
1886 nt_devmode->defaultsource=devmode->defaultsource;
1887 nt_devmode->printquality=devmode->printquality;
1888 nt_devmode->color=devmode->color;
1889 nt_devmode->duplex=devmode->duplex;
1890 nt_devmode->yresolution=devmode->yresolution;
1891 nt_devmode->ttoption=devmode->ttoption;
1892 nt_devmode->collate=devmode->collate;
1894 nt_devmode->logpixels=devmode->logpixels;
1895 nt_devmode->bitsperpel=devmode->bitsperpel;
1896 nt_devmode->pelswidth=devmode->pelswidth;
1897 nt_devmode->pelsheight=devmode->pelsheight;
1898 nt_devmode->displayflags=devmode->displayflags;
1899 nt_devmode->displayfrequency=devmode->displayfrequency;
1900 nt_devmode->icmmethod=devmode->icmmethod;
1901 nt_devmode->icmintent=devmode->icmintent;
1902 nt_devmode->mediatype=devmode->mediatype;
1903 nt_devmode->dithertype=devmode->dithertype;
1904 nt_devmode->reserved1=devmode->reserved1;
1905 nt_devmode->reserved2=devmode->reserved2;
1906 nt_devmode->panningwidth=devmode->panningwidth;
1907 nt_devmode->panningheight=devmode->panningheight;
1910 * Only change private and driverextra if the incoming devmode
1911 * has a new one. JRA.
1914 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1915 SAFE_FREE(nt_devmode->private);
1916 nt_devmode->driverextra=devmode->driverextra;
1917 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1919 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1922 *pp_nt_devmode = nt_devmode;
1927 /********************************************************************
1928 * _spoolss_enddocprinter_internal.
1929 ********************************************************************/
1931 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1933 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1937 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1941 if (!get_printer_snum(p, handle, &snum))
1944 Printer->document_started=False;
1945 print_job_end(snum, Printer->jobid,True);
1946 /* error codes unhandled so far ... */
1951 /********************************************************************
1952 * api_spoolss_closeprinter
1953 ********************************************************************/
1955 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1957 POLICY_HND *handle = &q_u->handle;
1959 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1961 if (Printer && Printer->document_started)
1962 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1964 if (!close_printer_handle(p, handle))
1967 /* clear the returned printer handle. Observed behavior
1968 from Win2k server. Don't think this really matters.
1969 Previous code just copied the value of the closed
1972 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1977 /********************************************************************
1978 * api_spoolss_deleteprinter
1980 ********************************************************************/
1982 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1984 POLICY_HND *handle = &q_u->handle;
1985 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1988 if (Printer && Printer->document_started)
1989 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1991 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1993 result = delete_printer_handle(p, handle);
1995 update_c_setprinter(False);
2000 /*******************************************************************
2001 * static function to lookup the version id corresponding to an
2002 * long architecture string
2003 ******************************************************************/
2005 static int get_version_id (char * arch)
2008 struct table_node archi_table[]= {
2010 {"Windows 4.0", "WIN40", 0 },
2011 {"Windows NT x86", "W32X86", 2 },
2012 {"Windows NT R4000", "W32MIPS", 2 },
2013 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2014 {"Windows NT PowerPC", "W32PPC", 2 },
2018 for (i=0; archi_table[i].long_archi != NULL; i++)
2020 if (strcmp(arch, archi_table[i].long_archi) == 0)
2021 return (archi_table[i].version);
2027 /********************************************************************
2028 * _spoolss_deleteprinterdriver
2029 ********************************************************************/
2031 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2035 NT_PRINTER_DRIVER_INFO_LEVEL info;
2036 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2038 struct current_user user;
2040 WERROR status_win2k = WERR_ACCESS_DENIED;
2042 get_current_user(&user, p);
2044 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2045 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2047 /* check that we have a valid driver name first */
2049 if ((version=get_version_id(arch)) == -1)
2050 return WERR_INVALID_ENVIRONMENT;
2053 ZERO_STRUCT(info_win2k);
2055 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2057 /* try for Win2k driver if "Windows NT x86" */
2059 if ( version == 2 ) {
2061 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2062 status = WERR_UNKNOWN_PRINTER_DRIVER;
2066 /* otherwise it was a failure */
2068 status = WERR_UNKNOWN_PRINTER_DRIVER;
2074 if (printer_driver_in_use(info.info_3)) {
2075 status = WERR_PRINTER_DRIVER_IN_USE;
2081 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2083 /* if we get to here, we now have 2 driver info structures to remove */
2084 /* remove the Win2k driver first*/
2086 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2087 free_a_printer_driver( info_win2k, 3 );
2089 /* this should not have failed---if it did, report to client */
2090 if ( !W_ERROR_IS_OK(status_win2k) )
2095 status = delete_printer_driver(info.info_3, &user, version, False);
2097 /* if at least one of the deletes succeeded return OK */
2099 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2103 free_a_printer_driver( info, 3 );
2108 /********************************************************************
2109 * spoolss_deleteprinterdriverex
2110 ********************************************************************/
2112 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2116 NT_PRINTER_DRIVER_INFO_LEVEL info;
2117 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2119 uint32 flags = q_u->delete_flags;
2121 struct current_user user;
2123 WERROR status_win2k = WERR_ACCESS_DENIED;
2125 get_current_user(&user, p);
2127 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2128 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2130 /* check that we have a valid driver name first */
2131 if ((version=get_version_id(arch)) == -1) {
2132 /* this is what NT returns */
2133 return WERR_INVALID_ENVIRONMENT;
2136 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2137 version = q_u->version;
2140 ZERO_STRUCT(info_win2k);
2142 status = get_a_printer_driver(&info, 3, driver, arch, version);
2144 if ( !W_ERROR_IS_OK(status) )
2147 * if the client asked for a specific version,
2148 * or this is something other than Windows NT x86,
2152 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2155 /* try for Win2k driver if "Windows NT x86" */
2158 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2159 status = WERR_UNKNOWN_PRINTER_DRIVER;
2164 if ( printer_driver_in_use(info.info_3) ) {
2165 status = WERR_PRINTER_DRIVER_IN_USE;
2170 * we have a couple of cases to consider.
2171 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2172 * then the delete should fail if **any** files overlap with
2174 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2175 * non-overlapping files
2176 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2177 * is set, the do not delete any files
2178 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2181 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2183 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2185 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2186 /* no idea of the correct error here */
2187 status = WERR_ACCESS_DENIED;
2192 /* also check for W32X86/3 if necessary; maybe we already have? */
2194 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2195 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2198 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2199 /* no idea of the correct error here */
2200 free_a_printer_driver( info_win2k, 3 );
2201 status = WERR_ACCESS_DENIED;
2205 /* if we get to here, we now have 2 driver info structures to remove */
2206 /* remove the Win2k driver first*/
2208 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2209 free_a_printer_driver( info_win2k, 3 );
2211 /* this should not have failed---if it did, report to client */
2213 if ( !W_ERROR_IS_OK(status_win2k) )
2218 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2220 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2223 free_a_printer_driver( info, 3 );
2229 /****************************************************************************
2230 Internal routine for retreiving printerdata
2231 ***************************************************************************/
2233 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2234 const char *key, const char *value, uint32 *type, uint8 **data,
2235 uint32 *needed, uint32 in_size )
2237 REGISTRY_VALUE *val;
2240 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2241 return WERR_BADFILE;
2243 *type = regval_type( val );
2245 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2247 size = regval_size( val );
2249 /* copy the min(in_size, len) */
2252 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2254 /* special case for 0 length values */
2256 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2260 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2269 DEBUG(5,("get_printer_dataex: copy done\n"));
2274 /****************************************************************************
2275 Internal routine for removing printerdata
2276 ***************************************************************************/
2278 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2280 return delete_printer_data( printer->info_2, key, value );
2283 /****************************************************************************
2284 Internal routine for storing printerdata
2285 ***************************************************************************/
2287 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2288 uint32 type, uint8 *data, int real_len )
2290 delete_printer_data( printer->info_2, key, value );
2292 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2295 /********************************************************************
2296 GetPrinterData on a printer server Handle.
2297 ********************************************************************/
2299 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2303 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2305 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2307 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2313 if (!StrCaseCmp(value, "BeepEnabled")) {
2315 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2317 SIVAL(*data, 0, 0x00);
2322 if (!StrCaseCmp(value, "EventLog")) {
2324 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2326 /* formally was 0x1b */
2327 SIVAL(*data, 0, 0x0);
2332 if (!StrCaseCmp(value, "NetPopup")) {
2334 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2336 SIVAL(*data, 0, 0x00);
2341 if (!StrCaseCmp(value, "MajorVersion")) {
2343 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2346 /* Windows NT 4.0 seems to not allow uploading of drivers
2347 to a server that reports 0x3 as the MajorVersion.
2348 need to investigate more how Win2k gets around this .
2351 if ( RA_WINNT == get_remote_arch() )
2360 if (!StrCaseCmp(value, "MinorVersion")) {
2362 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2370 * uint32 size = 0x114
2372 * uint32 minor = [0|1]
2373 * uint32 build = [2195|2600]
2374 * extra unicode string = e.g. "Service Pack 3"
2376 if (!StrCaseCmp(value, "OSVersion")) {
2380 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2382 ZERO_STRUCTP( *data );
2384 SIVAL(*data, 0, *needed); /* size */
2385 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2387 SIVAL(*data, 12, 2195); /* build */
2389 /* leave extra string empty */
2395 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2398 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2400 *needed = 2*(strlen(string)+1);
2401 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2403 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2405 /* it's done by hand ready to go on the wire */
2406 for (i=0; i<strlen(string); i++) {
2407 (*data)[2*i]=string[i];
2408 (*data)[2*i+1]='\0';
2413 if (!StrCaseCmp(value, "Architecture")) {
2414 pstring string="Windows NT x86";
2416 *needed = 2*(strlen(string)+1);
2417 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2419 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2420 for (i=0; i<strlen(string); i++) {
2421 (*data)[2*i]=string[i];
2422 (*data)[2*i+1]='\0';
2427 if (!StrCaseCmp(value, "DsPresent")) {
2429 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2431 SIVAL(*data, 0, 0x01);
2436 if (!StrCaseCmp(value, "DNSMachineName")) {
2439 if (!get_myfullname(hostname))
2440 return WERR_BADFILE;
2442 *needed = 2*(strlen(hostname)+1);
2443 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2445 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2446 for (i=0; i<strlen(hostname); i++) {
2447 (*data)[2*i]=hostname[i];
2448 (*data)[2*i+1]='\0';
2454 return WERR_BADFILE;
2457 /********************************************************************
2458 * spoolss_getprinterdata
2459 ********************************************************************/
2461 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2463 POLICY_HND *handle = &q_u->handle;
2464 UNISTR2 *valuename = &q_u->valuename;
2465 uint32 in_size = q_u->size;
2466 uint32 *type = &r_u->type;
2467 uint32 *out_size = &r_u->size;
2468 uint8 **data = &r_u->data;
2469 uint32 *needed = &r_u->needed;
2472 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2473 NT_PRINTER_INFO_LEVEL *printer = NULL;
2477 * Reminder: when it's a string, the length is in BYTES
2478 * even if UNICODE is negociated.
2483 *out_size = in_size;
2485 /* in case of problem, return some default values */
2490 DEBUG(4,("_spoolss_getprinterdata\n"));
2493 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2494 status = WERR_BADFID;
2498 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2500 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2501 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2504 if ( !get_printer_snum(p,handle, &snum) ) {
2505 status = WERR_BADFID;
2509 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2510 if ( !W_ERROR_IS_OK(status) )
2513 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2515 if ( strequal(value, "ChangeId") ) {
2517 *needed = sizeof(uint32);
2518 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2519 status = WERR_NOMEM;
2522 SIVAL( *data, 0, printer->info_2->changeid );
2526 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2529 if (*needed > *out_size)
2530 status = WERR_MORE_DATA;
2533 if ( !W_ERROR_IS_OK(status) )
2535 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2537 /* reply this param doesn't exist */
2540 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2542 free_a_printer( &printer, 2 );
2551 /* cleanup & exit */
2554 free_a_printer( &printer, 2 );
2559 /*********************************************************
2560 Connect to the client machine.
2561 **********************************************************/
2563 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2564 struct in_addr *client_ip, const char *remote_machine)
2566 ZERO_STRUCTP(the_cli);
2568 if(cli_initialise(the_cli) == NULL) {
2569 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2573 if ( is_zero_ip(*client_ip) ) {
2574 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2575 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2576 cli_shutdown(the_cli);
2580 if (ismyip(the_cli->dest_ip)) {
2581 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2582 cli_shutdown(the_cli);
2587 the_cli->dest_ip.s_addr = client_ip->s_addr;
2588 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2589 inet_ntoa(*client_ip) ));
2592 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2593 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) ));
2594 cli_shutdown(the_cli);
2598 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2599 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2601 cli_shutdown(the_cli);
2605 the_cli->protocol = PROTOCOL_NT1;
2607 if (!cli_negprot(the_cli)) {
2608 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2609 cli_shutdown(the_cli);
2613 if (the_cli->protocol != PROTOCOL_NT1) {
2614 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2615 cli_shutdown(the_cli);
2620 * Do an anonymous session setup.
2623 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2624 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2625 cli_shutdown(the_cli);
2629 if (!(the_cli->sec_mode & 1)) {
2630 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2631 cli_shutdown(the_cli);
2635 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2636 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) ));
2637 cli_shutdown(the_cli);
2642 * Ok - we have an anonymous connection to the IPC$ share.
2643 * Now start the NT Domain stuff :-).
2646 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2647 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)));
2648 cli_nt_session_close(the_cli);
2649 cli_ulogoff(the_cli);
2650 cli_shutdown(the_cli);
2657 /***************************************************************************
2658 Connect to the client.
2659 ****************************************************************************/
2661 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2662 uint32 localprinter, uint32 type,
2663 POLICY_HND *handle, struct in_addr *client_ip)
2668 * If it's the first connection, contact the client
2669 * and connect to the IPC$ share anonymously
2671 if (smb_connections==0) {
2672 fstring unix_printer;
2674 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2676 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2679 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2680 /* Tell the connections db we're now interested in printer
2681 * notify messages. */
2682 register_message_flags( True, FLAG_MSG_PRINTING );
2686 * Tell the specific printing tdb we want messages for this printer
2687 * by registering our PID.
2690 if (!print_notify_register_pid(snum))
2691 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2695 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2698 if (!W_ERROR_IS_OK(result))
2699 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2700 dos_errstr(result)));
2702 return (W_ERROR_IS_OK(result));
2705 /********************************************************************
2707 * ReplyFindFirstPrinterChangeNotifyEx
2709 * before replying OK: status=0 a rpc call is made to the workstation
2710 * asking ReplyOpenPrinter
2712 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2713 * called from api_spoolss_rffpcnex
2714 ********************************************************************/
2716 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2718 POLICY_HND *handle = &q_u->handle;
2719 uint32 flags = q_u->flags;
2720 uint32 options = q_u->options;
2721 UNISTR2 *localmachine = &q_u->localmachine;
2722 uint32 printerlocal = q_u->printerlocal;
2724 SPOOL_NOTIFY_OPTION *option = q_u->option;
2725 struct in_addr client_ip;
2727 /* store the notify value in the printer struct */
2729 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2732 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2736 Printer->notify.flags=flags;
2737 Printer->notify.options=options;
2738 Printer->notify.printerlocal=printerlocal;
2740 if (Printer->notify.option)
2741 free_spool_notify_option(&Printer->notify.option);
2743 Printer->notify.option=dup_spool_notify_option(option);
2745 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2746 sizeof(Printer->notify.localmachine)-1);
2748 /* Connect to the client machine and send a ReplyOpenPrinter */
2750 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2752 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2753 !get_printer_snum(p, handle, &snum) )
2756 client_ip.s_addr = inet_addr(p->conn->client_address);
2758 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2759 Printer->notify.printerlocal, 1,
2760 &Printer->notify.client_hnd, &client_ip))
2761 return WERR_SERVER_UNAVAILABLE;
2763 Printer->notify.client_connected=True;
2768 /*******************************************************************
2769 * fill a notify_info_data with the servername
2770 ********************************************************************/
2772 void spoolss_notify_server_name(int snum,
2773 SPOOL_NOTIFY_INFO_DATA *data,
2774 print_queue_struct *queue,
2775 NT_PRINTER_INFO_LEVEL *printer,
2776 TALLOC_CTX *mem_ctx)
2778 pstring temp_name, temp;
2781 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2783 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2785 data->notify_data.data.length = len;
2786 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2788 if (!data->notify_data.data.string) {
2789 data->notify_data.data.length = 0;
2793 memcpy(data->notify_data.data.string, temp, len);
2796 /*******************************************************************
2797 * fill a notify_info_data with the printername (not including the servername).
2798 ********************************************************************/
2800 void spoolss_notify_printer_name(int snum,
2801 SPOOL_NOTIFY_INFO_DATA *data,
2802 print_queue_struct *queue,
2803 NT_PRINTER_INFO_LEVEL *printer,
2804 TALLOC_CTX *mem_ctx)
2809 /* the notify name should not contain the \\server\ part */
2810 char *p = strrchr(printer->info_2->printername, '\\');
2813 p = printer->info_2->printername;
2818 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2820 data->notify_data.data.length = len;
2821 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2823 if (!data->notify_data.data.string) {
2824 data->notify_data.data.length = 0;
2828 memcpy(data->notify_data.data.string, temp, len);
2831 /*******************************************************************
2832 * fill a notify_info_data with the servicename
2833 ********************************************************************/
2835 void spoolss_notify_share_name(int snum,
2836 SPOOL_NOTIFY_INFO_DATA *data,
2837 print_queue_struct *queue,
2838 NT_PRINTER_INFO_LEVEL *printer,
2839 TALLOC_CTX *mem_ctx)
2844 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2846 data->notify_data.data.length = len;
2847 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2849 if (!data->notify_data.data.string) {
2850 data->notify_data.data.length = 0;
2854 memcpy(data->notify_data.data.string, temp, len);
2857 /*******************************************************************
2858 * fill a notify_info_data with the port name
2859 ********************************************************************/
2861 void spoolss_notify_port_name(int snum,
2862 SPOOL_NOTIFY_INFO_DATA *data,
2863 print_queue_struct *queue,
2864 NT_PRINTER_INFO_LEVEL *printer,
2865 TALLOC_CTX *mem_ctx)
2870 /* even if it's strange, that's consistant in all the code */
2872 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2874 data->notify_data.data.length = len;
2875 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2877 if (!data->notify_data.data.string) {
2878 data->notify_data.data.length = 0;
2882 memcpy(data->notify_data.data.string, temp, len);
2885 /*******************************************************************
2886 * fill a notify_info_data with the printername
2887 * but it doesn't exist, have to see what to do
2888 ********************************************************************/
2890 void spoolss_notify_driver_name(int snum,
2891 SPOOL_NOTIFY_INFO_DATA *data,
2892 print_queue_struct *queue,
2893 NT_PRINTER_INFO_LEVEL *printer,
2894 TALLOC_CTX *mem_ctx)
2899 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2901 data->notify_data.data.length = len;
2902 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2904 if (!data->notify_data.data.string) {
2905 data->notify_data.data.length = 0;
2909 memcpy(data->notify_data.data.string, temp, len);
2912 /*******************************************************************
2913 * fill a notify_info_data with the comment
2914 ********************************************************************/
2916 void spoolss_notify_comment(int snum,
2917 SPOOL_NOTIFY_INFO_DATA *data,
2918 print_queue_struct *queue,
2919 NT_PRINTER_INFO_LEVEL *printer,
2920 TALLOC_CTX *mem_ctx)
2925 if (*printer->info_2->comment == '\0')
2926 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2928 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2930 data->notify_data.data.length = len;
2931 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2933 if (!data->notify_data.data.string) {
2934 data->notify_data.data.length = 0;
2938 memcpy(data->notify_data.data.string, temp, len);
2941 /*******************************************************************
2942 * fill a notify_info_data with the comment
2943 * location = "Room 1, floor 2, building 3"
2944 ********************************************************************/
2946 void spoolss_notify_location(int snum,
2947 SPOOL_NOTIFY_INFO_DATA *data,
2948 print_queue_struct *queue,
2949 NT_PRINTER_INFO_LEVEL *printer,
2950 TALLOC_CTX *mem_ctx)
2955 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2957 data->notify_data.data.length = len;
2958 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2960 if (!data->notify_data.data.string) {
2961 data->notify_data.data.length = 0;
2965 memcpy(data->notify_data.data.string, temp, len);
2968 /*******************************************************************
2969 * fill a notify_info_data with the device mode
2970 * jfm:xxxx don't to it for know but that's a real problem !!!
2971 ********************************************************************/
2973 static void spoolss_notify_devmode(int snum,
2974 SPOOL_NOTIFY_INFO_DATA *data,
2975 print_queue_struct *queue,
2976 NT_PRINTER_INFO_LEVEL *printer,
2977 TALLOC_CTX *mem_ctx)
2981 /*******************************************************************
2982 * fill a notify_info_data with the separator file name
2983 ********************************************************************/
2985 void spoolss_notify_sepfile(int snum,
2986 SPOOL_NOTIFY_INFO_DATA *data,
2987 print_queue_struct *queue,
2988 NT_PRINTER_INFO_LEVEL *printer,
2989 TALLOC_CTX *mem_ctx)
2994 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2996 data->notify_data.data.length = len;
2997 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2999 if (!data->notify_data.data.string) {
3000 data->notify_data.data.length = 0;
3004 memcpy(data->notify_data.data.string, temp, len);
3007 /*******************************************************************
3008 * fill a notify_info_data with the print processor
3009 * jfm:xxxx return always winprint to indicate we don't do anything to it
3010 ********************************************************************/
3012 void spoolss_notify_print_processor(int snum,
3013 SPOOL_NOTIFY_INFO_DATA *data,
3014 print_queue_struct *queue,
3015 NT_PRINTER_INFO_LEVEL *printer,
3016 TALLOC_CTX *mem_ctx)
3021 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3023 data->notify_data.data.length = len;
3024 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3026 if (!data->notify_data.data.string) {
3027 data->notify_data.data.length = 0;
3031 memcpy(data->notify_data.data.string, temp, len);
3034 /*******************************************************************
3035 * fill a notify_info_data with the print processor options
3036 * jfm:xxxx send an empty string
3037 ********************************************************************/
3039 void spoolss_notify_parameters(int snum,
3040 SPOOL_NOTIFY_INFO_DATA *data,
3041 print_queue_struct *queue,
3042 NT_PRINTER_INFO_LEVEL *printer,
3043 TALLOC_CTX *mem_ctx)
3048 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3050 data->notify_data.data.length = len;
3051 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3053 if (!data->notify_data.data.string) {
3054 data->notify_data.data.length = 0;
3058 memcpy(data->notify_data.data.string, temp, len);
3061 /*******************************************************************
3062 * fill a notify_info_data with the data type
3063 * jfm:xxxx always send RAW as data type
3064 ********************************************************************/
3066 void spoolss_notify_datatype(int snum,
3067 SPOOL_NOTIFY_INFO_DATA *data,
3068 print_queue_struct *queue,
3069 NT_PRINTER_INFO_LEVEL *printer,
3070 TALLOC_CTX *mem_ctx)
3075 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3077 data->notify_data.data.length = len;
3078 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3080 if (!data->notify_data.data.string) {
3081 data->notify_data.data.length = 0;
3085 memcpy(data->notify_data.data.string, temp, len);
3088 /*******************************************************************
3089 * fill a notify_info_data with the security descriptor
3090 * jfm:xxxx send an null pointer to say no security desc
3091 * have to implement security before !
3092 ********************************************************************/
3094 static void spoolss_notify_security_desc(int snum,
3095 SPOOL_NOTIFY_INFO_DATA *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3101 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3104 /*******************************************************************
3105 * fill a notify_info_data with the attributes
3106 * jfm:xxxx a samba printer is always shared
3107 ********************************************************************/
3109 void spoolss_notify_attributes(int snum,
3110 SPOOL_NOTIFY_INFO_DATA *data,
3111 print_queue_struct *queue,
3112 NT_PRINTER_INFO_LEVEL *printer,
3113 TALLOC_CTX *mem_ctx)
3115 data->notify_data.value[0] = printer->info_2->attributes;
3116 data->notify_data.value[1] = 0;
3119 /*******************************************************************
3120 * fill a notify_info_data with the priority
3121 ********************************************************************/
3123 static void spoolss_notify_priority(int snum,
3124 SPOOL_NOTIFY_INFO_DATA *data,
3125 print_queue_struct *queue,
3126 NT_PRINTER_INFO_LEVEL *printer,
3127 TALLOC_CTX *mem_ctx)
3129 data->notify_data.value[0] = printer->info_2->priority;
3130 data->notify_data.value[1] = 0;
3133 /*******************************************************************
3134 * fill a notify_info_data with the default priority
3135 ********************************************************************/
3137 static void spoolss_notify_default_priority(int snum,
3138 SPOOL_NOTIFY_INFO_DATA *data,
3139 print_queue_struct *queue,
3140 NT_PRINTER_INFO_LEVEL *printer,
3141 TALLOC_CTX *mem_ctx)
3143 data->notify_data.value[0] = printer->info_2->default_priority;
3144 data->notify_data.value[1] = 0;
3147 /*******************************************************************
3148 * fill a notify_info_data with the start time
3149 ********************************************************************/
3151 static void spoolss_notify_start_time(int snum,
3152 SPOOL_NOTIFY_INFO_DATA *data,
3153 print_queue_struct *queue,
3154 NT_PRINTER_INFO_LEVEL *printer,
3155 TALLOC_CTX *mem_ctx)
3157 data->notify_data.value[0] = printer->info_2->starttime;
3158 data->notify_data.value[1] = 0;
3161 /*******************************************************************
3162 * fill a notify_info_data with the until time
3163 ********************************************************************/
3165 static void spoolss_notify_until_time(int snum,
3166 SPOOL_NOTIFY_INFO_DATA *data,
3167 print_queue_struct *queue,
3168 NT_PRINTER_INFO_LEVEL *printer,
3169 TALLOC_CTX *mem_ctx)
3171 data->notify_data.value[0] = printer->info_2->untiltime;
3172 data->notify_data.value[1] = 0;
3175 /*******************************************************************
3176 * fill a notify_info_data with the status
3177 ********************************************************************/
3179 static void spoolss_notify_status(int snum,
3180 SPOOL_NOTIFY_INFO_DATA *data,
3181 print_queue_struct *queue,
3182 NT_PRINTER_INFO_LEVEL *printer,
3183 TALLOC_CTX *mem_ctx)
3185 print_status_struct status;
3187 print_queue_length(snum, &status);
3188 data->notify_data.value[0]=(uint32) status.status;
3189 data->notify_data.value[1] = 0;
3192 /*******************************************************************
3193 * fill a notify_info_data with the number of jobs queued
3194 ********************************************************************/
3196 void spoolss_notify_cjobs(int snum,
3197 SPOOL_NOTIFY_INFO_DATA *data,
3198 print_queue_struct *queue,
3199 NT_PRINTER_INFO_LEVEL *printer,
3200 TALLOC_CTX *mem_ctx)
3202 data->notify_data.value[0] = print_queue_length(snum, NULL);
3203 data->notify_data.value[1] = 0;
3206 /*******************************************************************
3207 * fill a notify_info_data with the average ppm
3208 ********************************************************************/
3210 static void spoolss_notify_average_ppm(int snum,
3211 SPOOL_NOTIFY_INFO_DATA *data,
3212 print_queue_struct *queue,
3213 NT_PRINTER_INFO_LEVEL *printer,
3214 TALLOC_CTX *mem_ctx)
3216 /* always respond 8 pages per minutes */
3217 /* a little hard ! */
3218 data->notify_data.value[0] = printer->info_2->averageppm;
3219 data->notify_data.value[1] = 0;
3222 /*******************************************************************
3223 * fill a notify_info_data with username
3224 ********************************************************************/
3226 static void spoolss_notify_username(int snum,
3227 SPOOL_NOTIFY_INFO_DATA *data,
3228 print_queue_struct *queue,
3229 NT_PRINTER_INFO_LEVEL *printer,
3230 TALLOC_CTX *mem_ctx)
3235 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3237 data->notify_data.data.length = len;
3238 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3240 if (!data->notify_data.data.string) {
3241 data->notify_data.data.length = 0;
3245 memcpy(data->notify_data.data.string, temp, len);
3248 /*******************************************************************
3249 * fill a notify_info_data with job status
3250 ********************************************************************/
3252 static void spoolss_notify_job_status(int snum,
3253 SPOOL_NOTIFY_INFO_DATA *data,
3254 print_queue_struct *queue,
3255 NT_PRINTER_INFO_LEVEL *printer,
3256 TALLOC_CTX *mem_ctx)
3258 data->notify_data.value[0]=nt_printj_status(queue->status);
3259 data->notify_data.value[1] = 0;
3262 /*******************************************************************
3263 * fill a notify_info_data with job name
3264 ********************************************************************/
3266 static void spoolss_notify_job_name(int snum,
3267 SPOOL_NOTIFY_INFO_DATA *data,
3268 print_queue_struct *queue,
3269 NT_PRINTER_INFO_LEVEL *printer,
3270 TALLOC_CTX *mem_ctx)
3275 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3277 data->notify_data.data.length = len;
3278 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3280 if (!data->notify_data.data.string) {
3281 data->notify_data.data.length = 0;
3285 memcpy(data->notify_data.data.string, temp, len);
3288 /*******************************************************************
3289 * fill a notify_info_data with job status
3290 ********************************************************************/
3292 static void spoolss_notify_job_status_string(int snum,
3293 SPOOL_NOTIFY_INFO_DATA *data,
3294 print_queue_struct *queue,
3295 NT_PRINTER_INFO_LEVEL *printer,
3296 TALLOC_CTX *mem_ctx)
3299 * Now we're returning job status codes we just return a "" here. JRA.
3306 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3309 switch (queue->status) {
3314 p = ""; /* NT provides the paused string */
3323 #endif /* NO LONGER NEEDED. */
3325 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3327 data->notify_data.data.length = len;
3328 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3330 if (!data->notify_data.data.string) {
3331 data->notify_data.data.length = 0;
3335 memcpy(data->notify_data.data.string, temp, len);
3338 /*******************************************************************
3339 * fill a notify_info_data with job time
3340 ********************************************************************/
3342 static void spoolss_notify_job_time(int snum,
3343 SPOOL_NOTIFY_INFO_DATA *data,
3344 print_queue_struct *queue,
3345 NT_PRINTER_INFO_LEVEL *printer,
3346 TALLOC_CTX *mem_ctx)
3348 data->notify_data.value[0]=0x0;
3349 data->notify_data.value[1]=0;
3352 /*******************************************************************
3353 * fill a notify_info_data with job size
3354 ********************************************************************/
3356 static void spoolss_notify_job_size(int snum,
3357 SPOOL_NOTIFY_INFO_DATA *data,
3358 print_queue_struct *queue,
3359 NT_PRINTER_INFO_LEVEL *printer,
3360 TALLOC_CTX *mem_ctx)
3362 data->notify_data.value[0]=queue->size;
3363 data->notify_data.value[1]=0;
3366 /*******************************************************************
3367 * fill a notify_info_data with page info
3368 ********************************************************************/
3369 static void spoolss_notify_total_pages(int snum,
3370 SPOOL_NOTIFY_INFO_DATA *data,
3371 print_queue_struct *queue,
3372 NT_PRINTER_INFO_LEVEL *printer,
3373 TALLOC_CTX *mem_ctx)
3375 data->notify_data.value[0]=queue->page_count;
3376 data->notify_data.value[1]=0;
3379 /*******************************************************************
3380 * fill a notify_info_data with pages printed info.
3381 ********************************************************************/
3382 static void spoolss_notify_pages_printed(int snum,
3383 SPOOL_NOTIFY_INFO_DATA *data,
3384 print_queue_struct *queue,
3385 NT_PRINTER_INFO_LEVEL *printer,
3386 TALLOC_CTX *mem_ctx)
3388 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3389 data->notify_data.value[1]=0;
3392 /*******************************************************************
3393 Fill a notify_info_data with job position.
3394 ********************************************************************/
3396 static void spoolss_notify_job_position(int snum,
3397 SPOOL_NOTIFY_INFO_DATA *data,
3398 print_queue_struct *queue,
3399 NT_PRINTER_INFO_LEVEL *printer,
3400 TALLOC_CTX *mem_ctx)
3402 data->notify_data.value[0]=queue->job;
3403 data->notify_data.value[1]=0;
3406 /*******************************************************************
3407 Fill a notify_info_data with submitted time.
3408 ********************************************************************/
3410 static void spoolss_notify_submitted_time(int snum,
3411 SPOOL_NOTIFY_INFO_DATA *data,
3412 print_queue_struct *queue,
3413 NT_PRINTER_INFO_LEVEL *printer,
3414 TALLOC_CTX *mem_ctx)
3421 t=gmtime(&queue->time);
3423 len = sizeof(SYSTEMTIME);
3425 data->notify_data.data.length = len;
3426 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3428 if (!data->notify_data.data.string) {
3429 data->notify_data.data.length = 0;
3433 make_systemtime(&st, t);
3436 * Systemtime must be linearized as a set of UINT16's.
3437 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3440 p = (char *)data->notify_data.data.string;
3441 SSVAL(p, 0, st.year);
3442 SSVAL(p, 2, st.month);
3443 SSVAL(p, 4, st.dayofweek);
3444 SSVAL(p, 6, st.day);
3445 SSVAL(p, 8, st.hour);
3446 SSVAL(p, 10, st.minute);
3447 SSVAL(p, 12, st.second);
3448 SSVAL(p, 14, st.milliseconds);
3451 struct s_notify_info_data_table
3457 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3458 print_queue_struct *queue,
3459 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3462 /* A table describing the various print notification constants and
3463 whether the notification data is a pointer to a variable sized
3464 buffer, a one value uint32 or a two value uint32. */
3466 static const struct s_notify_info_data_table notify_info_data_table[] =
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3489 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3490 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3491 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3492 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3493 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3511 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3512 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3513 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3514 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3515 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3516 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3519 /*******************************************************************
3520 Return the size of info_data structure.
3521 ********************************************************************/
3523 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3527 for (i = 0; i < sizeof(notify_info_data_table); i++)
3529 if ( (notify_info_data_table[i].type == type)
3530 && (notify_info_data_table[i].field == field) )
3532 switch(notify_info_data_table[i].size)
3534 case NOTIFY_ONE_VALUE:
3535 case NOTIFY_TWO_VALUE:
3540 /* The only pointer notify data I have seen on
3541 the wire is the submitted time and this has
3542 the notify size set to 4. -tpot */
3544 case NOTIFY_POINTER:
3547 case NOTIFY_SECDESC:
3553 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3558 /*******************************************************************
3559 Return the type of notify_info_data.
3560 ********************************************************************/
3562 static int type_of_notify_info_data(uint16 type, uint16 field)
3566 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3567 if (notify_info_data_table[i].type == type &&
3568 notify_info_data_table[i].field == field)
3569 return notify_info_data_table[i].size;
3575 /****************************************************************************
3576 ****************************************************************************/
3578 static int search_notify(uint16 type, uint16 field, int *value)
3582 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3583 if (notify_info_data_table[i].type == type &&
3584 notify_info_data_table[i].field == field &&
3585 notify_info_data_table[i].fn != NULL) {
3594 /****************************************************************************
3595 ****************************************************************************/
3597 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3599 info_data->type = type;
3600 info_data->field = field;
3601 info_data->reserved = 0;
3603 info_data->size = size_of_notify_info_data(type, field);
3604 info_data->enc_type = type_of_notify_info_data(type, field);
3611 /*******************************************************************
3613 * fill a notify_info struct with info asked
3615 ********************************************************************/
3617 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3618 snum, SPOOL_NOTIFY_OPTION_TYPE
3619 *option_type, uint32 id,
3620 TALLOC_CTX *mem_ctx)
3626 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3627 NT_PRINTER_INFO_LEVEL *printer = NULL;
3628 print_queue_struct *queue=NULL;
3630 type=option_type->type;
3632 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3633 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3634 option_type->count, lp_servicename(snum)));
3636 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3639 for(field_num=0; field_num<option_type->count; field_num++) {
3640 field = option_type->fields[field_num];
3642 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3644 if (!search_notify(type, field, &j) )
3647 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3648 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3653 current_data = &info->data[info->count];
3655 construct_info_data(current_data, type, field, id);
3657 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3658 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3660 notify_info_data_table[j].fn(snum, current_data, queue,
3666 free_a_printer(&printer, 2);
3670 /*******************************************************************
3672 * fill a notify_info struct with info asked
3674 ********************************************************************/
3676 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3677 SPOOL_NOTIFY_INFO *info,
3678 NT_PRINTER_INFO_LEVEL *printer,
3679 int snum, SPOOL_NOTIFY_OPTION_TYPE
3680 *option_type, uint32 id,
3681 TALLOC_CTX *mem_ctx)
3687 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3689 DEBUG(4,("construct_notify_jobs_info\n"));
3691 type = option_type->type;
3693 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3694 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3695 option_type->count));
3697 for(field_num=0; field_num<option_type->count; field_num++) {
3698 field = option_type->fields[field_num];
3700 if (!search_notify(type, field, &j) )
3703 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3704 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3707 else info->data = tid;
3709 current_data=&(info->data[info->count]);
3711 construct_info_data(current_data, type, field, id);
3712 notify_info_data_table[j].fn(snum, current_data, queue,
3721 * JFM: The enumeration is not that simple, it's even non obvious.
3723 * let's take an example: I want to monitor the PRINTER SERVER for
3724 * the printer's name and the number of jobs currently queued.
3725 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3726 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3728 * I have 3 printers on the back of my server.
3730 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3733 * 1 printer 1 name 1
3734 * 2 printer 1 cjob 1
3735 * 3 printer 2 name 2
3736 * 4 printer 2 cjob 2
3737 * 5 printer 3 name 3
3738 * 6 printer 3 name 3
3740 * that's the print server case, the printer case is even worse.
3743 /*******************************************************************
3745 * enumerate all printers on the printserver
3746 * fill a notify_info struct with info asked
3748 ********************************************************************/
3750 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3751 SPOOL_NOTIFY_INFO *info,
3752 TALLOC_CTX *mem_ctx)
3755 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3756 int n_services=lp_numservices();
3759 SPOOL_NOTIFY_OPTION *option;
3760 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3762 DEBUG(4,("printserver_notify_info\n"));
3767 option=Printer->notify.option;
3773 for (i=0; i<option->count; i++) {
3774 option_type=&(option->ctr.type[i]);
3776 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3779 for (snum=0; snum<n_services; snum++)
3781 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3782 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3788 * Debugging information, don't delete.
3791 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3792 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3793 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3795 for (i=0; i<info->count; i++) {
3796 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3797 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3798 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3805 /*******************************************************************
3807 * fill a notify_info struct with info asked
3809 ********************************************************************/
3811 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3812 TALLOC_CTX *mem_ctx)
3815 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3818 SPOOL_NOTIFY_OPTION *option;
3819 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3821 print_queue_struct *queue=NULL;
3822 print_status_struct status;
3824 DEBUG(4,("printer_notify_info\n"));
3829 option=Printer->notify.option;
3835 get_printer_snum(p, hnd, &snum);
3837 for (i=0; i<option->count; i++) {
3838 option_type=&option->ctr.type[i];
3840 switch ( option_type->type ) {
3841 case PRINTER_NOTIFY_TYPE:
3842 if(construct_notify_printer_info(Printer, info, snum,
3848 case JOB_NOTIFY_TYPE: {
3849 NT_PRINTER_INFO_LEVEL *printer = NULL;
3851 count = print_queue_status(snum, &queue, &status);
3853 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3856 for (j=0; j<count; j++) {
3857 construct_notify_jobs_info(&queue[j], info,
3864 free_a_printer(&printer, 2);
3874 * Debugging information, don't delete.
3877 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3878 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3879 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3881 for (i=0; i<info->count; i++) {
3882 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3883 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3884 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3890 /********************************************************************
3892 ********************************************************************/
3894 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3896 POLICY_HND *handle = &q_u->handle;
3897 SPOOL_NOTIFY_INFO *info = &r_u->info;
3899 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3900 WERROR result = WERR_BADFID;
3902 /* we always have a NOTIFY_INFO struct */
3906 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3907 OUR_HANDLE(handle)));
3911 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3914 * We are now using the change value, and
3915 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3916 * I don't have a global notification system, I'm sending back all the
3917 * informations even when _NOTHING_ has changed.
3920 /* We need to keep track of the change value to send back in
3921 RRPCN replies otherwise our updates are ignored. */
3923 Printer->notify.fnpcn = True;
3925 if (Printer->notify.client_connected) {
3926 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3927 Printer->notify.change = q_u->change;
3930 /* just ignore the SPOOL_NOTIFY_OPTION */
3932 switch (Printer->printer_type) {
3933 case PRINTER_HANDLE_IS_PRINTSERVER:
3934 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3937 case PRINTER_HANDLE_IS_PRINTER:
3938 result = printer_notify_info(p, handle, info, p->mem_ctx);
3942 Printer->notify.fnpcn = False;
3948 /********************************************************************
3949 * construct_printer_info_0
3950 * fill a printer_info_0 struct
3951 ********************************************************************/
3953 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3957 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3958 counter_printer_0 *session_counter;
3959 uint32 global_counter;
3962 print_status_struct status;
3964 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3967 count = print_queue_length(snum, &status);
3969 /* check if we already have a counter for this printer */
3970 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3972 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3973 if (session_counter->snum == snum)
3977 /* it's the first time, add it to the list */
3978 if (session_counter==NULL) {
3979 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3980 free_a_printer(&ntprinter, 2);
3983 ZERO_STRUCTP(session_counter);
3984 session_counter->snum=snum;
3985 session_counter->counter=0;
3986 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3990 session_counter->counter++;
3993 * the global_counter should be stored in a TDB as it's common to all the clients
3994 * and should be zeroed on samba startup
3996 global_counter=session_counter->counter;
3998 pstrcpy(chaine,ntprinter->info_2->printername);
4000 init_unistr(&printer->printername, chaine);
4002 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
4003 init_unistr(&printer->servername, chaine);
4005 printer->cjobs = count;
4006 printer->total_jobs = 0;
4007 printer->total_bytes = 0;
4009 setuptime = (time_t)ntprinter->info_2->setuptime;
4010 t=gmtime(&setuptime);
4012 printer->year = t->tm_year+1900;
4013 printer->month = t->tm_mon+1;
4014 printer->dayofweek = t->tm_wday;
4015 printer->day = t->tm_mday;
4016 printer->hour = t->tm_hour;
4017 printer->minute = t->tm_min;
4018 printer->second = t->tm_sec;
4019 printer->milliseconds = 0;
4021 printer->global_counter = global_counter;
4022 printer->total_pages = 0;
4024 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4025 printer->major_version = 0x0005; /* NT 5 */
4026 printer->build_version = 0x0893; /* build 2195 */
4028 printer->unknown7 = 0x1;
4029 printer->unknown8 = 0x0;
4030 printer->unknown9 = 0x0;
4031 printer->session_counter = session_counter->counter;
4032 printer->unknown11 = 0x0;
4033 printer->printer_errors = 0x0; /* number of print failure */
4034 printer->unknown13 = 0x0;
4035 printer->unknown14 = 0x1;
4036 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4037 printer->unknown16 = 0x0;
4038 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4039 printer->unknown18 = 0x0;
4040 printer->status = nt_printq_status(status.status);
4041 printer->unknown20 = 0x0;
4042 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4043 printer->unknown22 = 0x0;
4044 printer->unknown23 = 0x6; /* 6 ???*/
4045 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4046 printer->unknown25 = 0;
4047 printer->unknown26 = 0;
4048 printer->unknown27 = 0;
4049 printer->unknown28 = 0;
4050 printer->unknown29 = 0;
4052 free_a_printer(&ntprinter,2);
4056 /********************************************************************
4057 * construct_printer_info_1
4058 * fill a printer_info_1 struct
4059 ********************************************************************/
4060 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4064 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4066 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4069 printer->flags=flags;
4071 if (*ntprinter->info_2->comment == '\0') {
4072 init_unistr(&printer->comment, lp_comment(snum));
4073 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4074 ntprinter->info_2->drivername, lp_comment(snum));
4077 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4078 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4079 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4082 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4084 init_unistr(&printer->description, chaine);
4085 init_unistr(&printer->name, chaine2);
4087 free_a_printer(&ntprinter,2);
4092 /****************************************************************************
4093 Free a DEVMODE struct.
4094 ****************************************************************************/
4096 static void free_dev_mode(DEVICEMODE *dev)
4101 SAFE_FREE(dev->private);
4106 /****************************************************************************
4107 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4108 should be valid upon entry
4109 ****************************************************************************/
4111 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4113 if ( !devmode || !ntdevmode )
4116 init_unistr(&devmode->devicename, ntdevmode->devicename);
4118 init_unistr(&devmode->formname, ntdevmode->formname);
4120 devmode->specversion = ntdevmode->specversion;
4121 devmode->driverversion = ntdevmode->driverversion;
4122 devmode->size = ntdevmode->size;
4123 devmode->driverextra = ntdevmode->driverextra;
4124 devmode->fields = ntdevmode->fields;
4126 devmode->orientation = ntdevmode->orientation;
4127 devmode->papersize = ntdevmode->papersize;
4128 devmode->paperlength = ntdevmode->paperlength;
4129 devmode->paperwidth = ntdevmode->paperwidth;
4130 devmode->scale = ntdevmode->scale;
4131 devmode->copies = ntdevmode->copies;
4132 devmode->defaultsource = ntdevmode->defaultsource;
4133 devmode->printquality = ntdevmode->printquality;
4134 devmode->color = ntdevmode->color;
4135 devmode->duplex = ntdevmode->duplex;
4136 devmode->yresolution = ntdevmode->yresolution;
4137 devmode->ttoption = ntdevmode->ttoption;
4138 devmode->collate = ntdevmode->collate;
4139 devmode->icmmethod = ntdevmode->icmmethod;
4140 devmode->icmintent = ntdevmode->icmintent;
4141 devmode->mediatype = ntdevmode->mediatype;
4142 devmode->dithertype = ntdevmode->dithertype;
4144 if (ntdevmode->private != NULL) {
4145 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4152 /****************************************************************************
4153 Create a DEVMODE struct. Returns malloced memory.
4154 ****************************************************************************/
4156 DEVICEMODE *construct_dev_mode(int snum)
4158 NT_PRINTER_INFO_LEVEL *printer = NULL;
4159 DEVICEMODE *devmode = NULL;
4161 DEBUG(7,("construct_dev_mode\n"));
4163 DEBUGADD(8,("getting printer characteristics\n"));
4165 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4168 if ( !printer->info_2->devmode ) {
4169 DEBUG(5, ("BONG! There was no device mode!\n"));
4173 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4174 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4178 ZERO_STRUCTP(devmode);
4180 DEBUGADD(8,("loading DEVICEMODE\n"));
4182 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4183 free_dev_mode( devmode );
4188 free_a_printer(&printer,2);
4193 /********************************************************************
4194 * construct_printer_info_2
4195 * fill a printer_info_2 struct
4196 ********************************************************************/
4198 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4201 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4203 print_status_struct status;
4205 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4208 count = print_queue_length(snum, &status);
4210 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4211 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4212 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4213 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4214 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4216 if (*ntprinter->info_2->comment == '\0')
4217 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4219 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4221 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4222 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4223 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4224 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4225 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4227 printer->attributes = ntprinter->info_2->attributes;
4229 printer->priority = ntprinter->info_2->priority; /* priority */
4230 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4231 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4232 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4233 printer->status = nt_printq_status(status.status); /* status */
4234 printer->cjobs = count; /* jobs */
4235 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4237 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4238 DEBUG(8, ("Returning NULL Devicemode!\n"));
4241 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4242 /* steal the printer info sec_desc structure. [badly done]. */
4243 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4244 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4245 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4246 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4249 printer->secdesc = NULL;
4252 free_a_printer(&ntprinter, 2);
4256 /********************************************************************
4257 * construct_printer_info_3
4258 * fill a printer_info_3 struct
4259 ********************************************************************/
4261 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4263 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4264 PRINTER_INFO_3 *printer = NULL;
4266 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4270 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4271 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4275 ZERO_STRUCTP(printer);
4277 printer->flags = 4; /* These are the components of the SD we are returning. */
4278 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4279 /* steal the printer info sec_desc structure. [badly done]. */
4280 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4284 * Set the flags for the components we are returning.
4287 if (printer->secdesc->owner_sid)
4288 printer->flags |= OWNER_SECURITY_INFORMATION;
4290 if (printer->secdesc->grp_sid)
4291 printer->flags |= GROUP_SECURITY_INFORMATION;
4293 if (printer->secdesc->dacl)
4294 printer->flags |= DACL_SECURITY_INFORMATION;
4296 if (printer->secdesc->sacl)
4297 printer->flags |= SACL_SECURITY_INFORMATION;
4300 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4301 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4302 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4305 free_a_printer(&ntprinter, 2);
4307 *pp_printer = printer;
4311 /********************************************************************
4312 * construct_printer_info_4
4313 * fill a printer_info_4 struct
4314 ********************************************************************/
4316 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4318 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4320 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4323 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4324 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4325 printer->attributes = ntprinter->info_2->attributes;
4327 free_a_printer(&ntprinter, 2);
4331 /********************************************************************
4332 * construct_printer_info_5
4333 * fill a printer_info_5 struct
4334 ********************************************************************/
4336 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4338 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4340 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4343 init_unistr(&printer->printername, ntprinter->info_2->printername);
4344 init_unistr(&printer->portname, ntprinter->info_2->portname);
4345 printer->attributes = ntprinter->info_2->attributes;
4347 /* these two are not used by NT+ according to MSDN */
4349 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4350 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4352 free_a_printer(&ntprinter, 2);
4357 /********************************************************************
4358 * construct_printer_info_7
4359 * fill a printer_info_7 struct
4360 ********************************************************************/
4362 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4364 char *guid_str = NULL;
4367 if (is_printer_published(print_hnd, snum, &guid)) {
4368 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4369 strupper_m(guid_str);
4370 init_unistr(&printer->guid, guid_str);
4371 printer->action = SPOOL_DS_PUBLISH;
4373 init_unistr(&printer->guid, "");
4374 printer->action = SPOOL_DS_UNPUBLISH;
4380 /********************************************************************
4381 Spoolss_enumprinters.
4382 ********************************************************************/
4384 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4388 int n_services=lp_numservices();
4389 PRINTER_INFO_1 *tp, *printers=NULL;
4390 PRINTER_INFO_1 current_prt;
4392 DEBUG(4,("enum_all_printers_info_1\n"));
4394 for (snum=0; snum<n_services; snum++) {
4395 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4396 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4398 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4399 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4400 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4401 SAFE_FREE(printers);
4406 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4408 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4414 /* check the required size. */
4415 for (i=0; i<*returned; i++)
4416 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4418 if (!alloc_buffer_size(buffer, *needed))
4419 return WERR_INSUFFICIENT_BUFFER;
4421 /* fill the buffer with the structures */
4422 for (i=0; i<*returned; i++)
4423 smb_io_printer_info_1("", buffer, &printers[i], 0);
4426 SAFE_FREE(printers);
4428 if (*needed > offered) {
4430 return WERR_INSUFFICIENT_BUFFER;
4436 /********************************************************************
4437 enum_all_printers_info_1_local.
4438 *********************************************************************/
4440 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4442 DEBUG(4,("enum_all_printers_info_1_local\n"));
4444 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4447 /********************************************************************
4448 enum_all_printers_info_1_name.
4449 *********************************************************************/
4451 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4455 DEBUG(4,("enum_all_printers_info_1_name\n"));
4457 if ((name[0] == '\\') && (name[1] == '\\'))
4460 if (is_myname_or_ipaddr(s)) {
4461 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4464 return WERR_INVALID_NAME;
4467 /********************************************************************
4468 enum_all_printers_info_1_remote.
4469 *********************************************************************/
4471 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4473 PRINTER_INFO_1 *printer;
4474 fstring printername;
4477 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4479 /* JFM: currently it's more a place holder than anything else.
4480 * In the spooler world there is a notion of server registration.
4481 * the print servers are registring (sp ?) on the PDC (in the same domain)
4483 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4486 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4491 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4492 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4493 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4495 init_unistr(&printer->description, desc);
4496 init_unistr(&printer->name, printername);
4497 init_unistr(&printer->comment, comment);
4498 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4500 /* check the required size. */
4501 *needed += spoolss_size_printer_info_1(printer);
4503 if (!alloc_buffer_size(buffer, *needed)) {
4505 return WERR_INSUFFICIENT_BUFFER;
4508 /* fill the buffer with the structures */
4509 smb_io_printer_info_1("", buffer, printer, 0);
4514 if (*needed > offered) {
4516 return WERR_INSUFFICIENT_BUFFER;
4522 /********************************************************************
4523 enum_all_printers_info_1_network.
4524 *********************************************************************/
4526 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4530 DEBUG(4,("enum_all_printers_info_1_network\n"));
4532 /* If we respond to a enum_printers level 1 on our name with flags
4533 set to PRINTER_ENUM_REMOTE with a list of printers then these
4534 printers incorrectly appear in the APW browse list.
4535 Specifically the printers for the server appear at the workgroup
4536 level where all the other servers in the domain are
4537 listed. Windows responds to this call with a
4538 WERR_CAN_NOT_COMPLETE so we should do the same. */
4540 if (name[0] == '\\' && name[1] == '\\')
4543 if (is_myname_or_ipaddr(s))
4544 return WERR_CAN_NOT_COMPLETE;
4546 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4549 /********************************************************************
4550 * api_spoolss_enumprinters
4552 * called from api_spoolss_enumprinters (see this to understand)
4553 ********************************************************************/
4555 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4559 int n_services=lp_numservices();
4560 PRINTER_INFO_2 *tp, *printers=NULL;
4561 PRINTER_INFO_2 current_prt;
4563 for (snum=0; snum<n_services; snum++) {
4564 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4565 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4567 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4568 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4569 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4570 SAFE_FREE(printers);
4575 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4576 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4582 /* check the required size. */
4583 for (i=0; i<*returned; i++)
4584 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4586 if (!alloc_buffer_size(buffer, *needed)) {
4587 for (i=0; i<*returned; i++) {
4588 free_devmode(printers[i].devmode);
4590 SAFE_FREE(printers);
4591 return WERR_INSUFFICIENT_BUFFER;
4594 /* fill the buffer with the structures */
4595 for (i=0; i<*returned; i++)
4596 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4599 for (i=0; i<*returned; i++) {
4600 free_devmode(printers[i].devmode);
4602 SAFE_FREE(printers);
4604 if (*needed > offered) {
4606 return WERR_INSUFFICIENT_BUFFER;
4612 /********************************************************************
4613 * handle enumeration of printers at level 1
4614 ********************************************************************/
4616 static WERROR enumprinters_level1( uint32 flags, fstring name,
4617 NEW_BUFFER *buffer, uint32 offered,
4618 uint32 *needed, uint32 *returned)
4620 /* Not all the flags are equals */
4622 if (flags & PRINTER_ENUM_LOCAL)
4623 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4625 if (flags & PRINTER_ENUM_NAME)
4626 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4628 if (flags & PRINTER_ENUM_REMOTE)
4629 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4631 if (flags & PRINTER_ENUM_NETWORK)
4632 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4634 return WERR_OK; /* NT4sp5 does that */
4637 /********************************************************************
4638 * handle enumeration of printers at level 2
4639 ********************************************************************/
4641 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4642 NEW_BUFFER *buffer, uint32 offered,
4643 uint32 *needed, uint32 *returned)
4645 char *s = servername;
4647 if (flags & PRINTER_ENUM_LOCAL) {
4648 return enum_all_printers_info_2(buffer, offered, needed, returned);
4651 if (flags & PRINTER_ENUM_NAME) {
4652 if ((servername[0] == '\\') && (servername[1] == '\\'))
4654 if (is_myname_or_ipaddr(s))
4655 return enum_all_printers_info_2(buffer, offered, needed, returned);
4657 return WERR_INVALID_NAME;
4660 if (flags & PRINTER_ENUM_REMOTE)
4661 return WERR_UNKNOWN_LEVEL;
4666 /********************************************************************
4667 * handle enumeration of printers at level 5
4668 ********************************************************************/
4670 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4671 NEW_BUFFER *buffer, uint32 offered,
4672 uint32 *needed, uint32 *returned)
4674 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4678 /********************************************************************
4679 * api_spoolss_enumprinters
4681 * called from api_spoolss_enumprinters (see this to understand)
4682 ********************************************************************/
4684 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4686 uint32 flags = q_u->flags;
4687 UNISTR2 *servername = &q_u->servername;
4688 uint32 level = q_u->level;
4689 NEW_BUFFER *buffer = NULL;
4690 uint32 offered = q_u->offered;
4691 uint32 *needed = &r_u->needed;
4692 uint32 *returned = &r_u->returned;
4696 /* that's an [in out] buffer */
4697 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4698 buffer = r_u->buffer;
4700 DEBUG(4,("_spoolss_enumprinters\n"));
4707 * flags==PRINTER_ENUM_NAME
4708 * if name=="" then enumerates all printers
4709 * if name!="" then enumerate the printer
4710 * flags==PRINTER_ENUM_REMOTE
4711 * name is NULL, enumerate printers
4712 * Level 2: name!="" enumerates printers, name can't be NULL
4713 * Level 3: doesn't exist
4714 * Level 4: does a local registry lookup
4715 * Level 5: same as Level 2
4718 unistr2_to_ascii(name, servername, sizeof(name)-1);
4723 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4725 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4727 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4732 return WERR_UNKNOWN_LEVEL;
4735 /****************************************************************************
4736 ****************************************************************************/
4738 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4740 PRINTER_INFO_0 *printer=NULL;
4742 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4745 construct_printer_info_0(print_hnd, printer, snum);
4747 /* check the required size. */
4748 *needed += spoolss_size_printer_info_0(printer);
4750 if (!alloc_buffer_size(buffer, *needed)) {
4752 return WERR_INSUFFICIENT_BUFFER;
4755 /* fill the buffer with the structures */
4756 smb_io_printer_info_0("", buffer, printer, 0);
4761 if (*needed > offered) {
4762 return WERR_INSUFFICIENT_BUFFER;
4768 /****************************************************************************
4769 ****************************************************************************/
4771 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4773 PRINTER_INFO_1 *printer=NULL;
4775 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4778 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4780 /* check the required size. */
4781 *needed += spoolss_size_printer_info_1(printer);
4783 if (!alloc_buffer_size(buffer, *needed)) {
4785 return WERR_INSUFFICIENT_BUFFER;
4788 /* fill the buffer with the structures */
4789 smb_io_printer_info_1("", buffer, printer, 0);
4794 if (*needed > offered) {
4795 return WERR_INSUFFICIENT_BUFFER;
4801 /****************************************************************************
4802 ****************************************************************************/
4804 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4806 PRINTER_INFO_2 *printer=NULL;
4808 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4811 construct_printer_info_2(print_hnd, printer, snum);
4813 /* check the required size. */
4814 *needed += spoolss_size_printer_info_2(printer);
4816 if (!alloc_buffer_size(buffer, *needed)) {
4817 free_printer_info_2(printer);
4818 return WERR_INSUFFICIENT_BUFFER;
4821 /* fill the buffer with the structures */
4822 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4823 free_printer_info_2(printer);
4828 free_printer_info_2(printer);
4830 if (*needed > offered) {
4831 return WERR_INSUFFICIENT_BUFFER;
4837 /****************************************************************************
4838 ****************************************************************************/
4840 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4842 PRINTER_INFO_3 *printer=NULL;
4844 if (!construct_printer_info_3(print_hnd, &printer, snum))
4847 /* check the required size. */
4848 *needed += spoolss_size_printer_info_3(printer);
4850 if (!alloc_buffer_size(buffer, *needed)) {
4851 free_printer_info_3(printer);
4852 return WERR_INSUFFICIENT_BUFFER;
4855 /* fill the buffer with the structures */
4856 smb_io_printer_info_3("", buffer, printer, 0);
4859 free_printer_info_3(printer);
4861 if (*needed > offered) {
4862 return WERR_INSUFFICIENT_BUFFER;
4868 /****************************************************************************
4869 ****************************************************************************/
4871 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4873 PRINTER_INFO_4 *printer=NULL;
4875 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4878 if (!construct_printer_info_4(print_hnd, printer, snum))
4881 /* check the required size. */
4882 *needed += spoolss_size_printer_info_4(printer);
4884 if (!alloc_buffer_size(buffer, *needed)) {
4885 free_printer_info_4(printer);
4886 return WERR_INSUFFICIENT_BUFFER;
4889 /* fill the buffer with the structures */
4890 smb_io_printer_info_4("", buffer, printer, 0);
4893 free_printer_info_4(printer);
4895 if (*needed > offered) {
4896 return WERR_INSUFFICIENT_BUFFER;
4902 /****************************************************************************
4903 ****************************************************************************/
4905 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4907 PRINTER_INFO_5 *printer=NULL;
4909 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4912 if (!construct_printer_info_5(print_hnd, printer, snum))
4915 /* check the required size. */
4916 *needed += spoolss_size_printer_info_5(printer);
4918 if (!alloc_buffer_size(buffer, *needed)) {
4919 free_printer_info_5(printer);
4920 return WERR_INSUFFICIENT_BUFFER;
4923 /* fill the buffer with the structures */
4924 smb_io_printer_info_5("", buffer, printer, 0);
4927 free_printer_info_5(printer);
4929 if (*needed > offered) {
4930 return WERR_INSUFFICIENT_BUFFER;
4936 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4938 PRINTER_INFO_7 *printer=NULL;
4940 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4943 if (!construct_printer_info_7(print_hnd, printer, snum))
4946 /* check the required size. */
4947 *needed += spoolss_size_printer_info_7(printer);
4949 if (!alloc_buffer_size(buffer, *needed)) {
4950 free_printer_info_7(printer);
4951 return WERR_INSUFFICIENT_BUFFER;
4954 /* fill the buffer with the structures */
4955 smb_io_printer_info_7("", buffer, printer, 0);
4958 free_printer_info_7(printer);
4960 if (*needed > offered) {
4961 return WERR_INSUFFICIENT_BUFFER;
4967 /****************************************************************************
4968 ****************************************************************************/
4970 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4972 POLICY_HND *handle = &q_u->handle;
4973 uint32 level = q_u->level;
4974 NEW_BUFFER *buffer = NULL;
4975 uint32 offered = q_u->offered;
4976 uint32 *needed = &r_u->needed;
4977 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4981 /* that's an [in out] buffer */
4982 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4983 buffer = r_u->buffer;
4987 if (!get_printer_snum(p, handle, &snum))
4992 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4994 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4996 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4998 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5000 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5002 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5004 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5006 return WERR_UNKNOWN_LEVEL;
5009 /********************************************************************
5010 * fill a DRIVER_INFO_1 struct
5011 ********************************************************************/
5013 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5015 init_unistr( &info->name, driver.info_3->name);
5018 /********************************************************************
5019 * construct_printer_driver_info_1
5020 ********************************************************************/
5022 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5024 NT_PRINTER_INFO_LEVEL *printer = NULL;
5025 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5027 ZERO_STRUCT(driver);
5029 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5030 return WERR_INVALID_PRINTER_NAME;
5032 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5033 return WERR_UNKNOWN_PRINTER_DRIVER;
5035 fill_printer_driver_info_1(info, driver, servername, architecture);
5037 free_a_printer(&printer,2);
5042 /********************************************************************
5043 * construct_printer_driver_info_2
5044 * fill a printer_info_2 struct
5045 ********************************************************************/
5047 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5051 info->version=driver.info_3->cversion;
5053 init_unistr( &info->name, driver.info_3->name );
5054 init_unistr( &info->architecture, driver.info_3->environment );
5057 if (strlen(driver.info_3->driverpath)) {
5058 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5059 init_unistr( &info->driverpath, temp );
5061 init_unistr( &info->driverpath, "" );
5063 if (strlen(driver.info_3->datafile)) {
5064 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5065 init_unistr( &info->datafile, temp );
5067 init_unistr( &info->datafile, "" );
5069 if (strlen(driver.info_3->configfile)) {
5070 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5071 init_unistr( &info->configfile, temp );
5073 init_unistr( &info->configfile, "" );
5076 /********************************************************************
5077 * construct_printer_driver_info_2
5078 * fill a printer_info_2 struct
5079 ********************************************************************/
5081 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5083 NT_PRINTER_INFO_LEVEL *printer = NULL;
5084 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5086 ZERO_STRUCT(printer);
5087 ZERO_STRUCT(driver);
5089 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5090 return WERR_INVALID_PRINTER_NAME;
5092 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5093 return WERR_UNKNOWN_PRINTER_DRIVER;
5095 fill_printer_driver_info_2(info, driver, servername);
5097 free_a_printer(&printer,2);
5102 /********************************************************************
5103 * copy a strings array and convert to UNICODE
5105 * convert an array of ascii string to a UNICODE string
5106 ********************************************************************/
5108 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5116 DEBUG(6,("init_unistr_array\n"));
5127 v = ""; /* hack to handle null lists */
5130 /* hack to allow this to be used in places other than when generating
5131 the list of dependent files */
5134 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5138 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
5140 /* add one extra unit16 for the second terminating NULL */
5142 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5143 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5151 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5156 /* special case for ""; we need to add both NULL's here */
5158 (*uni_array)[j++]=0x0000;
5159 (*uni_array)[j]=0x0000;
5162 DEBUGADD(6,("last one:done\n"));
5164 /* return size of array in uint16's */
5169 /********************************************************************
5170 * construct_printer_info_3
5171 * fill a printer_info_3 struct
5172 ********************************************************************/
5174 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5180 info->version=driver.info_3->cversion;
5182 init_unistr( &info->name, driver.info_3->name );
5183 init_unistr( &info->architecture, driver.info_3->environment );
5185 if (strlen(driver.info_3->driverpath)) {
5186 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5187 init_unistr( &info->driverpath, temp );
5189 init_unistr( &info->driverpath, "" );
5191 if (strlen(driver.info_3->datafile)) {
5192 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5193 init_unistr( &info->datafile, temp );
5195 init_unistr( &info->datafile, "" );
5197 if (strlen(driver.info_3->configfile)) {
5198 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5199 init_unistr( &info->configfile, temp );
5201 init_unistr( &info->configfile, "" );
5203 if (strlen(driver.info_3->helpfile)) {
5204 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5205 init_unistr( &info->helpfile, temp );
5207 init_unistr( &info->helpfile, "" );
5209 init_unistr( &info->monitorname, driver.info_3->monitorname );
5210 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5212 info->dependentfiles=NULL;
5213 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5216 /********************************************************************
5217 * construct_printer_info_3
5218 * fill a printer_info_3 struct
5219 ********************************************************************/
5221 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5223 NT_PRINTER_INFO_LEVEL *printer = NULL;
5224 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5226 ZERO_STRUCT(driver);
5228 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5229 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5230 if (!W_ERROR_IS_OK(status))
5231 return WERR_INVALID_PRINTER_NAME;
5233 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5234 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5239 * I put this code in during testing. Helpful when commenting out the
5240 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5241 * as win2k always queries the driver using an infor level of 6.
5242 * I've left it in (but ifdef'd out) because I'll probably
5243 * use it in experimentation again in the future. --jerry 22/01/2002
5246 if (!W_ERROR_IS_OK(status)) {
5248 * Is this a W2k client ?
5251 /* Yes - try again with a WinNT driver. */
5253 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5254 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5258 if (!W_ERROR_IS_OK(status)) {
5259 free_a_printer(&printer,2);
5260 return WERR_UNKNOWN_PRINTER_DRIVER;
5268 fill_printer_driver_info_3(info, driver, servername);
5270 free_a_printer(&printer,2);
5275 /********************************************************************
5276 * construct_printer_info_6
5277 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5278 ********************************************************************/
5280 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5286 memset(&nullstr, '\0', sizeof(fstring));
5288 info->version=driver.info_3->cversion;
5290 init_unistr( &info->name, driver.info_3->name );
5291 init_unistr( &info->architecture, driver.info_3->environment );
5293 if (strlen(driver.info_3->driverpath)) {
5294 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5295 init_unistr( &info->driverpath, temp );
5297 init_unistr( &info->driverpath, "" );
5299 if (strlen(driver.info_3->datafile)) {
5300 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5301 init_unistr( &info->datafile, temp );
5303 init_unistr( &info->datafile, "" );
5305 if (strlen(driver.info_3->configfile)) {
5306 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5307 init_unistr( &info->configfile, temp );
5309 init_unistr( &info->configfile, "" );
5311 if (strlen(driver.info_3->helpfile)) {
5312 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5313 init_unistr( &info->helpfile, temp );
5315 init_unistr( &info->helpfile, "" );
5317 init_unistr( &info->monitorname, driver.info_3->monitorname );
5318 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5320 info->dependentfiles = NULL;
5321 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5323 info->previousdrivernames=NULL;
5324 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5326 info->driver_date.low=0;
5327 info->driver_date.high=0;
5330 info->driver_version_low=0;
5331 info->driver_version_high=0;
5333 init_unistr( &info->mfgname, "");
5334 init_unistr( &info->oem_url, "");
5335 init_unistr( &info->hardware_id, "");
5336 init_unistr( &info->provider, "");
5339 /********************************************************************
5340 * construct_printer_info_6
5341 * fill a printer_info_6 struct
5342 ********************************************************************/
5344 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5345 fstring servername, fstring architecture, uint32 version)
5347 NT_PRINTER_INFO_LEVEL *printer = NULL;
5348 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5351 ZERO_STRUCT(driver);
5353 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5355 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5357 if (!W_ERROR_IS_OK(status))
5358 return WERR_INVALID_PRINTER_NAME;
5360 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5362 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5364 if (!W_ERROR_IS_OK(status))
5367 * Is this a W2k client ?
5371 free_a_printer(&printer,2);
5372 return WERR_UNKNOWN_PRINTER_DRIVER;
5375 /* Yes - try again with a WinNT driver. */
5377 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5378 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5379 if (!W_ERROR_IS_OK(status)) {
5380 free_a_printer(&printer,2);
5381 return WERR_UNKNOWN_PRINTER_DRIVER;
5385 fill_printer_driver_info_6(info, driver, servername);
5387 free_a_printer(&printer,2);
5388 free_a_printer_driver(driver, 3);
5393 /****************************************************************************
5394 ****************************************************************************/
5396 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5398 SAFE_FREE(info->dependentfiles);
5401 /****************************************************************************
5402 ****************************************************************************/
5404 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5406 SAFE_FREE(info->dependentfiles);
5410 /****************************************************************************
5411 ****************************************************************************/
5413 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5415 DRIVER_INFO_1 *info=NULL;
5418 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5421 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5422 if (!W_ERROR_IS_OK(status)) {
5427 /* check the required size. */
5428 *needed += spoolss_size_printer_driver_info_1(info);
5430 if (!alloc_buffer_size(buffer, *needed)) {
5432 return WERR_INSUFFICIENT_BUFFER;
5435 /* fill the buffer with the structures */
5436 smb_io_printer_driver_info_1("", buffer, info, 0);
5441 if (*needed > offered)
5442 return WERR_INSUFFICIENT_BUFFER;
5447 /****************************************************************************
5448 ****************************************************************************/
5450 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5452 DRIVER_INFO_2 *info=NULL;
5455 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5458 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5459 if (!W_ERROR_IS_OK(status)) {
5464 /* check the required size. */
5465 *needed += spoolss_size_printer_driver_info_2(info);
5467 if (!alloc_buffer_size(buffer, *needed)) {
5469 return WERR_INSUFFICIENT_BUFFER;
5472 /* fill the buffer with the structures */
5473 smb_io_printer_driver_info_2("", buffer, info, 0);
5478 if (*needed > offered)
5479 return WERR_INSUFFICIENT_BUFFER;
5484 /****************************************************************************
5485 ****************************************************************************/
5487 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5494 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5495 if (!W_ERROR_IS_OK(status)) {
5499 /* check the required size. */
5500 *needed += spoolss_size_printer_driver_info_3(&info);
5502 if (!alloc_buffer_size(buffer, *needed)) {
5503 free_printer_driver_info_3(&info);
5504 return WERR_INSUFFICIENT_BUFFER;
5507 /* fill the buffer with the structures */
5508 smb_io_printer_driver_info_3("", buffer, &info, 0);
5510 free_printer_driver_info_3(&info);
5512 if (*needed > offered)
5513 return WERR_INSUFFICIENT_BUFFER;
5518 /****************************************************************************
5519 ****************************************************************************/
5521 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5528 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5529 if (!W_ERROR_IS_OK(status)) {
5533 /* check the required size. */
5534 *needed += spoolss_size_printer_driver_info_6(&info);
5536 if (!alloc_buffer_size(buffer, *needed)) {
5537 free_printer_driver_info_6(&info);
5538 return WERR_INSUFFICIENT_BUFFER;
5541 /* fill the buffer with the structures */
5542 smb_io_printer_driver_info_6("", buffer, &info, 0);
5544 free_printer_driver_info_6(&info);
5546 if (*needed > offered)
5547 return WERR_INSUFFICIENT_BUFFER;
5552 /****************************************************************************
5553 ****************************************************************************/
5555 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5557 POLICY_HND *handle = &q_u->handle;
5558 UNISTR2 *uni_arch = &q_u->architecture;
5559 uint32 level = q_u->level;
5560 uint32 clientmajorversion = q_u->clientmajorversion;
5561 NEW_BUFFER *buffer = NULL;
5562 uint32 offered = q_u->offered;
5563 uint32 *needed = &r_u->needed;
5564 uint32 *servermajorversion = &r_u->servermajorversion;
5565 uint32 *serverminorversion = &r_u->serverminorversion;
5568 fstring architecture;
5571 /* that's an [in out] buffer */
5572 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5573 buffer = r_u->buffer;
5575 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5578 *servermajorversion = 0;
5579 *serverminorversion = 0;
5581 fstrcpy(servername, get_called_name());
5582 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5584 if (!get_printer_snum(p, handle, &snum))
5589 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5591 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5593 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5595 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5598 return WERR_UNKNOWN_LEVEL;
5601 /****************************************************************************
5602 ****************************************************************************/
5604 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5606 POLICY_HND *handle = &q_u->handle;
5608 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5611 DEBUG(3,("Error in startpageprinter printer handle\n"));
5615 Printer->page_started=True;
5619 /****************************************************************************
5620 ****************************************************************************/
5622 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5624 POLICY_HND *handle = &q_u->handle;
5627 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5630 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5634 if (!get_printer_snum(p, handle, &snum))
5637 Printer->page_started=False;
5638 print_job_endpage(snum, Printer->jobid);
5643 /********************************************************************
5644 * api_spoolss_getprinter
5645 * called from the spoolss dispatcher
5647 ********************************************************************/
5649 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5651 POLICY_HND *handle = &q_u->handle;
5652 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5653 uint32 *jobid = &r_u->jobid;
5655 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5659 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5660 struct current_user user;
5663 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5667 get_current_user(&user, p);
5670 * a nice thing with NT is it doesn't listen to what you tell it.
5671 * when asked to send _only_ RAW datas, it tries to send datas
5674 * So I add checks like in NT Server ...
5677 if (info_1->p_datatype != 0) {
5678 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5679 if (strcmp(datatype, "RAW") != 0) {
5681 return WERR_INVALID_DATATYPE;
5685 /* get the share number of the printer */
5686 if (!get_printer_snum(p, handle, &snum)) {
5690 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5692 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5694 /* An error occured in print_job_start() so return an appropriate
5697 if (Printer->jobid == -1) {
5698 return map_werror_from_unix(errno);
5701 Printer->document_started=True;
5702 (*jobid) = Printer->jobid;
5707 /********************************************************************
5708 * api_spoolss_getprinter
5709 * called from the spoolss dispatcher
5711 ********************************************************************/
5713 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5715 POLICY_HND *handle = &q_u->handle;
5717 return _spoolss_enddocprinter_internal(p, handle);
5720 /****************************************************************************
5721 ****************************************************************************/
5723 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5725 POLICY_HND *handle = &q_u->handle;
5726 uint32 buffer_size = q_u->buffer_size;
5727 uint8 *buffer = q_u->buffer;
5728 uint32 *buffer_written = &q_u->buffer_size2;
5730 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5733 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5734 r_u->buffer_written = q_u->buffer_size2;
5738 if (!get_printer_snum(p, handle, &snum))
5741 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5742 if (*buffer_written == -1) {
5743 r_u->buffer_written = 0;
5744 if (errno == ENOSPC)
5745 return WERR_NO_SPOOL_SPACE;
5747 return WERR_ACCESS_DENIED;
5750 r_u->buffer_written = q_u->buffer_size2;
5755 /********************************************************************
5756 * api_spoolss_getprinter
5757 * called from the spoolss dispatcher
5759 ********************************************************************/
5761 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5764 struct current_user user;
5766 WERROR errcode = WERR_BADFUNC;
5767 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5769 get_current_user(&user, p);
5772 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5776 if (!get_printer_snum(p, handle, &snum))
5780 case PRINTER_CONTROL_PAUSE:
5781 if (print_queue_pause(&user, snum, &errcode)) {
5785 case PRINTER_CONTROL_RESUME:
5786 case PRINTER_CONTROL_UNPAUSE:
5787 if (print_queue_resume(&user, snum, &errcode)) {
5791 case PRINTER_CONTROL_PURGE:
5792 if (print_queue_purge(&user, snum, &errcode)) {
5797 return WERR_UNKNOWN_LEVEL;
5803 /********************************************************************
5804 * api_spoolss_abortprinter
5805 * From MSDN: "Deletes printer's spool file if printer is configured
5807 ********************************************************************/
5809 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5811 POLICY_HND *handle = &q_u->handle;
5812 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5814 struct current_user user;
5815 WERROR errcode = WERR_OK;
5818 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5822 if (!get_printer_snum(p, handle, &snum))
5825 get_current_user( &user, p );
5827 print_job_delete( &user, snum, Printer->jobid, &errcode );
5832 /********************************************************************
5833 * called by spoolss_api_setprinter
5834 * when updating a printer description
5835 ********************************************************************/
5837 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5838 const SPOOL_PRINTER_INFO_LEVEL *info,
5839 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5841 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5842 struct current_user user;
5846 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5848 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5849 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5850 OUR_HANDLE(handle)));
5852 result = WERR_BADFID;
5856 /* NT seems to like setting the security descriptor even though
5857 nothing may have actually changed. This causes annoying
5858 dialog boxes when the user doesn't have permission to change
5859 the security descriptor. */
5861 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5863 if (DEBUGLEVEL >= 10) {
5867 the_acl = old_secdesc_ctr->sec->dacl;
5868 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5869 PRINTERNAME(snum), the_acl->num_aces));
5871 for (i = 0; i < the_acl->num_aces; i++) {
5874 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5876 DEBUG(10, ("%s 0x%08x\n", sid_str,
5877 the_acl->ace[i].info.mask));
5880 the_acl = secdesc_ctr->sec->dacl;
5883 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5884 PRINTERNAME(snum), the_acl->num_aces));
5886 for (i = 0; i < the_acl->num_aces; i++) {
5889 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5891 DEBUG(10, ("%s 0x%08x\n", sid_str,
5892 the_acl->ace[i].info.mask));
5895 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5899 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5901 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5906 /* Work out which user is performing the operation */
5908 get_current_user(&user, p);
5910 /* Check the user has permissions to change the security
5911 descriptor. By experimentation with two NT machines, the user
5912 requires Full Access to the printer to change security
5915 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5916 result = WERR_ACCESS_DENIED;
5920 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5927 /********************************************************************
5928 Do Samba sanity checks on a printer info struct.
5929 this has changed purpose: it now "canonicalises" printer
5930 info from a client rather than just checking it is correct
5931 ********************************************************************/
5933 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5935 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5936 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5938 /* we force some elements to "correct" values */
5939 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5940 fstrcpy(info->sharename, lp_servicename(snum));
5941 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5942 get_called_name(), info->sharename);
5943 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5949 /****************************************************************************
5950 ****************************************************************************/
5952 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5954 extern userdom_struct current_user_info;
5955 char *cmd = lp_addprinter_cmd();
5961 fstring remote_machine = "%m";
5963 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5965 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5966 cmd, printer->info_2->printername, printer->info_2->sharename,
5967 printer->info_2->portname, printer->info_2->drivername,
5968 printer->info_2->location, printer->info_2->comment, remote_machine);
5970 DEBUG(10,("Running [%s]\n", command));
5971 ret = smbrun(command, &fd);
5972 DEBUGADD(10,("returned [%d]\n", ret));
5981 /* Get lines and convert them back to dos-codepage */
5982 qlines = fd_lines_load(fd, &numlines);
5983 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5987 /* Set the portname to what the script says the portname should be. */
5988 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5989 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5991 /* Send SIGHUP to process group... is there a better way? */
5994 /* reload our services immediately */
5995 reload_services( False );
5998 file_lines_free(qlines);
6002 /********************************************************************
6003 * Called by spoolss_api_setprinter
6004 * when updating a printer description.
6005 ********************************************************************/
6007 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6008 const SPOOL_PRINTER_INFO_LEVEL *info,
6009 DEVICEMODE *devmode)
6012 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6013 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6018 DEBUG(8,("update_printer\n"));
6023 result = WERR_BADFID;
6027 if (!get_printer_snum(p, handle, &snum)) {
6028 result = WERR_BADFID;
6032 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6033 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6034 result = WERR_BADFID;
6038 DEBUGADD(8,("Converting info_2 struct\n"));
6041 * convert_printer_info converts the incoming
6042 * info from the client and overwrites the info
6043 * just read from the tdb in the pointer 'printer'.
6046 if (!convert_printer_info(info, printer, level)) {
6047 result = WERR_NOMEM;
6052 /* we have a valid devmode
6053 convert it and link it*/
6055 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6056 if (!convert_devicemode(printer->info_2->printername, devmode,
6057 &printer->info_2->devmode)) {
6058 result = WERR_NOMEM;
6063 /* Do sanity check on the requested changes for Samba */
6065 if (!check_printer_ok(printer->info_2, snum)) {
6066 result = WERR_INVALID_PARAM;
6070 /* FIXME!!! If the driver has changed we really should verify that
6071 it is installed before doing much else --jerry */
6073 /* Check calling user has permission to update printer description */
6075 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6076 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6077 result = WERR_ACCESS_DENIED;
6081 /* Call addprinter hook */
6082 /* Check changes to see if this is really needed */
6084 if ( *lp_addprinter_cmd()
6085 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6086 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6087 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6088 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6090 if ( !add_printer_hook(printer) ) {
6091 result = WERR_ACCESS_DENIED;
6096 * make sure we actually reload the services after
6097 * this as smb.conf could have a new section in it
6098 * .... shouldn't .... but could
6100 reload_services(False);
6104 * When a *new* driver is bound to a printer, the drivername is used to
6105 * lookup previously saved driver initialization info, which is then
6106 * bound to the printer, simulating what happens in the Windows arch.
6108 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6110 if (!set_driver_init(printer, 2))
6112 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6113 printer->info_2->drivername));
6116 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6117 printer->info_2->drivername));
6119 notify_printer_driver(snum, printer->info_2->drivername);
6123 * flag which changes actually occured. This is a small subset of
6124 * all the possible changes. We also have to update things in the
6128 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6129 init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 );
6130 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6131 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6133 notify_printer_comment(snum, printer->info_2->comment);
6136 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6137 init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 );
6138 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6139 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6140 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6141 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6143 notify_printer_sharename(snum, printer->info_2->sharename);
6146 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6147 init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 );
6148 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6149 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6151 notify_printer_port(snum, printer->info_2->portname);
6154 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6155 init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 );
6156 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6157 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6159 notify_printer_location(snum, printer->info_2->location);
6162 /* here we need to update some more DsSpooler keys */
6163 /* uNCName, serverName, shortServerName */
6165 init_unistr2( &buffer, global_myname(), strlen(global_myname())+1 );
6166 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6167 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6168 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6169 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6171 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6172 global_myname(), printer->info_2->sharename );
6173 init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 );
6174 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6175 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6177 /* Update printer info */
6178 result = mod_a_printer(*printer, 2);
6181 free_a_printer(&printer, 2);
6182 free_a_printer(&old_printer, 2);
6188 /****************************************************************************
6189 ****************************************************************************/
6190 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6191 const SPOOL_PRINTER_INFO_LEVEL *info)
6194 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6196 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6199 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6206 if (!get_printer_snum(p, handle, &snum))
6209 nt_printer_publish(Printer, snum, info7->action);
6213 return WERR_UNKNOWN_LEVEL;
6216 /****************************************************************************
6217 ****************************************************************************/
6219 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6221 POLICY_HND *handle = &q_u->handle;
6222 uint32 level = q_u->level;
6223 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6224 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6225 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6226 uint32 command = q_u->command;
6228 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6231 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6235 /* check the level */
6238 return control_printer(handle, command, p);
6240 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6242 return update_printer_sec(handle, level, info, p,
6245 return publish_or_unpublish_printer(p, handle, info);
6247 return WERR_UNKNOWN_LEVEL;
6251 /****************************************************************************
6252 ****************************************************************************/
6254 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6256 POLICY_HND *handle = &q_u->handle;
6257 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6260 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6264 if (Printer->notify.client_connected==True) {
6267 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6269 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6270 !get_printer_snum(p, handle, &snum) )
6273 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6276 Printer->notify.flags=0;
6277 Printer->notify.options=0;
6278 Printer->notify.localmachine[0]='\0';
6279 Printer->notify.printerlocal=0;
6280 if (Printer->notify.option)
6281 free_spool_notify_option(&Printer->notify.option);
6282 Printer->notify.client_connected=False;
6287 /****************************************************************************
6288 ****************************************************************************/
6290 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6292 /* that's an [in out] buffer (despite appearences to the contrary) */
6293 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6296 return WERR_INVALID_PARAM; /* this is what a NT server
6297 returns for AddJob. AddJob
6298 must fail on non-local
6302 /****************************************************************************
6303 ****************************************************************************/
6305 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6306 int position, int snum)
6312 t=gmtime(&queue->time);
6313 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6315 job_info->jobid=queue->job;
6316 init_unistr(&job_info->printername, lp_servicename(snum));
6317 init_unistr(&job_info->machinename, temp_name);
6318 init_unistr(&job_info->username, queue->fs_user);
6319 init_unistr(&job_info->document, queue->fs_file);
6320 init_unistr(&job_info->datatype, "RAW");
6321 init_unistr(&job_info->text_status, "");
6322 job_info->status=nt_printj_status(queue->status);
6323 job_info->priority=queue->priority;
6324 job_info->position=position;
6325 job_info->totalpages=queue->page_count;
6326 job_info->pagesprinted=0;
6328 make_systemtime(&job_info->submitted, t);
6331 /****************************************************************************
6332 ****************************************************************************/
6334 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6335 int position, int snum,
6336 NT_PRINTER_INFO_LEVEL *ntprinter,
6337 DEVICEMODE *devmode)
6342 t=gmtime(&queue->time);
6343 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6345 job_info->jobid=queue->job;
6347 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6349 init_unistr(&job_info->machinename, temp_name);
6350 init_unistr(&job_info->username, queue->fs_user);
6351 init_unistr(&job_info->document, queue->fs_file);
6352 init_unistr(&job_info->notifyname, queue->fs_user);
6353 init_unistr(&job_info->datatype, "RAW");
6354 init_unistr(&job_info->printprocessor, "winprint");
6355 init_unistr(&job_info->parameters, "");
6356 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6357 init_unistr(&job_info->text_status, "");
6359 /* and here the security descriptor */
6361 job_info->status=nt_printj_status(queue->status);
6362 job_info->priority=queue->priority;
6363 job_info->position=position;
6364 job_info->starttime=0;
6365 job_info->untiltime=0;
6366 job_info->totalpages=queue->page_count;
6367 job_info->size=queue->size;
6368 make_systemtime(&(job_info->submitted), t);
6369 job_info->timeelapsed=0;
6370 job_info->pagesprinted=0;
6372 job_info->devmode = devmode;
6377 /****************************************************************************
6378 Enumjobs at level 1.
6379 ****************************************************************************/
6381 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6382 NEW_BUFFER *buffer, uint32 offered,
6383 uint32 *needed, uint32 *returned)
6388 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6395 for (i=0; i<*returned; i++)
6396 fill_job_info_1(&info[i], &queue[i], i, snum);
6400 /* check the required size. */
6401 for (i=0; i<*returned; i++)
6402 (*needed) += spoolss_size_job_info_1(&info[i]);
6404 if (!alloc_buffer_size(buffer, *needed)) {
6406 return WERR_INSUFFICIENT_BUFFER;
6409 /* fill the buffer with the structures */
6410 for (i=0; i<*returned; i++)
6411 smb_io_job_info_1("", buffer, &info[i], 0);
6416 if (*needed > offered) {
6418 return WERR_INSUFFICIENT_BUFFER;
6424 /****************************************************************************
6425 Enumjobs at level 2.
6426 ****************************************************************************/
6428 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6429 NEW_BUFFER *buffer, uint32 offered,
6430 uint32 *needed, uint32 *returned)
6432 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6433 JOB_INFO_2 *info = NULL;
6436 DEVICEMODE *devmode = NULL;
6438 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6441 result = WERR_NOMEM;
6445 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6446 if (!W_ERROR_IS_OK(result)) {
6451 /* this should not be a failure condition if the devmode is NULL */
6453 devmode = construct_dev_mode(snum);
6455 for (i=0; i<*returned; i++)
6456 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6459 free_a_printer(&ntprinter, 2);
6462 /* check the required size. */
6463 for (i=0; i<*returned; i++)
6464 (*needed) += spoolss_size_job_info_2(&info[i]);
6466 if (*needed > offered) {
6468 result = WERR_INSUFFICIENT_BUFFER;
6472 if (!alloc_buffer_size(buffer, *needed)) {
6474 result = WERR_INSUFFICIENT_BUFFER;
6478 /* fill the buffer with the structures */
6479 for (i=0; i<*returned; i++)
6480 smb_io_job_info_2("", buffer, &info[i], 0);
6485 free_a_printer(&ntprinter, 2);
6486 free_devmode(devmode);
6494 /****************************************************************************
6496 ****************************************************************************/
6498 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6500 POLICY_HND *handle = &q_u->handle;
6501 uint32 level = q_u->level;
6502 NEW_BUFFER *buffer = NULL;
6503 uint32 offered = q_u->offered;
6504 uint32 *needed = &r_u->needed;
6505 uint32 *returned = &r_u->returned;
6509 print_status_struct prt_status;
6510 print_queue_struct *queue=NULL;
6512 /* that's an [in out] buffer */
6513 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6514 buffer = r_u->buffer;
6516 DEBUG(4,("_spoolss_enumjobs\n"));
6521 if (!get_printer_snum(p, handle, &snum))
6524 *returned = print_queue_status(snum, &queue, &prt_status);
6525 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6527 if (*returned == 0) {
6528 set_enumjobs_timestamp(snum);
6535 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6536 set_enumjobs_timestamp(snum);
6539 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6540 set_enumjobs_timestamp(snum);
6545 return WERR_UNKNOWN_LEVEL;
6549 /****************************************************************************
6550 ****************************************************************************/
6552 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6557 /****************************************************************************
6558 ****************************************************************************/
6560 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6562 POLICY_HND *handle = &q_u->handle;
6563 uint32 jobid = q_u->jobid;
6564 uint32 command = q_u->command;
6566 struct current_user user;
6568 WERROR errcode = WERR_BADFUNC;
6570 if (!get_printer_snum(p, handle, &snum)) {
6574 if (!print_job_exists(snum, jobid)) {
6575 return WERR_INVALID_PRINTER_NAME;
6578 get_current_user(&user, p);
6581 case JOB_CONTROL_CANCEL:
6582 case JOB_CONTROL_DELETE:
6583 if (print_job_delete(&user, snum, jobid, &errcode)) {
6587 case JOB_CONTROL_PAUSE:
6588 if (print_job_pause(&user, snum, jobid, &errcode)) {
6592 case JOB_CONTROL_RESTART:
6593 case JOB_CONTROL_RESUME:
6594 if (print_job_resume(&user, snum, jobid, &errcode)) {
6599 return WERR_UNKNOWN_LEVEL;
6605 /****************************************************************************
6606 Enumerates all printer drivers at level 1.
6607 ****************************************************************************/
6609 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6614 fstring *list = NULL;
6616 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6617 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6621 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6623 ndrivers=get_ntdrivers(&list, architecture, version);
6624 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6630 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6631 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6632 SAFE_FREE(driver_info_1);
6636 else driver_info_1 = tdi1;
6639 for (i=0; i<ndrivers; i++) {
6641 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6642 ZERO_STRUCT(driver);
6643 status = get_a_printer_driver(&driver, 3, list[i],
6644 architecture, version);
6645 if (!W_ERROR_IS_OK(status)) {
6649 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6650 free_a_printer_driver(driver, 3);
6653 *returned+=ndrivers;
6657 /* check the required size. */
6658 for (i=0; i<*returned; i++) {
6659 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6660 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6663 if (!alloc_buffer_size(buffer, *needed)) {
6664 SAFE_FREE(driver_info_1);
6665 return WERR_INSUFFICIENT_BUFFER;
6668 /* fill the buffer with the driver structures */
6669 for (i=0; i<*returned; i++) {
6670 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6671 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6674 SAFE_FREE(driver_info_1);
6676 if (*needed > offered) {
6678 return WERR_INSUFFICIENT_BUFFER;
6684 /****************************************************************************
6685 Enumerates all printer drivers at level 2.
6686 ****************************************************************************/
6688 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6693 fstring *list = NULL;
6695 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6696 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6700 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6702 ndrivers=get_ntdrivers(&list, architecture, version);
6703 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6709 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6710 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6711 SAFE_FREE(driver_info_2);
6715 else driver_info_2 = tdi2;
6718 for (i=0; i<ndrivers; i++) {
6721 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6722 ZERO_STRUCT(driver);
6723 status = get_a_printer_driver(&driver, 3, list[i],
6724 architecture, version);
6725 if (!W_ERROR_IS_OK(status)) {
6729 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6730 free_a_printer_driver(driver, 3);
6733 *returned+=ndrivers;
6737 /* check the required size. */
6738 for (i=0; i<*returned; i++) {
6739 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6740 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6743 if (!alloc_buffer_size(buffer, *needed)) {
6744 SAFE_FREE(driver_info_2);
6745 return WERR_INSUFFICIENT_BUFFER;
6748 /* fill the buffer with the form structures */
6749 for (i=0; i<*returned; i++) {
6750 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6751 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6754 SAFE_FREE(driver_info_2);
6756 if (*needed > offered) {
6758 return WERR_INSUFFICIENT_BUFFER;
6764 /****************************************************************************
6765 Enumerates all printer drivers at level 3.
6766 ****************************************************************************/
6768 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6773 fstring *list = NULL;
6775 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6776 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6780 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6782 ndrivers=get_ntdrivers(&list, architecture, version);
6783 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6789 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6790 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6791 SAFE_FREE(driver_info_3);
6795 else driver_info_3 = tdi3;
6798 for (i=0; i<ndrivers; i++) {
6801 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6802 ZERO_STRUCT(driver);
6803 status = get_a_printer_driver(&driver, 3, list[i],
6804 architecture, version);
6805 if (!W_ERROR_IS_OK(status)) {
6809 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6810 free_a_printer_driver(driver, 3);
6813 *returned+=ndrivers;
6817 /* check the required size. */
6818 for (i=0; i<*returned; i++) {
6819 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6820 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6823 if (!alloc_buffer_size(buffer, *needed)) {
6824 SAFE_FREE(driver_info_3);
6825 return WERR_INSUFFICIENT_BUFFER;
6828 /* fill the buffer with the driver structures */
6829 for (i=0; i<*returned; i++) {
6830 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6831 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6834 for (i=0; i<*returned; i++)
6835 SAFE_FREE(driver_info_3[i].dependentfiles);
6837 SAFE_FREE(driver_info_3);
6839 if (*needed > offered) {
6841 return WERR_INSUFFICIENT_BUFFER;
6847 /****************************************************************************
6848 Enumerates all printer drivers.
6849 ****************************************************************************/
6851 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6853 UNISTR2 *environment = &q_u->environment;
6854 uint32 level = q_u->level;
6855 NEW_BUFFER *buffer = NULL;
6856 uint32 offered = q_u->offered;
6857 uint32 *needed = &r_u->needed;
6858 uint32 *returned = &r_u->returned;
6860 fstring *list = NULL;
6862 fstring architecture;
6864 /* that's an [in out] buffer */
6865 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6866 buffer = r_u->buffer;
6868 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6869 fstrcpy(servername, get_called_name());
6873 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6877 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6879 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6881 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6885 return WERR_UNKNOWN_LEVEL;
6889 /****************************************************************************
6890 ****************************************************************************/
6892 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6894 form->flag=list->flag;
6895 init_unistr(&form->name, list->name);
6896 form->width=list->width;
6897 form->length=list->length;
6898 form->left=list->left;
6899 form->top=list->top;
6900 form->right=list->right;
6901 form->bottom=list->bottom;
6904 /****************************************************************************
6905 ****************************************************************************/
6907 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6909 uint32 level = q_u->level;
6910 NEW_BUFFER *buffer = NULL;
6911 uint32 offered = q_u->offered;
6912 uint32 *needed = &r_u->needed;
6913 uint32 *numofforms = &r_u->numofforms;
6914 uint32 numbuiltinforms;
6916 nt_forms_struct *list=NULL;
6917 nt_forms_struct *builtinlist=NULL;
6922 /* that's an [in out] buffer */
6923 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6924 buffer = r_u->buffer;
6926 DEBUG(4,("_spoolss_enumforms\n"));
6927 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6928 DEBUGADD(5,("Info level [%d]\n", level));
6930 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6931 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6932 *numofforms = get_ntforms(&list);
6933 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6934 *numofforms += numbuiltinforms;
6936 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6940 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6945 /* construct the list of form structures */
6946 for (i=0; i<numbuiltinforms; i++) {
6947 DEBUGADD(6,("Filling form number [%d]\n",i));
6948 fill_form_1(&forms_1[i], &builtinlist[i]);
6951 SAFE_FREE(builtinlist);
6953 for (; i<*numofforms; i++) {
6954 DEBUGADD(6,("Filling form number [%d]\n",i));
6955 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6960 /* check the required size. */
6961 for (i=0; i<numbuiltinforms; i++) {
6962 DEBUGADD(6,("adding form [%d]'s size\n",i));
6963 buffer_size += spoolss_size_form_1(&forms_1[i]);
6965 for (; i<*numofforms; i++) {
6966 DEBUGADD(6,("adding form [%d]'s size\n",i));
6967 buffer_size += spoolss_size_form_1(&forms_1[i]);
6970 *needed=buffer_size;
6972 if (!alloc_buffer_size(buffer, buffer_size)){
6974 return WERR_INSUFFICIENT_BUFFER;
6977 /* fill the buffer with the form structures */
6978 for (i=0; i<numbuiltinforms; i++) {
6979 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6980 smb_io_form_1("", buffer, &forms_1[i], 0);
6982 for (; i<*numofforms; i++) {
6983 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6984 smb_io_form_1("", buffer, &forms_1[i], 0);
6989 if (*needed > offered) {
6991 return WERR_INSUFFICIENT_BUFFER;
6998 SAFE_FREE(builtinlist);
6999 return WERR_UNKNOWN_LEVEL;
7004 /****************************************************************************
7005 ****************************************************************************/
7007 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7009 uint32 level = q_u->level;
7010 UNISTR2 *uni_formname = &q_u->formname;
7011 NEW_BUFFER *buffer = NULL;
7012 uint32 offered = q_u->offered;
7013 uint32 *needed = &r_u->needed;
7015 nt_forms_struct *list=NULL;
7016 nt_forms_struct builtin_form;
7021 int numofforms=0, i=0;
7023 /* that's an [in out] buffer */
7024 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7025 buffer = r_u->buffer;
7027 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7029 DEBUG(4,("_spoolss_getform\n"));
7030 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7031 DEBUGADD(5,("Info level [%d]\n", level));
7033 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7034 if (!foundBuiltin) {
7035 numofforms = get_ntforms(&list);
7036 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7038 if (numofforms == 0)
7045 fill_form_1(&form_1, &builtin_form);
7048 /* Check if the requested name is in the list of form structures */
7049 for (i=0; i<numofforms; i++) {
7051 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7053 if (strequal(form_name, list[i].name)) {
7054 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7055 fill_form_1(&form_1, &list[i]);
7061 if (i == numofforms) {
7065 /* check the required size. */
7067 *needed=spoolss_size_form_1(&form_1);
7069 if (!alloc_buffer_size(buffer, buffer_size)){
7070 return WERR_INSUFFICIENT_BUFFER;
7073 if (*needed > offered) {
7074 return WERR_INSUFFICIENT_BUFFER;
7077 /* fill the buffer with the form structures */
7078 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7079 smb_io_form_1("", buffer, &form_1, 0);
7085 return WERR_UNKNOWN_LEVEL;
7089 /****************************************************************************
7090 ****************************************************************************/
7092 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7094 init_unistr(&port->port_name, name);
7097 /****************************************************************************
7098 ****************************************************************************/
7100 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7102 init_unistr(&port->port_name, name);
7103 init_unistr(&port->monitor_name, "Local Monitor");
7104 init_unistr(&port->description, "Local Port");
7105 #define PORT_TYPE_WRITE 1
7106 port->port_type=PORT_TYPE_WRITE;
7110 /****************************************************************************
7112 ****************************************************************************/
7114 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7116 PORT_INFO_1 *ports=NULL;
7119 if (*lp_enumports_cmd()) {
7120 char *cmd = lp_enumports_cmd();
7127 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7129 DEBUG(10,("Running [%s]\n", command));
7130 ret = smbrun(command, &fd);
7131 DEBUG(10,("Returned [%d]\n", ret));
7135 /* Is this the best error to return here? */
7136 return WERR_ACCESS_DENIED;
7140 qlines = fd_lines_load(fd, &numlines);
7141 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7145 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7146 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7147 dos_errstr(WERR_NOMEM)));
7148 file_lines_free(qlines);
7152 for (i=0; i<numlines; i++) {
7153 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7154 fill_port_1(&ports[i], qlines[i]);
7157 file_lines_free(qlines);
7160 *returned = numlines;
7163 *returned = 1; /* Sole Samba port returned. */
7165 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7168 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7170 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7173 /* check the required size. */
7174 for (i=0; i<*returned; i++) {
7175 DEBUGADD(6,("adding port [%d]'s size\n", i));
7176 *needed += spoolss_size_port_info_1(&ports[i]);
7179 if (!alloc_buffer_size(buffer, *needed)) {
7181 return WERR_INSUFFICIENT_BUFFER;
7184 /* fill the buffer with the ports structures */
7185 for (i=0; i<*returned; i++) {
7186 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7187 smb_io_port_1("", buffer, &ports[i], 0);
7192 if (*needed > offered) {
7194 return WERR_INSUFFICIENT_BUFFER;
7200 /****************************************************************************
7202 ****************************************************************************/
7204 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7206 PORT_INFO_2 *ports=NULL;
7209 if (*lp_enumports_cmd()) {
7210 char *cmd = lp_enumports_cmd();
7219 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7220 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7222 path = lp_lockdir();
7224 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7225 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7228 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7229 ret = smbrun(command, &fd);
7230 DEBUGADD(10,("returned [%d]\n", ret));
7234 /* Is this the best error to return here? */
7235 return WERR_ACCESS_DENIED;
7239 qlines = fd_lines_load(fd, &numlines);
7240 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7244 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7245 file_lines_free(qlines);
7249 for (i=0; i<numlines; i++) {
7250 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7251 fill_port_2(&(ports[i]), qlines[i]);
7254 file_lines_free(qlines);
7257 *returned = numlines;
7263 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7266 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7268 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7271 /* check the required size. */
7272 for (i=0; i<*returned; i++) {
7273 DEBUGADD(6,("adding port [%d]'s size\n", i));
7274 *needed += spoolss_size_port_info_2(&ports[i]);
7277 if (!alloc_buffer_size(buffer, *needed)) {
7279 return WERR_INSUFFICIENT_BUFFER;
7282 /* fill the buffer with the ports structures */
7283 for (i=0; i<*returned; i++) {
7284 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7285 smb_io_port_2("", buffer, &ports[i], 0);
7290 if (*needed > offered) {
7292 return WERR_INSUFFICIENT_BUFFER;
7298 /****************************************************************************
7300 ****************************************************************************/
7302 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7304 uint32 level = q_u->level;
7305 NEW_BUFFER *buffer = NULL;
7306 uint32 offered = q_u->offered;
7307 uint32 *needed = &r_u->needed;
7308 uint32 *returned = &r_u->returned;
7310 /* that's an [in out] buffer */
7311 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7312 buffer = r_u->buffer;
7314 DEBUG(4,("_spoolss_enumports\n"));
7321 return enumports_level_1(buffer, offered, needed, returned);
7323 return enumports_level_2(buffer, offered, needed, returned);
7325 return WERR_UNKNOWN_LEVEL;
7329 /****************************************************************************
7330 ****************************************************************************/
7332 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7333 const SPOOL_PRINTER_INFO_LEVEL *info,
7334 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7335 uint32 user_switch, const SPOOL_USER_CTR *user,
7338 NT_PRINTER_INFO_LEVEL *printer = NULL;
7341 WERROR err = WERR_OK;
7343 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7344 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7348 ZERO_STRUCTP(printer);
7350 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7351 if (!convert_printer_info(info, printer, 2)) {
7352 free_a_printer(&printer, 2);
7356 /* check to see if the printer already exists */
7358 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7359 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7360 printer->info_2->sharename));
7361 free_a_printer(&printer, 2);
7362 return WERR_PRINTER_ALREADY_EXISTS;
7365 /* FIXME!!! smbd should check to see if the driver is installed before
7366 trying to add a printer like this --jerry */
7368 if (*lp_addprinter_cmd() ) {
7369 if ( !add_printer_hook(printer) ) {
7370 free_a_printer(&printer,2);
7371 return WERR_ACCESS_DENIED;
7375 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7376 printer->info_2->sharename);
7379 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7380 free_a_printer(&printer,2);
7381 return WERR_ACCESS_DENIED;
7384 /* you must be a printer admin to add a new printer */
7385 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7386 free_a_printer(&printer,2);
7387 return WERR_ACCESS_DENIED;
7391 * Do sanity check on the requested changes for Samba.
7394 if (!check_printer_ok(printer->info_2, snum)) {
7395 free_a_printer(&printer,2);
7396 return WERR_INVALID_PARAM;
7400 * When a printer is created, the drivername bound to the printer is used
7401 * to lookup previously saved driver initialization info, which is then
7402 * bound to the new printer, simulating what happens in the Windows arch.
7407 set_driver_init(printer, 2);
7411 /* A valid devmode was included, convert and link it
7413 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7415 if (!convert_devicemode(printer->info_2->printername, devmode,
7416 &printer->info_2->devmode))
7420 /* write the ASCII on disk */
7421 err = mod_a_printer(*printer, 2);
7422 if (!W_ERROR_IS_OK(err)) {
7423 free_a_printer(&printer,2);
7427 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7428 /* Handle open failed - remove addition. */
7429 del_a_printer(printer->info_2->sharename);
7430 free_a_printer(&printer,2);
7431 return WERR_ACCESS_DENIED;
7434 update_c_setprinter(False);
7435 free_a_printer(&printer,2);
7440 /****************************************************************************
7441 ****************************************************************************/
7443 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7445 UNISTR2 *uni_srv_name = &q_u->server_name;
7446 uint32 level = q_u->level;
7447 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7448 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7449 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7450 uint32 user_switch = q_u->user_switch;
7451 SPOOL_USER_CTR *user = &q_u->user_ctr;
7452 POLICY_HND *handle = &r_u->handle;
7456 /* we don't handle yet */
7457 /* but I know what to do ... */
7458 return WERR_UNKNOWN_LEVEL;
7460 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7462 user_switch, user, handle);
7464 return WERR_UNKNOWN_LEVEL;
7468 /****************************************************************************
7469 ****************************************************************************/
7471 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7473 uint32 level = q_u->level;
7474 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7475 WERROR err = WERR_OK;
7476 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7477 struct current_user user;
7478 fstring driver_name;
7481 ZERO_STRUCT(driver);
7483 get_current_user(&user, p);
7485 if (!convert_printer_driver_info(info, &driver, level)) {
7490 DEBUG(5,("Cleaning driver's information\n"));
7491 err = clean_up_driver_struct(driver, level, &user);
7492 if (!W_ERROR_IS_OK(err))
7495 DEBUG(5,("Moving driver to final destination\n"));
7496 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7497 if (W_ERROR_IS_OK(err))
7498 err = WERR_ACCESS_DENIED;
7502 if (add_a_printer_driver(driver, level)!=0) {
7503 err = WERR_ACCESS_DENIED;
7507 /* BEGIN_ADMIN_LOG */
7510 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7511 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7512 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7515 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7516 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7517 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7523 * I think this is where he DrvUpgradePrinter() hook would be
7524 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7525 * server. Right now, we just need to send ourselves a message
7526 * to update each printer bound to this driver. --jerry
7529 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7530 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7535 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7536 * decide if the driver init data should be deleted. The rules are:
7537 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7538 * 2) delete init data only if there is no 2k/Xp driver
7539 * 3) always delete init data
7540 * The generalized rule is always use init data from the highest order driver.
7541 * It is necessary to follow the driver install by an initialization step to
7542 * finish off this process.
7545 version = driver.info_3->cversion;
7546 else if (level == 6)
7547 version = driver.info_6->version;
7552 * 9x printer driver - never delete init data
7555 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7560 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7561 * there is no 2k/Xp driver init data for this driver name.
7565 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7567 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7569 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7571 if (!del_driver_init(driver_name))
7572 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7575 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7577 free_a_printer_driver(driver1,3);
7578 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7585 * 2k or Xp printer driver - always delete init data
7588 if (!del_driver_init(driver_name))
7589 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7593 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7599 free_a_printer_driver(driver, level);
7603 /********************************************************************
7604 * spoolss_addprinterdriverex
7605 ********************************************************************/
7607 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7609 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7610 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7613 * we only support the semantics of AddPrinterDriver()
7614 * i.e. only copy files that are newer than existing ones
7617 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7618 return WERR_ACCESS_DENIED;
7620 ZERO_STRUCT(q_u_local);
7621 ZERO_STRUCT(r_u_local);
7623 /* just pass the information off to _spoolss_addprinterdriver() */
7624 q_u_local.server_name_ptr = q_u->server_name_ptr;
7625 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7626 q_u_local.level = q_u->level;
7627 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7629 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7632 /****************************************************************************
7633 ****************************************************************************/
7635 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7637 init_unistr(&info->name, name);
7640 /****************************************************************************
7641 ****************************************************************************/
7643 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7647 const char *short_archi;
7648 DRIVER_DIRECTORY_1 *info=NULL;
7650 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7652 if (!(short_archi = get_short_archi(long_archi)))
7653 return WERR_INVALID_ENVIRONMENT;
7655 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7658 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7660 DEBUG(4,("printer driver directory: [%s]\n", path));
7662 fill_driverdir_1(info, path);
7664 *needed += spoolss_size_driverdir_info_1(info);
7666 if (!alloc_buffer_size(buffer, *needed)) {
7668 return WERR_INSUFFICIENT_BUFFER;
7671 smb_io_driverdir_1("", buffer, info, 0);
7675 if (*needed > offered)
7676 return WERR_INSUFFICIENT_BUFFER;
7681 /****************************************************************************
7682 ****************************************************************************/
7684 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7686 UNISTR2 *name = &q_u->name;
7687 UNISTR2 *uni_environment = &q_u->environment;
7688 uint32 level = q_u->level;
7689 NEW_BUFFER *buffer = NULL;
7690 uint32 offered = q_u->offered;
7691 uint32 *needed = &r_u->needed;
7693 /* that's an [in out] buffer */
7694 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7695 buffer = r_u->buffer;
7697 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7703 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7705 return WERR_UNKNOWN_LEVEL;
7709 /****************************************************************************
7710 ****************************************************************************/
7712 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7714 POLICY_HND *handle = &q_u->handle;
7715 uint32 idx = q_u->index;
7716 uint32 in_value_len = q_u->valuesize;
7717 uint32 in_data_len = q_u->datasize;
7718 uint32 *out_max_value_len = &r_u->valuesize;
7719 uint16 **out_value = &r_u->value;
7720 uint32 *out_value_len = &r_u->realvaluesize;
7721 uint32 *out_type = &r_u->type;
7722 uint32 *out_max_data_len = &r_u->datasize;
7723 uint8 **data_out = &r_u->data;
7724 uint32 *out_data_len = &r_u->realdatasize;
7726 NT_PRINTER_INFO_LEVEL *printer = NULL;
7729 uint32 biggest_valuesize;
7730 uint32 biggest_datasize;
7732 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7735 REGISTRY_VALUE *val = NULL;
7736 NT_PRINTER_DATA *p_data;
7737 int i, key_index, num_values;
7740 ZERO_STRUCT( printer );
7744 *out_max_data_len = 0;
7748 DEBUG(5,("spoolss_enumprinterdata\n"));
7751 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7755 if (!get_printer_snum(p,handle, &snum))
7758 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7759 if (!W_ERROR_IS_OK(result))
7762 p_data = &printer->info_2->data;
7763 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7768 * The NT machine wants to know the biggest size of value and data
7770 * cf: MSDN EnumPrinterData remark section
7773 if ( !in_value_len && !in_data_len && (key_index != -1) )
7775 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7778 biggest_valuesize = 0;
7779 biggest_datasize = 0;
7781 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7783 for ( i=0; i<num_values; i++ )
7785 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7787 name_length = strlen(val->valuename);
7788 if ( strlen(val->valuename) > biggest_valuesize )
7789 biggest_valuesize = name_length;
7791 if ( val->size > biggest_datasize )
7792 biggest_datasize = val->size;
7794 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7798 /* the value is an UNICODE string but real_value_size is the length
7799 in bytes including the trailing 0 */
7801 *out_value_len = 2 * (1+biggest_valuesize);
7802 *out_data_len = biggest_datasize;
7804 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7810 * the value len is wrong in NT sp3
7811 * that's the number of bytes not the number of unicode chars
7814 if ( key_index != -1 )
7815 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7820 /* out_value should default to "" or else NT4 has
7821 problems unmarshalling the response */
7823 *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, "", in_value_len, 0);
7833 /* the data is counted in bytes */
7835 *out_max_data_len = in_data_len;
7836 *out_data_len = in_data_len;
7838 /* only allocate when given a non-zero data_len */
7840 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7842 result = WERR_NOMEM;
7846 result = WERR_NO_MORE_ITEMS;
7852 * - counted in bytes in the request
7853 * - counted in UNICODE chars in the max reply
7854 * - counted in bytes in the real size
7856 * take a pause *before* coding not *during* coding
7860 *out_max_value_len=(in_value_len/sizeof(uint16));
7861 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7863 result = WERR_NOMEM;
7867 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7871 *out_type = regval_type( val );
7873 /* data - counted in bytes */
7875 *out_max_data_len = in_data_len;
7876 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7878 result = WERR_NOMEM;
7881 data_len = (size_t)regval_size(val);
7882 memcpy( *data_out, regval_data_p(val), data_len );
7883 *out_data_len = data_len;
7887 free_a_printer(&printer, 2);
7891 /****************************************************************************
7892 ****************************************************************************/
7894 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7896 POLICY_HND *handle = &q_u->handle;
7897 UNISTR2 *value = &q_u->value;
7898 uint32 type = q_u->type;
7899 uint8 *data = q_u->data;
7900 uint32 real_len = q_u->real_len;
7902 NT_PRINTER_INFO_LEVEL *printer = NULL;
7904 WERROR status = WERR_OK;
7905 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7908 DEBUG(5,("spoolss_setprinterdata\n"));
7911 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7915 if (!get_printer_snum(p,handle, &snum))
7919 * Access check : NT returns "access denied" if you make a
7920 * SetPrinterData call without the necessary privildge.
7921 * we were originally returning OK if nothing changed
7922 * which made Win2k issue **a lot** of SetPrinterData
7923 * when connecting to a printer --jerry
7926 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7928 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7929 status = WERR_ACCESS_DENIED;
7933 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7934 if (!W_ERROR_IS_OK(status))
7937 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7940 * When client side code sets a magic printer data key, detect it and save
7941 * the current printer data and the magic key's data (its the DEVMODE) for
7942 * future printer/driver initializations.
7944 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7946 /* Set devmode and printer initialization info */
7947 status = save_driver_init( printer, 2, data, real_len );
7949 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7953 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7954 type, data, real_len );
7955 if ( W_ERROR_IS_OK(status) )
7956 status = mod_a_printer(*printer, 2);
7960 free_a_printer(&printer, 2);
7965 /****************************************************************************
7966 ****************************************************************************/
7968 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7970 POLICY_HND *handle = &q_u->handle;
7971 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7974 DEBUG(5,("_spoolss_resetprinter\n"));
7977 * All we do is to check to see if the handle and queue is valid.
7978 * This call really doesn't mean anything to us because we only
7979 * support RAW printing. --jerry
7983 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7987 if (!get_printer_snum(p,handle, &snum))
7991 /* blindly return success */
7996 /****************************************************************************
7997 ****************************************************************************/
7999 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8001 POLICY_HND *handle = &q_u->handle;
8002 UNISTR2 *value = &q_u->valuename;
8004 NT_PRINTER_INFO_LEVEL *printer = NULL;
8006 WERROR status = WERR_OK;
8007 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8010 DEBUG(5,("spoolss_deleteprinterdata\n"));
8013 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8017 if (!get_printer_snum(p, handle, &snum))
8020 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8021 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8022 return WERR_ACCESS_DENIED;
8025 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8026 if (!W_ERROR_IS_OK(status))
8029 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8031 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8033 free_a_printer(&printer, 2);
8038 /****************************************************************************
8039 ****************************************************************************/
8041 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8043 POLICY_HND *handle = &q_u->handle;
8044 FORM *form = &q_u->form;
8045 nt_forms_struct tmpForm;
8047 WERROR status = WERR_OK;
8048 NT_PRINTER_INFO_LEVEL *printer = NULL;
8051 nt_forms_struct *list=NULL;
8052 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8054 DEBUG(5,("spoolss_addform\n"));
8057 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8062 /* forms can be added on printer of on the print server handle */
8064 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8066 if (!get_printer_snum(p,handle, &snum))
8069 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8070 if (!W_ERROR_IS_OK(status))
8074 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8075 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8076 status = WERR_ACCESS_DENIED;
8080 /* can't add if builtin */
8082 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8083 status = WERR_ALREADY_EXISTS;
8087 count = get_ntforms(&list);
8089 if(!add_a_form(&list, form, &count)) {
8090 status = WERR_NOMEM;
8094 write_ntforms(&list, count);
8097 * ChangeID must always be set if this is a printer
8100 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8101 status = mod_a_printer(*printer, 2);
8105 free_a_printer(&printer, 2);
8111 /****************************************************************************
8112 ****************************************************************************/
8114 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8116 POLICY_HND *handle = &q_u->handle;
8117 UNISTR2 *form_name = &q_u->name;
8118 nt_forms_struct tmpForm;
8120 nt_forms_struct *list=NULL;
8121 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8123 WERROR status = WERR_OK;
8124 NT_PRINTER_INFO_LEVEL *printer = NULL;
8126 DEBUG(5,("spoolss_deleteform\n"));
8129 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8133 /* forms can be deleted on printer of on the print server handle */
8135 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8137 if (!get_printer_snum(p,handle, &snum))
8140 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8141 if (!W_ERROR_IS_OK(status))
8145 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8146 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8147 status = WERR_ACCESS_DENIED;
8151 /* can't delete if builtin */
8153 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8154 status = WERR_INVALID_PARAM;
8158 count = get_ntforms(&list);
8160 if ( !delete_a_form(&list, form_name, &count, &status ))
8164 * ChangeID must always be set if this is a printer
8167 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8168 status = mod_a_printer(*printer, 2);
8172 free_a_printer(&printer, 2);
8178 /****************************************************************************
8179 ****************************************************************************/
8181 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8183 POLICY_HND *handle = &q_u->handle;
8184 FORM *form = &q_u->form;
8185 nt_forms_struct tmpForm;
8187 WERROR status = WERR_OK;
8188 NT_PRINTER_INFO_LEVEL *printer = NULL;
8191 nt_forms_struct *list=NULL;
8192 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8194 DEBUG(5,("spoolss_setform\n"));
8197 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8201 /* forms can be modified on printer of on the print server handle */
8203 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8205 if (!get_printer_snum(p,handle, &snum))
8208 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8209 if (!W_ERROR_IS_OK(status))
8213 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8214 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8215 status = WERR_ACCESS_DENIED;
8219 /* can't set if builtin */
8220 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8221 status = WERR_INVALID_PARAM;
8225 count = get_ntforms(&list);
8226 update_a_form(&list, form, count);
8227 write_ntforms(&list, count);
8230 * ChangeID must always be set if this is a printer
8233 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8234 status = mod_a_printer(*printer, 2);
8239 free_a_printer(&printer, 2);
8245 /****************************************************************************
8246 enumprintprocessors level 1.
8247 ****************************************************************************/
8249 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8251 PRINTPROCESSOR_1 *info_1=NULL;
8253 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8258 init_unistr(&info_1->name, "winprint");
8260 *needed += spoolss_size_printprocessor_info_1(info_1);
8262 if (!alloc_buffer_size(buffer, *needed))
8263 return WERR_INSUFFICIENT_BUFFER;
8265 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8269 if (*needed > offered) {
8271 return WERR_INSUFFICIENT_BUFFER;
8277 /****************************************************************************
8278 ****************************************************************************/
8280 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8282 uint32 level = q_u->level;
8283 NEW_BUFFER *buffer = NULL;
8284 uint32 offered = q_u->offered;
8285 uint32 *needed = &r_u->needed;
8286 uint32 *returned = &r_u->returned;
8288 /* that's an [in out] buffer */
8289 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8290 buffer = r_u->buffer;
8292 DEBUG(5,("spoolss_enumprintprocessors\n"));
8295 * Enumerate the print processors ...
8297 * Just reply with "winprint", to keep NT happy
8298 * and I can use my nice printer checker.
8306 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8308 return WERR_UNKNOWN_LEVEL;
8312 /****************************************************************************
8313 enumprintprocdatatypes level 1.
8314 ****************************************************************************/
8316 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8318 PRINTPROCDATATYPE_1 *info_1=NULL;
8320 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8325 init_unistr(&info_1->name, "RAW");
8327 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8329 if (!alloc_buffer_size(buffer, *needed))
8330 return WERR_INSUFFICIENT_BUFFER;
8332 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8336 if (*needed > offered) {
8338 return WERR_INSUFFICIENT_BUFFER;
8344 /****************************************************************************
8345 ****************************************************************************/
8347 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8349 uint32 level = q_u->level;
8350 NEW_BUFFER *buffer = NULL;
8351 uint32 offered = q_u->offered;
8352 uint32 *needed = &r_u->needed;
8353 uint32 *returned = &r_u->returned;
8355 /* that's an [in out] buffer */
8356 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8357 buffer = r_u->buffer;
8359 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8366 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8368 return WERR_UNKNOWN_LEVEL;
8372 /****************************************************************************
8373 enumprintmonitors level 1.
8374 ****************************************************************************/
8376 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8378 PRINTMONITOR_1 *info_1=NULL;
8380 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8385 init_unistr(&info_1->name, "Local Port");
8387 *needed += spoolss_size_printmonitor_info_1(info_1);
8389 if (!alloc_buffer_size(buffer, *needed))
8390 return WERR_INSUFFICIENT_BUFFER;
8392 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8396 if (*needed > offered) {
8398 return WERR_INSUFFICIENT_BUFFER;
8404 /****************************************************************************
8405 enumprintmonitors level 2.
8406 ****************************************************************************/
8408 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8410 PRINTMONITOR_2 *info_2=NULL;
8412 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8417 init_unistr(&info_2->name, "Local Port");
8418 init_unistr(&info_2->environment, "Windows NT X86");
8419 init_unistr(&info_2->dll_name, "localmon.dll");
8421 *needed += spoolss_size_printmonitor_info_2(info_2);
8423 if (!alloc_buffer_size(buffer, *needed))
8424 return WERR_INSUFFICIENT_BUFFER;
8426 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8430 if (*needed > offered) {
8432 return WERR_INSUFFICIENT_BUFFER;
8438 /****************************************************************************
8439 ****************************************************************************/
8441 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8443 uint32 level = q_u->level;
8444 NEW_BUFFER *buffer = NULL;
8445 uint32 offered = q_u->offered;
8446 uint32 *needed = &r_u->needed;
8447 uint32 *returned = &r_u->returned;
8449 /* that's an [in out] buffer */
8450 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8451 buffer = r_u->buffer;
8453 DEBUG(5,("spoolss_enumprintmonitors\n"));
8456 * Enumerate the print monitors ...
8458 * Just reply with "Local Port", to keep NT happy
8459 * and I can use my nice printer checker.
8467 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8469 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8471 return WERR_UNKNOWN_LEVEL;
8475 /****************************************************************************
8476 ****************************************************************************/
8478 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8482 JOB_INFO_1 *info_1=NULL;
8484 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8486 if (info_1 == NULL) {
8490 for (i=0; i<count && found==False; i++) {
8491 if ((*queue)[i].job==(int)jobid)
8497 /* NT treats not found as bad param... yet another bad choice */
8498 return WERR_INVALID_PARAM;
8501 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8503 *needed += spoolss_size_job_info_1(info_1);
8505 if (!alloc_buffer_size(buffer, *needed)) {
8507 return WERR_INSUFFICIENT_BUFFER;
8510 smb_io_job_info_1("", buffer, info_1, 0);
8514 if (*needed > offered)
8515 return WERR_INSUFFICIENT_BUFFER;
8520 /****************************************************************************
8521 ****************************************************************************/
8523 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8528 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8530 DEVICEMODE *devmode = NULL;
8531 NT_DEVICEMODE *nt_devmode = NULL;
8533 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8535 ZERO_STRUCTP(info_2);
8537 if (info_2 == NULL) {
8542 for ( i=0; i<count && found==False; i++ )
8544 if ((*queue)[i].job == (int)jobid)
8550 /* NT treats not found as bad param... yet another bad
8552 ret = WERR_INVALID_PARAM;
8556 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8557 if (!W_ERROR_IS_OK(ret))
8561 * if the print job does not have a DEVMODE associated with it,
8562 * just use the one for the printer. A NULL devicemode is not
8563 * a failure condition
8566 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8567 devmode = construct_dev_mode(snum);
8569 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8570 ZERO_STRUCTP( devmode );
8571 convert_nt_devicemode( devmode, nt_devmode );
8575 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8577 *needed += spoolss_size_job_info_2(info_2);
8579 if (!alloc_buffer_size(buffer, *needed)) {
8580 ret = WERR_INSUFFICIENT_BUFFER;
8584 smb_io_job_info_2("", buffer, info_2, 0);
8586 if (*needed > offered) {
8587 ret = WERR_INSUFFICIENT_BUFFER;
8594 /* Cleanup allocated memory */
8596 free_job_info_2(info_2); /* Also frees devmode */
8598 free_a_printer(&ntprinter, 2);
8603 /****************************************************************************
8604 ****************************************************************************/
8606 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8608 POLICY_HND *handle = &q_u->handle;
8609 uint32 jobid = q_u->jobid;
8610 uint32 level = q_u->level;
8611 NEW_BUFFER *buffer = NULL;
8612 uint32 offered = q_u->offered;
8613 uint32 *needed = &r_u->needed;
8614 WERROR wstatus = WERR_OK;
8618 print_queue_struct *queue = NULL;
8619 print_status_struct prt_status;
8621 /* that's an [in out] buffer */
8622 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8623 buffer = r_u->buffer;
8625 DEBUG(5,("spoolss_getjob\n"));
8629 if (!get_printer_snum(p, handle, &snum))
8632 count = print_queue_status(snum, &queue, &prt_status);
8634 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8635 count, prt_status.status, prt_status.message));
8639 wstatus = getjob_level_1(&queue, count, snum, jobid,
8640 buffer, offered, needed);
8643 wstatus = getjob_level_2(&queue, count, snum, jobid,
8644 buffer, offered, needed);
8647 wstatus = WERR_UNKNOWN_LEVEL;
8655 /********************************************************************
8656 spoolss_getprinterdataex
8658 From MSDN documentation of GetPrinterDataEx: pass request
8659 to GetPrinterData if key is "PrinterDriverData".
8660 ********************************************************************/
8662 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8664 POLICY_HND *handle = &q_u->handle;
8665 uint32 in_size = q_u->size;
8666 uint32 *type = &r_u->type;
8667 uint32 *out_size = &r_u->size;
8668 uint8 **data = &r_u->data;
8669 uint32 *needed = &r_u->needed;
8670 fstring keyname, valuename;
8672 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8674 NT_PRINTER_INFO_LEVEL *printer = NULL;
8676 WERROR status = WERR_OK;
8678 DEBUG(4,("_spoolss_getprinterdataex\n"));
8680 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8681 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8683 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8684 keyname, valuename));
8686 /* in case of problem, return some default values */
8690 *out_size = in_size;
8693 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8694 status = WERR_BADFID;
8698 /* Is the handle to a printer or to the server? */
8700 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8701 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8702 status = WERR_INVALID_PARAM;
8706 if ( !get_printer_snum(p,handle, &snum) )
8709 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8710 if ( !W_ERROR_IS_OK(status) )
8713 /* check to see if the keyname is valid */
8714 if ( !strlen(keyname) ) {
8715 status = WERR_INVALID_PARAM;
8719 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8720 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8721 free_a_printer( &printer, 2 );
8722 status = WERR_BADFILE;
8726 /* When given a new keyname, we should just create it */
8728 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8730 if (*needed > *out_size)
8731 status = WERR_MORE_DATA;
8734 if ( !W_ERROR_IS_OK(status) )
8736 DEBUG(5, ("error: allocating %d\n", *out_size));
8738 /* reply this param doesn't exist */
8742 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8743 status = WERR_NOMEM;
8753 free_a_printer( &printer, 2 );
8758 /********************************************************************
8759 * spoolss_setprinterdataex
8760 ********************************************************************/
8762 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8764 POLICY_HND *handle = &q_u->handle;
8765 uint32 type = q_u->type;
8766 uint8 *data = q_u->data;
8767 uint32 real_len = q_u->real_len;
8769 NT_PRINTER_INFO_LEVEL *printer = NULL;
8771 WERROR status = WERR_OK;
8772 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8777 DEBUG(4,("_spoolss_setprinterdataex\n"));
8779 /* From MSDN documentation of SetPrinterDataEx: pass request to
8780 SetPrinterData if key is "PrinterDriverData" */
8783 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8787 if ( !get_printer_snum(p,handle, &snum) )
8791 * Access check : NT returns "access denied" if you make a
8792 * SetPrinterData call without the necessary privildge.
8793 * we were originally returning OK if nothing changed
8794 * which made Win2k issue **a lot** of SetPrinterData
8795 * when connecting to a printer --jerry
8798 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8800 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8801 return WERR_ACCESS_DENIED;
8804 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8805 if (!W_ERROR_IS_OK(status))
8808 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8809 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8811 /* check for OID in valuename */
8813 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8819 /* save the registry data */
8821 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8823 if ( W_ERROR_IS_OK(status) )
8825 /* save the OID if one was specified */
8827 fstrcat( keyname, "\\" );
8828 fstrcat( keyname, SPOOL_OID_KEY );
8831 * I'm not checking the status here on purpose. Don't know
8832 * if this is right, but I'm returning the status from the
8833 * previous set_printer_dataex() call. I have no idea if
8834 * this is right. --jerry
8837 set_printer_dataex( printer, keyname, valuename,
8838 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8841 status = mod_a_printer(*printer, 2);
8844 free_a_printer(&printer, 2);
8850 /********************************************************************
8851 * spoolss_deleteprinterdataex
8852 ********************************************************************/
8854 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8856 POLICY_HND *handle = &q_u->handle;
8857 UNISTR2 *value = &q_u->valuename;
8858 UNISTR2 *key = &q_u->keyname;
8860 NT_PRINTER_INFO_LEVEL *printer = NULL;
8862 WERROR status = WERR_OK;
8863 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8864 pstring valuename, keyname;
8866 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8869 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8873 if (!get_printer_snum(p, handle, &snum))
8876 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8877 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8878 return WERR_ACCESS_DENIED;
8881 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8882 if (!W_ERROR_IS_OK(status))
8885 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8886 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8888 status = delete_printer_dataex( printer, keyname, valuename );
8890 free_a_printer(&printer, 2);
8895 /********************************************************************
8896 * spoolss_enumprinterkey
8897 ********************************************************************/
8900 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8903 fstring *keynames = NULL;
8904 uint16 *enumkeys = NULL;
8907 POLICY_HND *handle = &q_u->handle;
8908 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8909 NT_PRINTER_DATA *data;
8910 NT_PRINTER_INFO_LEVEL *printer = NULL;
8912 WERROR status = WERR_BADFILE;
8915 DEBUG(4,("_spoolss_enumprinterkey\n"));
8918 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8922 if ( !get_printer_snum(p,handle, &snum) )
8925 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8926 if (!W_ERROR_IS_OK(status))
8929 /* get the list of subkey names */
8931 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8932 data = &printer->info_2->data;
8934 num_keys = get_printer_subkeys( data, key, &keynames );
8936 if ( num_keys == -1 ) {
8937 status = WERR_BADFILE;
8941 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8943 r_u->needed = printerkey_len*2;
8945 if ( q_u->size < r_u->needed ) {
8946 status = WERR_MORE_DATA;
8950 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8951 status = WERR_NOMEM;
8957 if ( q_u->size < r_u->needed )
8958 status = WERR_MORE_DATA;
8961 free_a_printer( &printer, 2 );
8962 SAFE_FREE( keynames );
8967 /********************************************************************
8968 * spoolss_deleteprinterkey
8969 ********************************************************************/
8971 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8973 POLICY_HND *handle = &q_u->handle;
8974 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8976 NT_PRINTER_INFO_LEVEL *printer = NULL;
8980 DEBUG(5,("spoolss_deleteprinterkey\n"));
8983 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8987 /* if keyname == NULL, return error */
8989 if ( !q_u->keyname.buffer )
8990 return WERR_INVALID_PARAM;
8992 if (!get_printer_snum(p, handle, &snum))
8995 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8996 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8997 return WERR_ACCESS_DENIED;
9000 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9001 if (!W_ERROR_IS_OK(status))
9004 /* delete the key and all subneys */
9006 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9008 status = delete_all_printer_data( printer->info_2, key );
9010 if ( W_ERROR_IS_OK(status) )
9011 status = mod_a_printer(*printer, 2);
9013 free_a_printer( &printer, 2 );
9019 /********************************************************************
9020 * spoolss_enumprinterdataex
9021 ********************************************************************/
9023 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9025 POLICY_HND *handle = &q_u->handle;
9026 uint32 in_size = q_u->size;
9029 NT_PRINTER_INFO_LEVEL *printer = NULL;
9030 PRINTER_ENUM_VALUES *enum_values = NULL;
9031 NT_PRINTER_DATA *p_data;
9033 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9038 REGISTRY_VALUE *val;
9043 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9046 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9051 * first check for a keyname of NULL or "". Win2k seems to send
9052 * this a lot and we should send back WERR_INVALID_PARAM
9053 * no need to spend time looking up the printer in this case.
9057 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9058 if ( !strlen(key) ) {
9059 result = WERR_INVALID_PARAM;
9063 /* get the printer off of disk */
9065 if (!get_printer_snum(p,handle, &snum))
9068 ZERO_STRUCT(printer);
9069 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9070 if (!W_ERROR_IS_OK(result))
9073 /* now look for a match on the key name */
9075 p_data = &printer->info_2->data;
9077 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9078 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9080 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9081 result = WERR_INVALID_PARAM;
9088 /* allocate the memory for the array of pointers -- if necessary */
9090 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9093 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9095 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
9096 num_entries*sizeof(PRINTER_ENUM_VALUES)));
9097 result = WERR_NOMEM;
9101 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9105 * loop through all params and build the array to pass
9106 * back to the client
9109 for ( i=0; i<num_entries; i++ )
9111 /* lookup the registry value */
9113 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9114 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9118 value_name = regval_name( val );
9119 init_unistr( &enum_values[i].valuename, value_name );
9120 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9121 enum_values[i].type = regval_type( val );
9123 data_len = regval_size( val );
9125 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9127 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9129 result = WERR_NOMEM;
9133 enum_values[i].data_len = data_len;
9135 /* keep track of the size of the array in bytes */
9137 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9140 /* housekeeping information in the reply */
9142 r_u->needed = needed;
9143 r_u->returned = num_entries;
9145 if (needed > in_size) {
9146 result = WERR_MORE_DATA;
9150 /* copy data into the reply */
9152 r_u->ctr.size = r_u->needed;
9153 r_u->ctr.size_of_array = r_u->returned;
9154 r_u->ctr.values = enum_values;
9160 free_a_printer(&printer, 2);
9165 /****************************************************************************
9166 ****************************************************************************/
9168 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9170 init_unistr(&info->name, name);
9173 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9174 UNISTR2 *environment,
9181 const char *short_archi;
9182 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9184 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9186 if (!(short_archi = get_short_archi(long_archi)))
9187 return WERR_INVALID_ENVIRONMENT;
9189 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9192 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9194 fill_printprocessordirectory_1(info, path);
9196 *needed += spoolss_size_printprocessordirectory_info_1(info);
9198 if (!alloc_buffer_size(buffer, *needed)) {
9200 return WERR_INSUFFICIENT_BUFFER;
9203 smb_io_printprocessordirectory_1("", buffer, info, 0);
9207 if (*needed > offered)
9208 return WERR_INSUFFICIENT_BUFFER;
9213 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9215 uint32 level = q_u->level;
9216 NEW_BUFFER *buffer = NULL;
9217 uint32 offered = q_u->offered;
9218 uint32 *needed = &r_u->needed;
9221 /* that's an [in out] buffer */
9222 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9223 buffer = r_u->buffer;
9225 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9231 result = getprintprocessordirectory_level_1
9232 (&q_u->name, &q_u->environment, buffer, offered, needed);
9235 result = WERR_UNKNOWN_LEVEL;
9243 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9244 SPOOL_R_REPLYOPENPRINTER *r_u)
9246 DEBUG(5,("_spoolss_replyopenprinter\n"));
9248 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9253 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9254 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9256 DEBUG(5,("_spoolss_replycloseprinter\n"));