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=%lu)\n", handlename, (unsigned long)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=%lu)\n", aprinter, (unsigned long)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 [%p]", 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 %lu messages in list\n", (unsigned long)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")) {
2396 const char *string="C:\\PRINTERS";
2398 *needed = 2*(strlen(string)+1);
2399 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2401 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2403 /* it's done by hand ready to go on the wire */
2404 for (i=0; i<strlen(string); i++) {
2405 (*data)[2*i]=string[i];
2406 (*data)[2*i+1]='\0';
2411 if (!StrCaseCmp(value, "Architecture")) {
2412 const char *string="Windows NT x86";
2414 *needed = 2*(strlen(string)+1);
2415 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2417 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2418 for (i=0; i<strlen(string); i++) {
2419 (*data)[2*i]=string[i];
2420 (*data)[2*i+1]='\0';
2425 if (!StrCaseCmp(value, "DsPresent")) {
2427 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2429 SIVAL(*data, 0, 0x01);
2434 if (!StrCaseCmp(value, "DNSMachineName")) {
2437 if (!get_myfullname(hostname))
2438 return WERR_BADFILE;
2440 *needed = 2*(strlen(hostname)+1);
2441 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2443 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2444 for (i=0; i<strlen(hostname); i++) {
2445 (*data)[2*i]=hostname[i];
2446 (*data)[2*i+1]='\0';
2452 return WERR_BADFILE;
2455 /********************************************************************
2456 * spoolss_getprinterdata
2457 ********************************************************************/
2459 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2461 POLICY_HND *handle = &q_u->handle;
2462 UNISTR2 *valuename = &q_u->valuename;
2463 uint32 in_size = q_u->size;
2464 uint32 *type = &r_u->type;
2465 uint32 *out_size = &r_u->size;
2466 uint8 **data = &r_u->data;
2467 uint32 *needed = &r_u->needed;
2470 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2471 NT_PRINTER_INFO_LEVEL *printer = NULL;
2475 * Reminder: when it's a string, the length is in BYTES
2476 * even if UNICODE is negociated.
2481 *out_size = in_size;
2483 /* in case of problem, return some default values */
2488 DEBUG(4,("_spoolss_getprinterdata\n"));
2491 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2492 status = WERR_BADFID;
2496 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2498 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2499 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2502 if ( !get_printer_snum(p,handle, &snum) ) {
2503 status = WERR_BADFID;
2507 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2508 if ( !W_ERROR_IS_OK(status) )
2511 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2513 if ( strequal(value, "ChangeId") ) {
2515 *needed = sizeof(uint32);
2516 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2517 status = WERR_NOMEM;
2520 SIVAL( *data, 0, printer->info_2->changeid );
2524 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2527 if (*needed > *out_size)
2528 status = WERR_MORE_DATA;
2531 if ( !W_ERROR_IS_OK(status) )
2533 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2535 /* reply this param doesn't exist */
2538 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2540 free_a_printer( &printer, 2 );
2549 /* cleanup & exit */
2552 free_a_printer( &printer, 2 );
2557 /*********************************************************
2558 Connect to the client machine.
2559 **********************************************************/
2561 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2562 struct in_addr *client_ip, const char *remote_machine)
2564 ZERO_STRUCTP(the_cli);
2566 if(cli_initialise(the_cli) == NULL) {
2567 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2571 if ( is_zero_ip(*client_ip) ) {
2572 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2573 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2574 cli_shutdown(the_cli);
2578 if (ismyip(the_cli->dest_ip)) {
2579 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2580 cli_shutdown(the_cli);
2585 the_cli->dest_ip.s_addr = client_ip->s_addr;
2586 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2587 inet_ntoa(*client_ip) ));
2590 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2591 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) ));
2592 cli_shutdown(the_cli);
2596 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2597 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2599 cli_shutdown(the_cli);
2603 the_cli->protocol = PROTOCOL_NT1;
2605 if (!cli_negprot(the_cli)) {
2606 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2607 cli_shutdown(the_cli);
2611 if (the_cli->protocol != PROTOCOL_NT1) {
2612 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2613 cli_shutdown(the_cli);
2618 * Do an anonymous session setup.
2621 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2622 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2623 cli_shutdown(the_cli);
2627 if (!(the_cli->sec_mode & 1)) {
2628 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2629 cli_shutdown(the_cli);
2633 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2634 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) ));
2635 cli_shutdown(the_cli);
2640 * Ok - we have an anonymous connection to the IPC$ share.
2641 * Now start the NT Domain stuff :-).
2644 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2645 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)));
2646 cli_nt_session_close(the_cli);
2647 cli_ulogoff(the_cli);
2648 cli_shutdown(the_cli);
2655 /***************************************************************************
2656 Connect to the client.
2657 ****************************************************************************/
2659 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2660 uint32 localprinter, uint32 type,
2661 POLICY_HND *handle, struct in_addr *client_ip)
2666 * If it's the first connection, contact the client
2667 * and connect to the IPC$ share anonymously
2669 if (smb_connections==0) {
2670 fstring unix_printer;
2672 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2674 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2677 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2678 /* Tell the connections db we're now interested in printer
2679 * notify messages. */
2680 register_message_flags( True, FLAG_MSG_PRINTING );
2684 * Tell the specific printing tdb we want messages for this printer
2685 * by registering our PID.
2688 if (!print_notify_register_pid(snum))
2689 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2693 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2696 if (!W_ERROR_IS_OK(result))
2697 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2698 dos_errstr(result)));
2700 return (W_ERROR_IS_OK(result));
2703 /********************************************************************
2705 * ReplyFindFirstPrinterChangeNotifyEx
2707 * before replying OK: status=0 a rpc call is made to the workstation
2708 * asking ReplyOpenPrinter
2710 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2711 * called from api_spoolss_rffpcnex
2712 ********************************************************************/
2714 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2716 POLICY_HND *handle = &q_u->handle;
2717 uint32 flags = q_u->flags;
2718 uint32 options = q_u->options;
2719 UNISTR2 *localmachine = &q_u->localmachine;
2720 uint32 printerlocal = q_u->printerlocal;
2722 SPOOL_NOTIFY_OPTION *option = q_u->option;
2723 struct in_addr client_ip;
2725 /* store the notify value in the printer struct */
2727 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2730 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2734 Printer->notify.flags=flags;
2735 Printer->notify.options=options;
2736 Printer->notify.printerlocal=printerlocal;
2738 if (Printer->notify.option)
2739 free_spool_notify_option(&Printer->notify.option);
2741 Printer->notify.option=dup_spool_notify_option(option);
2743 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2744 sizeof(Printer->notify.localmachine)-1);
2746 /* Connect to the client machine and send a ReplyOpenPrinter */
2748 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2750 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2751 !get_printer_snum(p, handle, &snum) )
2754 client_ip.s_addr = inet_addr(p->conn->client_address);
2756 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2757 Printer->notify.printerlocal, 1,
2758 &Printer->notify.client_hnd, &client_ip))
2759 return WERR_SERVER_UNAVAILABLE;
2761 Printer->notify.client_connected=True;
2766 /*******************************************************************
2767 * fill a notify_info_data with the servername
2768 ********************************************************************/
2770 void spoolss_notify_server_name(int snum,
2771 SPOOL_NOTIFY_INFO_DATA *data,
2772 print_queue_struct *queue,
2773 NT_PRINTER_INFO_LEVEL *printer,
2774 TALLOC_CTX *mem_ctx)
2776 pstring temp_name, temp;
2779 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2781 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2783 data->notify_data.data.length = len;
2784 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2786 if (!data->notify_data.data.string) {
2787 data->notify_data.data.length = 0;
2791 memcpy(data->notify_data.data.string, temp, len);
2794 /*******************************************************************
2795 * fill a notify_info_data with the printername (not including the servername).
2796 ********************************************************************/
2798 void spoolss_notify_printer_name(int snum,
2799 SPOOL_NOTIFY_INFO_DATA *data,
2800 print_queue_struct *queue,
2801 NT_PRINTER_INFO_LEVEL *printer,
2802 TALLOC_CTX *mem_ctx)
2807 /* the notify name should not contain the \\server\ part */
2808 char *p = strrchr(printer->info_2->printername, '\\');
2811 p = printer->info_2->printername;
2816 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2818 data->notify_data.data.length = len;
2819 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2821 if (!data->notify_data.data.string) {
2822 data->notify_data.data.length = 0;
2826 memcpy(data->notify_data.data.string, temp, len);
2829 /*******************************************************************
2830 * fill a notify_info_data with the servicename
2831 ********************************************************************/
2833 void spoolss_notify_share_name(int snum,
2834 SPOOL_NOTIFY_INFO_DATA *data,
2835 print_queue_struct *queue,
2836 NT_PRINTER_INFO_LEVEL *printer,
2837 TALLOC_CTX *mem_ctx)
2842 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2844 data->notify_data.data.length = len;
2845 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2847 if (!data->notify_data.data.string) {
2848 data->notify_data.data.length = 0;
2852 memcpy(data->notify_data.data.string, temp, len);
2855 /*******************************************************************
2856 * fill a notify_info_data with the port name
2857 ********************************************************************/
2859 void spoolss_notify_port_name(int snum,
2860 SPOOL_NOTIFY_INFO_DATA *data,
2861 print_queue_struct *queue,
2862 NT_PRINTER_INFO_LEVEL *printer,
2863 TALLOC_CTX *mem_ctx)
2868 /* even if it's strange, that's consistant in all the code */
2870 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2872 data->notify_data.data.length = len;
2873 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2875 if (!data->notify_data.data.string) {
2876 data->notify_data.data.length = 0;
2880 memcpy(data->notify_data.data.string, temp, len);
2883 /*******************************************************************
2884 * fill a notify_info_data with the printername
2885 * but it doesn't exist, have to see what to do
2886 ********************************************************************/
2888 void spoolss_notify_driver_name(int snum,
2889 SPOOL_NOTIFY_INFO_DATA *data,
2890 print_queue_struct *queue,
2891 NT_PRINTER_INFO_LEVEL *printer,
2892 TALLOC_CTX *mem_ctx)
2897 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2899 data->notify_data.data.length = len;
2900 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2902 if (!data->notify_data.data.string) {
2903 data->notify_data.data.length = 0;
2907 memcpy(data->notify_data.data.string, temp, len);
2910 /*******************************************************************
2911 * fill a notify_info_data with the comment
2912 ********************************************************************/
2914 void spoolss_notify_comment(int snum,
2915 SPOOL_NOTIFY_INFO_DATA *data,
2916 print_queue_struct *queue,
2917 NT_PRINTER_INFO_LEVEL *printer,
2918 TALLOC_CTX *mem_ctx)
2923 if (*printer->info_2->comment == '\0')
2924 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2926 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2928 data->notify_data.data.length = len;
2929 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2931 if (!data->notify_data.data.string) {
2932 data->notify_data.data.length = 0;
2936 memcpy(data->notify_data.data.string, temp, len);
2939 /*******************************************************************
2940 * fill a notify_info_data with the comment
2941 * location = "Room 1, floor 2, building 3"
2942 ********************************************************************/
2944 void spoolss_notify_location(int snum,
2945 SPOOL_NOTIFY_INFO_DATA *data,
2946 print_queue_struct *queue,
2947 NT_PRINTER_INFO_LEVEL *printer,
2948 TALLOC_CTX *mem_ctx)
2953 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2955 data->notify_data.data.length = len;
2956 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2958 if (!data->notify_data.data.string) {
2959 data->notify_data.data.length = 0;
2963 memcpy(data->notify_data.data.string, temp, len);
2966 /*******************************************************************
2967 * fill a notify_info_data with the device mode
2968 * jfm:xxxx don't to it for know but that's a real problem !!!
2969 ********************************************************************/
2971 static void spoolss_notify_devmode(int snum,
2972 SPOOL_NOTIFY_INFO_DATA *data,
2973 print_queue_struct *queue,
2974 NT_PRINTER_INFO_LEVEL *printer,
2975 TALLOC_CTX *mem_ctx)
2979 /*******************************************************************
2980 * fill a notify_info_data with the separator file name
2981 ********************************************************************/
2983 void spoolss_notify_sepfile(int snum,
2984 SPOOL_NOTIFY_INFO_DATA *data,
2985 print_queue_struct *queue,
2986 NT_PRINTER_INFO_LEVEL *printer,
2987 TALLOC_CTX *mem_ctx)
2992 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2994 data->notify_data.data.length = len;
2995 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2997 if (!data->notify_data.data.string) {
2998 data->notify_data.data.length = 0;
3002 memcpy(data->notify_data.data.string, temp, len);
3005 /*******************************************************************
3006 * fill a notify_info_data with the print processor
3007 * jfm:xxxx return always winprint to indicate we don't do anything to it
3008 ********************************************************************/
3010 void spoolss_notify_print_processor(int snum,
3011 SPOOL_NOTIFY_INFO_DATA *data,
3012 print_queue_struct *queue,
3013 NT_PRINTER_INFO_LEVEL *printer,
3014 TALLOC_CTX *mem_ctx)
3019 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3021 data->notify_data.data.length = len;
3022 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3024 if (!data->notify_data.data.string) {
3025 data->notify_data.data.length = 0;
3029 memcpy(data->notify_data.data.string, temp, len);
3032 /*******************************************************************
3033 * fill a notify_info_data with the print processor options
3034 * jfm:xxxx send an empty string
3035 ********************************************************************/
3037 void spoolss_notify_parameters(int snum,
3038 SPOOL_NOTIFY_INFO_DATA *data,
3039 print_queue_struct *queue,
3040 NT_PRINTER_INFO_LEVEL *printer,
3041 TALLOC_CTX *mem_ctx)
3046 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3048 data->notify_data.data.length = len;
3049 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3051 if (!data->notify_data.data.string) {
3052 data->notify_data.data.length = 0;
3056 memcpy(data->notify_data.data.string, temp, len);
3059 /*******************************************************************
3060 * fill a notify_info_data with the data type
3061 * jfm:xxxx always send RAW as data type
3062 ********************************************************************/
3064 void spoolss_notify_datatype(int snum,
3065 SPOOL_NOTIFY_INFO_DATA *data,
3066 print_queue_struct *queue,
3067 NT_PRINTER_INFO_LEVEL *printer,
3068 TALLOC_CTX *mem_ctx)
3073 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3075 data->notify_data.data.length = len;
3076 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3078 if (!data->notify_data.data.string) {
3079 data->notify_data.data.length = 0;
3083 memcpy(data->notify_data.data.string, temp, len);
3086 /*******************************************************************
3087 * fill a notify_info_data with the security descriptor
3088 * jfm:xxxx send an null pointer to say no security desc
3089 * have to implement security before !
3090 ********************************************************************/
3092 static void spoolss_notify_security_desc(int snum,
3093 SPOOL_NOTIFY_INFO_DATA *data,
3094 print_queue_struct *queue,
3095 NT_PRINTER_INFO_LEVEL *printer,
3096 TALLOC_CTX *mem_ctx)
3098 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3099 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3102 /*******************************************************************
3103 * fill a notify_info_data with the attributes
3104 * jfm:xxxx a samba printer is always shared
3105 ********************************************************************/
3107 void spoolss_notify_attributes(int snum,
3108 SPOOL_NOTIFY_INFO_DATA *data,
3109 print_queue_struct *queue,
3110 NT_PRINTER_INFO_LEVEL *printer,
3111 TALLOC_CTX *mem_ctx)
3113 data->notify_data.value[0] = printer->info_2->attributes;
3114 data->notify_data.value[1] = 0;
3117 /*******************************************************************
3118 * fill a notify_info_data with the priority
3119 ********************************************************************/
3121 static void spoolss_notify_priority(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3127 data->notify_data.value[0] = printer->info_2->priority;
3128 data->notify_data.value[1] = 0;
3131 /*******************************************************************
3132 * fill a notify_info_data with the default priority
3133 ********************************************************************/
3135 static void spoolss_notify_default_priority(int snum,
3136 SPOOL_NOTIFY_INFO_DATA *data,
3137 print_queue_struct *queue,
3138 NT_PRINTER_INFO_LEVEL *printer,
3139 TALLOC_CTX *mem_ctx)
3141 data->notify_data.value[0] = printer->info_2->default_priority;
3142 data->notify_data.value[1] = 0;
3145 /*******************************************************************
3146 * fill a notify_info_data with the start time
3147 ********************************************************************/
3149 static void spoolss_notify_start_time(int snum,
3150 SPOOL_NOTIFY_INFO_DATA *data,
3151 print_queue_struct *queue,
3152 NT_PRINTER_INFO_LEVEL *printer,
3153 TALLOC_CTX *mem_ctx)
3155 data->notify_data.value[0] = printer->info_2->starttime;
3156 data->notify_data.value[1] = 0;
3159 /*******************************************************************
3160 * fill a notify_info_data with the until time
3161 ********************************************************************/
3163 static void spoolss_notify_until_time(int snum,
3164 SPOOL_NOTIFY_INFO_DATA *data,
3165 print_queue_struct *queue,
3166 NT_PRINTER_INFO_LEVEL *printer,
3167 TALLOC_CTX *mem_ctx)
3169 data->notify_data.value[0] = printer->info_2->untiltime;
3170 data->notify_data.value[1] = 0;
3173 /*******************************************************************
3174 * fill a notify_info_data with the status
3175 ********************************************************************/
3177 static void spoolss_notify_status(int snum,
3178 SPOOL_NOTIFY_INFO_DATA *data,
3179 print_queue_struct *queue,
3180 NT_PRINTER_INFO_LEVEL *printer,
3181 TALLOC_CTX *mem_ctx)
3183 print_status_struct status;
3185 print_queue_length(snum, &status);
3186 data->notify_data.value[0]=(uint32) status.status;
3187 data->notify_data.value[1] = 0;
3190 /*******************************************************************
3191 * fill a notify_info_data with the number of jobs queued
3192 ********************************************************************/
3194 void spoolss_notify_cjobs(int snum,
3195 SPOOL_NOTIFY_INFO_DATA *data,
3196 print_queue_struct *queue,
3197 NT_PRINTER_INFO_LEVEL *printer,
3198 TALLOC_CTX *mem_ctx)
3200 data->notify_data.value[0] = print_queue_length(snum, NULL);
3201 data->notify_data.value[1] = 0;
3204 /*******************************************************************
3205 * fill a notify_info_data with the average ppm
3206 ********************************************************************/
3208 static void spoolss_notify_average_ppm(int snum,
3209 SPOOL_NOTIFY_INFO_DATA *data,
3210 print_queue_struct *queue,
3211 NT_PRINTER_INFO_LEVEL *printer,
3212 TALLOC_CTX *mem_ctx)
3214 /* always respond 8 pages per minutes */
3215 /* a little hard ! */
3216 data->notify_data.value[0] = printer->info_2->averageppm;
3217 data->notify_data.value[1] = 0;
3220 /*******************************************************************
3221 * fill a notify_info_data with username
3222 ********************************************************************/
3224 static void spoolss_notify_username(int snum,
3225 SPOOL_NOTIFY_INFO_DATA *data,
3226 print_queue_struct *queue,
3227 NT_PRINTER_INFO_LEVEL *printer,
3228 TALLOC_CTX *mem_ctx)
3233 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3235 data->notify_data.data.length = len;
3236 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3238 if (!data->notify_data.data.string) {
3239 data->notify_data.data.length = 0;
3243 memcpy(data->notify_data.data.string, temp, len);
3246 /*******************************************************************
3247 * fill a notify_info_data with job status
3248 ********************************************************************/
3250 static void spoolss_notify_job_status(int snum,
3251 SPOOL_NOTIFY_INFO_DATA *data,
3252 print_queue_struct *queue,
3253 NT_PRINTER_INFO_LEVEL *printer,
3254 TALLOC_CTX *mem_ctx)
3256 data->notify_data.value[0]=nt_printj_status(queue->status);
3257 data->notify_data.value[1] = 0;
3260 /*******************************************************************
3261 * fill a notify_info_data with job name
3262 ********************************************************************/
3264 static void spoolss_notify_job_name(int snum,
3265 SPOOL_NOTIFY_INFO_DATA *data,
3266 print_queue_struct *queue,
3267 NT_PRINTER_INFO_LEVEL *printer,
3268 TALLOC_CTX *mem_ctx)
3273 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3275 data->notify_data.data.length = len;
3276 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3278 if (!data->notify_data.data.string) {
3279 data->notify_data.data.length = 0;
3283 memcpy(data->notify_data.data.string, temp, len);
3286 /*******************************************************************
3287 * fill a notify_info_data with job status
3288 ********************************************************************/
3290 static void spoolss_notify_job_status_string(int snum,
3291 SPOOL_NOTIFY_INFO_DATA *data,
3292 print_queue_struct *queue,
3293 NT_PRINTER_INFO_LEVEL *printer,
3294 TALLOC_CTX *mem_ctx)
3297 * Now we're returning job status codes we just return a "" here. JRA.
3304 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3307 switch (queue->status) {
3312 p = ""; /* NT provides the paused string */
3321 #endif /* NO LONGER NEEDED. */
3323 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3325 data->notify_data.data.length = len;
3326 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3328 if (!data->notify_data.data.string) {
3329 data->notify_data.data.length = 0;
3333 memcpy(data->notify_data.data.string, temp, len);
3336 /*******************************************************************
3337 * fill a notify_info_data with job time
3338 ********************************************************************/
3340 static void spoolss_notify_job_time(int snum,
3341 SPOOL_NOTIFY_INFO_DATA *data,
3342 print_queue_struct *queue,
3343 NT_PRINTER_INFO_LEVEL *printer,
3344 TALLOC_CTX *mem_ctx)
3346 data->notify_data.value[0]=0x0;
3347 data->notify_data.value[1]=0;
3350 /*******************************************************************
3351 * fill a notify_info_data with job size
3352 ********************************************************************/
3354 static void spoolss_notify_job_size(int snum,
3355 SPOOL_NOTIFY_INFO_DATA *data,
3356 print_queue_struct *queue,
3357 NT_PRINTER_INFO_LEVEL *printer,
3358 TALLOC_CTX *mem_ctx)
3360 data->notify_data.value[0]=queue->size;
3361 data->notify_data.value[1]=0;
3364 /*******************************************************************
3365 * fill a notify_info_data with page info
3366 ********************************************************************/
3367 static void spoolss_notify_total_pages(int snum,
3368 SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer,
3371 TALLOC_CTX *mem_ctx)
3373 data->notify_data.value[0]=queue->page_count;
3374 data->notify_data.value[1]=0;
3377 /*******************************************************************
3378 * fill a notify_info_data with pages printed info.
3379 ********************************************************************/
3380 static void spoolss_notify_pages_printed(int snum,
3381 SPOOL_NOTIFY_INFO_DATA *data,
3382 print_queue_struct *queue,
3383 NT_PRINTER_INFO_LEVEL *printer,
3384 TALLOC_CTX *mem_ctx)
3386 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3387 data->notify_data.value[1]=0;
3390 /*******************************************************************
3391 Fill a notify_info_data with job position.
3392 ********************************************************************/
3394 static void spoolss_notify_job_position(int snum,
3395 SPOOL_NOTIFY_INFO_DATA *data,
3396 print_queue_struct *queue,
3397 NT_PRINTER_INFO_LEVEL *printer,
3398 TALLOC_CTX *mem_ctx)
3400 data->notify_data.value[0]=queue->job;
3401 data->notify_data.value[1]=0;
3404 /*******************************************************************
3405 Fill a notify_info_data with submitted time.
3406 ********************************************************************/
3408 static void spoolss_notify_submitted_time(int snum,
3409 SPOOL_NOTIFY_INFO_DATA *data,
3410 print_queue_struct *queue,
3411 NT_PRINTER_INFO_LEVEL *printer,
3412 TALLOC_CTX *mem_ctx)
3419 t=gmtime(&queue->time);
3421 len = sizeof(SYSTEMTIME);
3423 data->notify_data.data.length = len;
3424 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3426 if (!data->notify_data.data.string) {
3427 data->notify_data.data.length = 0;
3431 make_systemtime(&st, t);
3434 * Systemtime must be linearized as a set of UINT16's.
3435 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3438 p = (char *)data->notify_data.data.string;
3439 SSVAL(p, 0, st.year);
3440 SSVAL(p, 2, st.month);
3441 SSVAL(p, 4, st.dayofweek);
3442 SSVAL(p, 6, st.day);
3443 SSVAL(p, 8, st.hour);
3444 SSVAL(p, 10, st.minute);
3445 SSVAL(p, 12, st.second);
3446 SSVAL(p, 14, st.milliseconds);
3449 struct s_notify_info_data_table
3455 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3456 print_queue_struct *queue,
3457 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3460 /* A table describing the various print notification constants and
3461 whether the notification data is a pointer to a variable sized
3462 buffer, a one value uint32 or a two value uint32. */
3464 static const struct s_notify_info_data_table notify_info_data_table[] =
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3489 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3490 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3491 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3511 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3512 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3513 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3514 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3517 /*******************************************************************
3518 Return the size of info_data structure.
3519 ********************************************************************/
3521 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3525 for (i = 0; i < sizeof(notify_info_data_table); i++)
3527 if ( (notify_info_data_table[i].type == type)
3528 && (notify_info_data_table[i].field == field) )
3530 switch(notify_info_data_table[i].size)
3532 case NOTIFY_ONE_VALUE:
3533 case NOTIFY_TWO_VALUE:
3538 /* The only pointer notify data I have seen on
3539 the wire is the submitted time and this has
3540 the notify size set to 4. -tpot */
3542 case NOTIFY_POINTER:
3545 case NOTIFY_SECDESC:
3551 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3556 /*******************************************************************
3557 Return the type of notify_info_data.
3558 ********************************************************************/
3560 static int type_of_notify_info_data(uint16 type, uint16 field)
3564 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3565 if (notify_info_data_table[i].type == type &&
3566 notify_info_data_table[i].field == field)
3567 return notify_info_data_table[i].size;
3573 /****************************************************************************
3574 ****************************************************************************/
3576 static int search_notify(uint16 type, uint16 field, int *value)
3580 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3581 if (notify_info_data_table[i].type == type &&
3582 notify_info_data_table[i].field == field &&
3583 notify_info_data_table[i].fn != NULL) {
3592 /****************************************************************************
3593 ****************************************************************************/
3595 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3597 info_data->type = type;
3598 info_data->field = field;
3599 info_data->reserved = 0;
3601 info_data->size = size_of_notify_info_data(type, field);
3602 info_data->enc_type = type_of_notify_info_data(type, field);
3609 /*******************************************************************
3611 * fill a notify_info struct with info asked
3613 ********************************************************************/
3615 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3616 snum, SPOOL_NOTIFY_OPTION_TYPE
3617 *option_type, uint32 id,
3618 TALLOC_CTX *mem_ctx)
3624 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3625 NT_PRINTER_INFO_LEVEL *printer = NULL;
3626 print_queue_struct *queue=NULL;
3628 type=option_type->type;
3630 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3631 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3632 option_type->count, lp_servicename(snum)));
3634 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3637 for(field_num=0; field_num<option_type->count; field_num++) {
3638 field = option_type->fields[field_num];
3640 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3642 if (!search_notify(type, field, &j) )
3645 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3646 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3651 current_data = &info->data[info->count];
3653 construct_info_data(current_data, type, field, id);
3655 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3656 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3658 notify_info_data_table[j].fn(snum, current_data, queue,
3664 free_a_printer(&printer, 2);
3668 /*******************************************************************
3670 * fill a notify_info struct with info asked
3672 ********************************************************************/
3674 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3675 SPOOL_NOTIFY_INFO *info,
3676 NT_PRINTER_INFO_LEVEL *printer,
3677 int snum, SPOOL_NOTIFY_OPTION_TYPE
3678 *option_type, uint32 id,
3679 TALLOC_CTX *mem_ctx)
3685 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3687 DEBUG(4,("construct_notify_jobs_info\n"));
3689 type = option_type->type;
3691 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3692 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3693 option_type->count));
3695 for(field_num=0; field_num<option_type->count; field_num++) {
3696 field = option_type->fields[field_num];
3698 if (!search_notify(type, field, &j) )
3701 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3702 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3705 else info->data = tid;
3707 current_data=&(info->data[info->count]);
3709 construct_info_data(current_data, type, field, id);
3710 notify_info_data_table[j].fn(snum, current_data, queue,
3719 * JFM: The enumeration is not that simple, it's even non obvious.
3721 * let's take an example: I want to monitor the PRINTER SERVER for
3722 * the printer's name and the number of jobs currently queued.
3723 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3724 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3726 * I have 3 printers on the back of my server.
3728 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3731 * 1 printer 1 name 1
3732 * 2 printer 1 cjob 1
3733 * 3 printer 2 name 2
3734 * 4 printer 2 cjob 2
3735 * 5 printer 3 name 3
3736 * 6 printer 3 name 3
3738 * that's the print server case, the printer case is even worse.
3741 /*******************************************************************
3743 * enumerate all printers on the printserver
3744 * fill a notify_info struct with info asked
3746 ********************************************************************/
3748 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3749 SPOOL_NOTIFY_INFO *info,
3750 TALLOC_CTX *mem_ctx)
3753 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3754 int n_services=lp_numservices();
3757 SPOOL_NOTIFY_OPTION *option;
3758 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3760 DEBUG(4,("printserver_notify_info\n"));
3765 option=Printer->notify.option;
3771 for (i=0; i<option->count; i++) {
3772 option_type=&(option->ctr.type[i]);
3774 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3777 for (snum=0; snum<n_services; snum++)
3779 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3780 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3786 * Debugging information, don't delete.
3789 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3790 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3791 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3793 for (i=0; i<info->count; i++) {
3794 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3795 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3796 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3803 /*******************************************************************
3805 * fill a notify_info struct with info asked
3807 ********************************************************************/
3809 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3810 TALLOC_CTX *mem_ctx)
3813 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3816 SPOOL_NOTIFY_OPTION *option;
3817 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3819 print_queue_struct *queue=NULL;
3820 print_status_struct status;
3822 DEBUG(4,("printer_notify_info\n"));
3827 option=Printer->notify.option;
3833 get_printer_snum(p, hnd, &snum);
3835 for (i=0; i<option->count; i++) {
3836 option_type=&option->ctr.type[i];
3838 switch ( option_type->type ) {
3839 case PRINTER_NOTIFY_TYPE:
3840 if(construct_notify_printer_info(Printer, info, snum,
3846 case JOB_NOTIFY_TYPE: {
3847 NT_PRINTER_INFO_LEVEL *printer = NULL;
3849 count = print_queue_status(snum, &queue, &status);
3851 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3854 for (j=0; j<count; j++) {
3855 construct_notify_jobs_info(&queue[j], info,
3862 free_a_printer(&printer, 2);
3872 * Debugging information, don't delete.
3875 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3876 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3877 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3879 for (i=0; i<info->count; i++) {
3880 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3881 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3882 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3888 /********************************************************************
3890 ********************************************************************/
3892 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3894 POLICY_HND *handle = &q_u->handle;
3895 SPOOL_NOTIFY_INFO *info = &r_u->info;
3897 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3898 WERROR result = WERR_BADFID;
3900 /* we always have a NOTIFY_INFO struct */
3904 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3905 OUR_HANDLE(handle)));
3909 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3912 * We are now using the change value, and
3913 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3914 * I don't have a global notification system, I'm sending back all the
3915 * informations even when _NOTHING_ has changed.
3918 /* We need to keep track of the change value to send back in
3919 RRPCN replies otherwise our updates are ignored. */
3921 Printer->notify.fnpcn = True;
3923 if (Printer->notify.client_connected) {
3924 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3925 Printer->notify.change = q_u->change;
3928 /* just ignore the SPOOL_NOTIFY_OPTION */
3930 switch (Printer->printer_type) {
3931 case PRINTER_HANDLE_IS_PRINTSERVER:
3932 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3935 case PRINTER_HANDLE_IS_PRINTER:
3936 result = printer_notify_info(p, handle, info, p->mem_ctx);
3940 Printer->notify.fnpcn = False;
3946 /********************************************************************
3947 * construct_printer_info_0
3948 * fill a printer_info_0 struct
3949 ********************************************************************/
3951 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3955 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3956 counter_printer_0 *session_counter;
3957 uint32 global_counter;
3960 print_status_struct status;
3962 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3965 count = print_queue_length(snum, &status);
3967 /* check if we already have a counter for this printer */
3968 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3970 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3971 if (session_counter->snum == snum)
3975 /* it's the first time, add it to the list */
3976 if (session_counter==NULL) {
3977 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3978 free_a_printer(&ntprinter, 2);
3981 ZERO_STRUCTP(session_counter);
3982 session_counter->snum=snum;
3983 session_counter->counter=0;
3984 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3988 session_counter->counter++;
3991 * the global_counter should be stored in a TDB as it's common to all the clients
3992 * and should be zeroed on samba startup
3994 global_counter=session_counter->counter;
3996 pstrcpy(chaine,ntprinter->info_2->printername);
3998 init_unistr(&printer->printername, chaine);
4000 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
4001 init_unistr(&printer->servername, chaine);
4003 printer->cjobs = count;
4004 printer->total_jobs = 0;
4005 printer->total_bytes = 0;
4007 setuptime = (time_t)ntprinter->info_2->setuptime;
4008 t=gmtime(&setuptime);
4010 printer->year = t->tm_year+1900;
4011 printer->month = t->tm_mon+1;
4012 printer->dayofweek = t->tm_wday;
4013 printer->day = t->tm_mday;
4014 printer->hour = t->tm_hour;
4015 printer->minute = t->tm_min;
4016 printer->second = t->tm_sec;
4017 printer->milliseconds = 0;
4019 printer->global_counter = global_counter;
4020 printer->total_pages = 0;
4022 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4023 printer->major_version = 0x0005; /* NT 5 */
4024 printer->build_version = 0x0893; /* build 2195 */
4026 printer->unknown7 = 0x1;
4027 printer->unknown8 = 0x0;
4028 printer->unknown9 = 0x0;
4029 printer->session_counter = session_counter->counter;
4030 printer->unknown11 = 0x0;
4031 printer->printer_errors = 0x0; /* number of print failure */
4032 printer->unknown13 = 0x0;
4033 printer->unknown14 = 0x1;
4034 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4035 printer->unknown16 = 0x0;
4036 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4037 printer->unknown18 = 0x0;
4038 printer->status = nt_printq_status(status.status);
4039 printer->unknown20 = 0x0;
4040 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4041 printer->unknown22 = 0x0;
4042 printer->unknown23 = 0x6; /* 6 ???*/
4043 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4044 printer->unknown25 = 0;
4045 printer->unknown26 = 0;
4046 printer->unknown27 = 0;
4047 printer->unknown28 = 0;
4048 printer->unknown29 = 0;
4050 free_a_printer(&ntprinter,2);
4054 /********************************************************************
4055 * construct_printer_info_1
4056 * fill a printer_info_1 struct
4057 ********************************************************************/
4058 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4062 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4064 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4067 printer->flags=flags;
4069 if (*ntprinter->info_2->comment == '\0') {
4070 init_unistr(&printer->comment, lp_comment(snum));
4071 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4072 ntprinter->info_2->drivername, lp_comment(snum));
4075 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4076 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4077 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4080 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4082 init_unistr(&printer->description, chaine);
4083 init_unistr(&printer->name, chaine2);
4085 free_a_printer(&ntprinter,2);
4090 /****************************************************************************
4091 Free a DEVMODE struct.
4092 ****************************************************************************/
4094 static void free_dev_mode(DEVICEMODE *dev)
4099 SAFE_FREE(dev->private);
4104 /****************************************************************************
4105 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4106 should be valid upon entry
4107 ****************************************************************************/
4109 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4111 if ( !devmode || !ntdevmode )
4114 init_unistr(&devmode->devicename, ntdevmode->devicename);
4116 init_unistr(&devmode->formname, ntdevmode->formname);
4118 devmode->specversion = ntdevmode->specversion;
4119 devmode->driverversion = ntdevmode->driverversion;
4120 devmode->size = ntdevmode->size;
4121 devmode->driverextra = ntdevmode->driverextra;
4122 devmode->fields = ntdevmode->fields;
4124 devmode->orientation = ntdevmode->orientation;
4125 devmode->papersize = ntdevmode->papersize;
4126 devmode->paperlength = ntdevmode->paperlength;
4127 devmode->paperwidth = ntdevmode->paperwidth;
4128 devmode->scale = ntdevmode->scale;
4129 devmode->copies = ntdevmode->copies;
4130 devmode->defaultsource = ntdevmode->defaultsource;
4131 devmode->printquality = ntdevmode->printquality;
4132 devmode->color = ntdevmode->color;
4133 devmode->duplex = ntdevmode->duplex;
4134 devmode->yresolution = ntdevmode->yresolution;
4135 devmode->ttoption = ntdevmode->ttoption;
4136 devmode->collate = ntdevmode->collate;
4137 devmode->icmmethod = ntdevmode->icmmethod;
4138 devmode->icmintent = ntdevmode->icmintent;
4139 devmode->mediatype = ntdevmode->mediatype;
4140 devmode->dithertype = ntdevmode->dithertype;
4142 if (ntdevmode->private != NULL) {
4143 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4150 /****************************************************************************
4151 Create a DEVMODE struct. Returns malloced memory.
4152 ****************************************************************************/
4154 DEVICEMODE *construct_dev_mode(int snum)
4156 NT_PRINTER_INFO_LEVEL *printer = NULL;
4157 DEVICEMODE *devmode = NULL;
4159 DEBUG(7,("construct_dev_mode\n"));
4161 DEBUGADD(8,("getting printer characteristics\n"));
4163 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4166 if ( !printer->info_2->devmode ) {
4167 DEBUG(5, ("BONG! There was no device mode!\n"));
4171 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4172 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4176 ZERO_STRUCTP(devmode);
4178 DEBUGADD(8,("loading DEVICEMODE\n"));
4180 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4181 free_dev_mode( devmode );
4186 free_a_printer(&printer,2);
4191 /********************************************************************
4192 * construct_printer_info_2
4193 * fill a printer_info_2 struct
4194 ********************************************************************/
4196 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4199 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4201 print_status_struct status;
4203 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4206 count = print_queue_length(snum, &status);
4208 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4209 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4210 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4211 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4212 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4214 if (*ntprinter->info_2->comment == '\0')
4215 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4217 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4219 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4220 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4221 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4222 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4223 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4225 printer->attributes = ntprinter->info_2->attributes;
4227 printer->priority = ntprinter->info_2->priority; /* priority */
4228 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4229 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4230 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4231 printer->status = nt_printq_status(status.status); /* status */
4232 printer->cjobs = count; /* jobs */
4233 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4235 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4236 DEBUG(8, ("Returning NULL Devicemode!\n"));
4239 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4240 /* steal the printer info sec_desc structure. [badly done]. */
4241 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4242 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4243 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4244 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4247 printer->secdesc = NULL;
4250 free_a_printer(&ntprinter, 2);
4254 /********************************************************************
4255 * construct_printer_info_3
4256 * fill a printer_info_3 struct
4257 ********************************************************************/
4259 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4261 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4262 PRINTER_INFO_3 *printer = NULL;
4264 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4268 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4269 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4273 ZERO_STRUCTP(printer);
4275 printer->flags = 4; /* These are the components of the SD we are returning. */
4276 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4277 /* steal the printer info sec_desc structure. [badly done]. */
4278 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4282 * Set the flags for the components we are returning.
4285 if (printer->secdesc->owner_sid)
4286 printer->flags |= OWNER_SECURITY_INFORMATION;
4288 if (printer->secdesc->grp_sid)
4289 printer->flags |= GROUP_SECURITY_INFORMATION;
4291 if (printer->secdesc->dacl)
4292 printer->flags |= DACL_SECURITY_INFORMATION;
4294 if (printer->secdesc->sacl)
4295 printer->flags |= SACL_SECURITY_INFORMATION;
4298 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4299 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4300 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4303 free_a_printer(&ntprinter, 2);
4305 *pp_printer = printer;
4309 /********************************************************************
4310 * construct_printer_info_4
4311 * fill a printer_info_4 struct
4312 ********************************************************************/
4314 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4316 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4318 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4321 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4322 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4323 printer->attributes = ntprinter->info_2->attributes;
4325 free_a_printer(&ntprinter, 2);
4329 /********************************************************************
4330 * construct_printer_info_5
4331 * fill a printer_info_5 struct
4332 ********************************************************************/
4334 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4336 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4338 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4341 init_unistr(&printer->printername, ntprinter->info_2->printername);
4342 init_unistr(&printer->portname, ntprinter->info_2->portname);
4343 printer->attributes = ntprinter->info_2->attributes;
4345 /* these two are not used by NT+ according to MSDN */
4347 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4348 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4350 free_a_printer(&ntprinter, 2);
4355 /********************************************************************
4356 * construct_printer_info_7
4357 * fill a printer_info_7 struct
4358 ********************************************************************/
4360 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4362 char *guid_str = NULL;
4365 if (is_printer_published(print_hnd, snum, &guid)) {
4366 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4367 strupper_m(guid_str);
4368 init_unistr(&printer->guid, guid_str);
4369 printer->action = SPOOL_DS_PUBLISH;
4371 init_unistr(&printer->guid, "");
4372 printer->action = SPOOL_DS_UNPUBLISH;
4378 /********************************************************************
4379 Spoolss_enumprinters.
4380 ********************************************************************/
4382 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4386 int n_services=lp_numservices();
4387 PRINTER_INFO_1 *tp, *printers=NULL;
4388 PRINTER_INFO_1 current_prt;
4390 DEBUG(4,("enum_all_printers_info_1\n"));
4392 for (snum=0; snum<n_services; snum++) {
4393 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4394 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4396 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4397 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4398 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4399 SAFE_FREE(printers);
4404 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4406 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4412 /* check the required size. */
4413 for (i=0; i<*returned; i++)
4414 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4416 if (!alloc_buffer_size(buffer, *needed))
4417 return WERR_INSUFFICIENT_BUFFER;
4419 /* fill the buffer with the structures */
4420 for (i=0; i<*returned; i++)
4421 smb_io_printer_info_1("", buffer, &printers[i], 0);
4424 SAFE_FREE(printers);
4426 if (*needed > offered) {
4428 return WERR_INSUFFICIENT_BUFFER;
4434 /********************************************************************
4435 enum_all_printers_info_1_local.
4436 *********************************************************************/
4438 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4440 DEBUG(4,("enum_all_printers_info_1_local\n"));
4442 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4445 /********************************************************************
4446 enum_all_printers_info_1_name.
4447 *********************************************************************/
4449 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4453 DEBUG(4,("enum_all_printers_info_1_name\n"));
4455 if ((name[0] == '\\') && (name[1] == '\\'))
4458 if (is_myname_or_ipaddr(s)) {
4459 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4462 return WERR_INVALID_NAME;
4465 /********************************************************************
4466 enum_all_printers_info_1_remote.
4467 *********************************************************************/
4469 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4471 PRINTER_INFO_1 *printer;
4472 fstring printername;
4475 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4477 /* JFM: currently it's more a place holder than anything else.
4478 * In the spooler world there is a notion of server registration.
4479 * the print servers are registring (sp ?) on the PDC (in the same domain)
4481 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4484 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4489 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4490 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4491 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4493 init_unistr(&printer->description, desc);
4494 init_unistr(&printer->name, printername);
4495 init_unistr(&printer->comment, comment);
4496 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4498 /* check the required size. */
4499 *needed += spoolss_size_printer_info_1(printer);
4501 if (!alloc_buffer_size(buffer, *needed)) {
4503 return WERR_INSUFFICIENT_BUFFER;
4506 /* fill the buffer with the structures */
4507 smb_io_printer_info_1("", buffer, printer, 0);
4512 if (*needed > offered) {
4514 return WERR_INSUFFICIENT_BUFFER;
4520 /********************************************************************
4521 enum_all_printers_info_1_network.
4522 *********************************************************************/
4524 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4528 DEBUG(4,("enum_all_printers_info_1_network\n"));
4530 /* If we respond to a enum_printers level 1 on our name with flags
4531 set to PRINTER_ENUM_REMOTE with a list of printers then these
4532 printers incorrectly appear in the APW browse list.
4533 Specifically the printers for the server appear at the workgroup
4534 level where all the other servers in the domain are
4535 listed. Windows responds to this call with a
4536 WERR_CAN_NOT_COMPLETE so we should do the same. */
4538 if (name[0] == '\\' && name[1] == '\\')
4541 if (is_myname_or_ipaddr(s))
4542 return WERR_CAN_NOT_COMPLETE;
4544 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4547 /********************************************************************
4548 * api_spoolss_enumprinters
4550 * called from api_spoolss_enumprinters (see this to understand)
4551 ********************************************************************/
4553 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4557 int n_services=lp_numservices();
4558 PRINTER_INFO_2 *tp, *printers=NULL;
4559 PRINTER_INFO_2 current_prt;
4561 for (snum=0; snum<n_services; snum++) {
4562 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4563 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4565 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4566 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4567 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4568 SAFE_FREE(printers);
4573 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4574 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4580 /* check the required size. */
4581 for (i=0; i<*returned; i++)
4582 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4584 if (!alloc_buffer_size(buffer, *needed)) {
4585 for (i=0; i<*returned; i++) {
4586 free_devmode(printers[i].devmode);
4588 SAFE_FREE(printers);
4589 return WERR_INSUFFICIENT_BUFFER;
4592 /* fill the buffer with the structures */
4593 for (i=0; i<*returned; i++)
4594 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4597 for (i=0; i<*returned; i++) {
4598 free_devmode(printers[i].devmode);
4600 SAFE_FREE(printers);
4602 if (*needed > offered) {
4604 return WERR_INSUFFICIENT_BUFFER;
4610 /********************************************************************
4611 * handle enumeration of printers at level 1
4612 ********************************************************************/
4614 static WERROR enumprinters_level1( uint32 flags, fstring name,
4615 NEW_BUFFER *buffer, uint32 offered,
4616 uint32 *needed, uint32 *returned)
4618 /* Not all the flags are equals */
4620 if (flags & PRINTER_ENUM_LOCAL)
4621 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4623 if (flags & PRINTER_ENUM_NAME)
4624 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4626 if (flags & PRINTER_ENUM_REMOTE)
4627 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4629 if (flags & PRINTER_ENUM_NETWORK)
4630 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4632 return WERR_OK; /* NT4sp5 does that */
4635 /********************************************************************
4636 * handle enumeration of printers at level 2
4637 ********************************************************************/
4639 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4640 NEW_BUFFER *buffer, uint32 offered,
4641 uint32 *needed, uint32 *returned)
4643 char *s = servername;
4645 if (flags & PRINTER_ENUM_LOCAL) {
4646 return enum_all_printers_info_2(buffer, offered, needed, returned);
4649 if (flags & PRINTER_ENUM_NAME) {
4650 if ((servername[0] == '\\') && (servername[1] == '\\'))
4652 if (is_myname_or_ipaddr(s))
4653 return enum_all_printers_info_2(buffer, offered, needed, returned);
4655 return WERR_INVALID_NAME;
4658 if (flags & PRINTER_ENUM_REMOTE)
4659 return WERR_UNKNOWN_LEVEL;
4664 /********************************************************************
4665 * handle enumeration of printers at level 5
4666 ********************************************************************/
4668 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4669 NEW_BUFFER *buffer, uint32 offered,
4670 uint32 *needed, uint32 *returned)
4672 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4676 /********************************************************************
4677 * api_spoolss_enumprinters
4679 * called from api_spoolss_enumprinters (see this to understand)
4680 ********************************************************************/
4682 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4684 uint32 flags = q_u->flags;
4685 UNISTR2 *servername = &q_u->servername;
4686 uint32 level = q_u->level;
4687 NEW_BUFFER *buffer = NULL;
4688 uint32 offered = q_u->offered;
4689 uint32 *needed = &r_u->needed;
4690 uint32 *returned = &r_u->returned;
4694 /* that's an [in out] buffer */
4695 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4696 buffer = r_u->buffer;
4698 DEBUG(4,("_spoolss_enumprinters\n"));
4705 * flags==PRINTER_ENUM_NAME
4706 * if name=="" then enumerates all printers
4707 * if name!="" then enumerate the printer
4708 * flags==PRINTER_ENUM_REMOTE
4709 * name is NULL, enumerate printers
4710 * Level 2: name!="" enumerates printers, name can't be NULL
4711 * Level 3: doesn't exist
4712 * Level 4: does a local registry lookup
4713 * Level 5: same as Level 2
4716 unistr2_to_ascii(name, servername, sizeof(name)-1);
4721 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4723 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4725 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4730 return WERR_UNKNOWN_LEVEL;
4733 /****************************************************************************
4734 ****************************************************************************/
4736 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4738 PRINTER_INFO_0 *printer=NULL;
4740 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4743 construct_printer_info_0(print_hnd, printer, snum);
4745 /* check the required size. */
4746 *needed += spoolss_size_printer_info_0(printer);
4748 if (!alloc_buffer_size(buffer, *needed)) {
4750 return WERR_INSUFFICIENT_BUFFER;
4753 /* fill the buffer with the structures */
4754 smb_io_printer_info_0("", buffer, printer, 0);
4759 if (*needed > offered) {
4760 return WERR_INSUFFICIENT_BUFFER;
4766 /****************************************************************************
4767 ****************************************************************************/
4769 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4771 PRINTER_INFO_1 *printer=NULL;
4773 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4776 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4778 /* check the required size. */
4779 *needed += spoolss_size_printer_info_1(printer);
4781 if (!alloc_buffer_size(buffer, *needed)) {
4783 return WERR_INSUFFICIENT_BUFFER;
4786 /* fill the buffer with the structures */
4787 smb_io_printer_info_1("", buffer, printer, 0);
4792 if (*needed > offered) {
4793 return WERR_INSUFFICIENT_BUFFER;
4799 /****************************************************************************
4800 ****************************************************************************/
4802 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4804 PRINTER_INFO_2 *printer=NULL;
4806 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4809 construct_printer_info_2(print_hnd, printer, snum);
4811 /* check the required size. */
4812 *needed += spoolss_size_printer_info_2(printer);
4814 if (!alloc_buffer_size(buffer, *needed)) {
4815 free_printer_info_2(printer);
4816 return WERR_INSUFFICIENT_BUFFER;
4819 /* fill the buffer with the structures */
4820 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4821 free_printer_info_2(printer);
4826 free_printer_info_2(printer);
4828 if (*needed > offered) {
4829 return WERR_INSUFFICIENT_BUFFER;
4835 /****************************************************************************
4836 ****************************************************************************/
4838 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4840 PRINTER_INFO_3 *printer=NULL;
4842 if (!construct_printer_info_3(print_hnd, &printer, snum))
4845 /* check the required size. */
4846 *needed += spoolss_size_printer_info_3(printer);
4848 if (!alloc_buffer_size(buffer, *needed)) {
4849 free_printer_info_3(printer);
4850 return WERR_INSUFFICIENT_BUFFER;
4853 /* fill the buffer with the structures */
4854 smb_io_printer_info_3("", buffer, printer, 0);
4857 free_printer_info_3(printer);
4859 if (*needed > offered) {
4860 return WERR_INSUFFICIENT_BUFFER;
4866 /****************************************************************************
4867 ****************************************************************************/
4869 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4871 PRINTER_INFO_4 *printer=NULL;
4873 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4876 if (!construct_printer_info_4(print_hnd, printer, snum))
4879 /* check the required size. */
4880 *needed += spoolss_size_printer_info_4(printer);
4882 if (!alloc_buffer_size(buffer, *needed)) {
4883 free_printer_info_4(printer);
4884 return WERR_INSUFFICIENT_BUFFER;
4887 /* fill the buffer with the structures */
4888 smb_io_printer_info_4("", buffer, printer, 0);
4891 free_printer_info_4(printer);
4893 if (*needed > offered) {
4894 return WERR_INSUFFICIENT_BUFFER;
4900 /****************************************************************************
4901 ****************************************************************************/
4903 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4905 PRINTER_INFO_5 *printer=NULL;
4907 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4910 if (!construct_printer_info_5(print_hnd, printer, snum))
4913 /* check the required size. */
4914 *needed += spoolss_size_printer_info_5(printer);
4916 if (!alloc_buffer_size(buffer, *needed)) {
4917 free_printer_info_5(printer);
4918 return WERR_INSUFFICIENT_BUFFER;
4921 /* fill the buffer with the structures */
4922 smb_io_printer_info_5("", buffer, printer, 0);
4925 free_printer_info_5(printer);
4927 if (*needed > offered) {
4928 return WERR_INSUFFICIENT_BUFFER;
4934 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4936 PRINTER_INFO_7 *printer=NULL;
4938 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4941 if (!construct_printer_info_7(print_hnd, printer, snum))
4944 /* check the required size. */
4945 *needed += spoolss_size_printer_info_7(printer);
4947 if (!alloc_buffer_size(buffer, *needed)) {
4948 free_printer_info_7(printer);
4949 return WERR_INSUFFICIENT_BUFFER;
4952 /* fill the buffer with the structures */
4953 smb_io_printer_info_7("", buffer, printer, 0);
4956 free_printer_info_7(printer);
4958 if (*needed > offered) {
4959 return WERR_INSUFFICIENT_BUFFER;
4965 /****************************************************************************
4966 ****************************************************************************/
4968 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4970 POLICY_HND *handle = &q_u->handle;
4971 uint32 level = q_u->level;
4972 NEW_BUFFER *buffer = NULL;
4973 uint32 offered = q_u->offered;
4974 uint32 *needed = &r_u->needed;
4975 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4979 /* that's an [in out] buffer */
4980 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4981 buffer = r_u->buffer;
4985 if (!get_printer_snum(p, handle, &snum))
4990 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4992 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4994 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4996 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4998 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5000 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5002 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5004 return WERR_UNKNOWN_LEVEL;
5007 /********************************************************************
5008 * fill a DRIVER_INFO_1 struct
5009 ********************************************************************/
5011 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5013 init_unistr( &info->name, driver.info_3->name);
5016 /********************************************************************
5017 * construct_printer_driver_info_1
5018 ********************************************************************/
5020 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5022 NT_PRINTER_INFO_LEVEL *printer = NULL;
5023 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5025 ZERO_STRUCT(driver);
5027 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5028 return WERR_INVALID_PRINTER_NAME;
5030 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5031 return WERR_UNKNOWN_PRINTER_DRIVER;
5033 fill_printer_driver_info_1(info, driver, servername, architecture);
5035 free_a_printer(&printer,2);
5040 /********************************************************************
5041 * construct_printer_driver_info_2
5042 * fill a printer_info_2 struct
5043 ********************************************************************/
5045 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5049 info->version=driver.info_3->cversion;
5051 init_unistr( &info->name, driver.info_3->name );
5052 init_unistr( &info->architecture, driver.info_3->environment );
5055 if (strlen(driver.info_3->driverpath)) {
5056 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5057 init_unistr( &info->driverpath, temp );
5059 init_unistr( &info->driverpath, "" );
5061 if (strlen(driver.info_3->datafile)) {
5062 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5063 init_unistr( &info->datafile, temp );
5065 init_unistr( &info->datafile, "" );
5067 if (strlen(driver.info_3->configfile)) {
5068 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5069 init_unistr( &info->configfile, temp );
5071 init_unistr( &info->configfile, "" );
5074 /********************************************************************
5075 * construct_printer_driver_info_2
5076 * fill a printer_info_2 struct
5077 ********************************************************************/
5079 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5081 NT_PRINTER_INFO_LEVEL *printer = NULL;
5082 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5084 ZERO_STRUCT(printer);
5085 ZERO_STRUCT(driver);
5087 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5088 return WERR_INVALID_PRINTER_NAME;
5090 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5091 return WERR_UNKNOWN_PRINTER_DRIVER;
5093 fill_printer_driver_info_2(info, driver, servername);
5095 free_a_printer(&printer,2);
5100 /********************************************************************
5101 * copy a strings array and convert to UNICODE
5103 * convert an array of ascii string to a UNICODE string
5104 ********************************************************************/
5106 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5114 DEBUG(6,("init_unistr_array\n"));
5125 v = ""; /* hack to handle null lists */
5128 /* hack to allow this to be used in places other than when generating
5129 the list of dependent files */
5132 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5136 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5138 /* add one extra unit16 for the second terminating NULL */
5140 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5141 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5149 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5154 /* special case for ""; we need to add both NULL's here */
5156 (*uni_array)[j++]=0x0000;
5157 (*uni_array)[j]=0x0000;
5160 DEBUGADD(6,("last one:done\n"));
5162 /* return size of array in uint16's */
5167 /********************************************************************
5168 * construct_printer_info_3
5169 * fill a printer_info_3 struct
5170 ********************************************************************/
5172 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5178 info->version=driver.info_3->cversion;
5180 init_unistr( &info->name, driver.info_3->name );
5181 init_unistr( &info->architecture, driver.info_3->environment );
5183 if (strlen(driver.info_3->driverpath)) {
5184 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5185 init_unistr( &info->driverpath, temp );
5187 init_unistr( &info->driverpath, "" );
5189 if (strlen(driver.info_3->datafile)) {
5190 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5191 init_unistr( &info->datafile, temp );
5193 init_unistr( &info->datafile, "" );
5195 if (strlen(driver.info_3->configfile)) {
5196 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5197 init_unistr( &info->configfile, temp );
5199 init_unistr( &info->configfile, "" );
5201 if (strlen(driver.info_3->helpfile)) {
5202 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5203 init_unistr( &info->helpfile, temp );
5205 init_unistr( &info->helpfile, "" );
5207 init_unistr( &info->monitorname, driver.info_3->monitorname );
5208 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5210 info->dependentfiles=NULL;
5211 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5214 /********************************************************************
5215 * construct_printer_info_3
5216 * fill a printer_info_3 struct
5217 ********************************************************************/
5219 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5221 NT_PRINTER_INFO_LEVEL *printer = NULL;
5222 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5224 ZERO_STRUCT(driver);
5226 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5227 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5228 if (!W_ERROR_IS_OK(status))
5229 return WERR_INVALID_PRINTER_NAME;
5231 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5232 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5237 * I put this code in during testing. Helpful when commenting out the
5238 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5239 * as win2k always queries the driver using an infor level of 6.
5240 * I've left it in (but ifdef'd out) because I'll probably
5241 * use it in experimentation again in the future. --jerry 22/01/2002
5244 if (!W_ERROR_IS_OK(status)) {
5246 * Is this a W2k client ?
5249 /* Yes - try again with a WinNT driver. */
5251 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5252 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5256 if (!W_ERROR_IS_OK(status)) {
5257 free_a_printer(&printer,2);
5258 return WERR_UNKNOWN_PRINTER_DRIVER;
5266 fill_printer_driver_info_3(info, driver, servername);
5268 free_a_printer(&printer,2);
5273 /********************************************************************
5274 * construct_printer_info_6
5275 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5276 ********************************************************************/
5278 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5284 memset(&nullstr, '\0', sizeof(fstring));
5286 info->version=driver.info_3->cversion;
5288 init_unistr( &info->name, driver.info_3->name );
5289 init_unistr( &info->architecture, driver.info_3->environment );
5291 if (strlen(driver.info_3->driverpath)) {
5292 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5293 init_unistr( &info->driverpath, temp );
5295 init_unistr( &info->driverpath, "" );
5297 if (strlen(driver.info_3->datafile)) {
5298 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5299 init_unistr( &info->datafile, temp );
5301 init_unistr( &info->datafile, "" );
5303 if (strlen(driver.info_3->configfile)) {
5304 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5305 init_unistr( &info->configfile, temp );
5307 init_unistr( &info->configfile, "" );
5309 if (strlen(driver.info_3->helpfile)) {
5310 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5311 init_unistr( &info->helpfile, temp );
5313 init_unistr( &info->helpfile, "" );
5315 init_unistr( &info->monitorname, driver.info_3->monitorname );
5316 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5318 info->dependentfiles = NULL;
5319 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5321 info->previousdrivernames=NULL;
5322 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5324 info->driver_date.low=0;
5325 info->driver_date.high=0;
5328 info->driver_version_low=0;
5329 info->driver_version_high=0;
5331 init_unistr( &info->mfgname, "");
5332 init_unistr( &info->oem_url, "");
5333 init_unistr( &info->hardware_id, "");
5334 init_unistr( &info->provider, "");
5337 /********************************************************************
5338 * construct_printer_info_6
5339 * fill a printer_info_6 struct
5340 ********************************************************************/
5342 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5343 fstring servername, fstring architecture, uint32 version)
5345 NT_PRINTER_INFO_LEVEL *printer = NULL;
5346 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5349 ZERO_STRUCT(driver);
5351 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5353 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5355 if (!W_ERROR_IS_OK(status))
5356 return WERR_INVALID_PRINTER_NAME;
5358 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5360 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5362 if (!W_ERROR_IS_OK(status))
5365 * Is this a W2k client ?
5369 free_a_printer(&printer,2);
5370 return WERR_UNKNOWN_PRINTER_DRIVER;
5373 /* Yes - try again with a WinNT driver. */
5375 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5376 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5377 if (!W_ERROR_IS_OK(status)) {
5378 free_a_printer(&printer,2);
5379 return WERR_UNKNOWN_PRINTER_DRIVER;
5383 fill_printer_driver_info_6(info, driver, servername);
5385 free_a_printer(&printer,2);
5386 free_a_printer_driver(driver, 3);
5391 /****************************************************************************
5392 ****************************************************************************/
5394 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5396 SAFE_FREE(info->dependentfiles);
5399 /****************************************************************************
5400 ****************************************************************************/
5402 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5404 SAFE_FREE(info->dependentfiles);
5408 /****************************************************************************
5409 ****************************************************************************/
5411 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5413 DRIVER_INFO_1 *info=NULL;
5416 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5419 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5420 if (!W_ERROR_IS_OK(status)) {
5425 /* check the required size. */
5426 *needed += spoolss_size_printer_driver_info_1(info);
5428 if (!alloc_buffer_size(buffer, *needed)) {
5430 return WERR_INSUFFICIENT_BUFFER;
5433 /* fill the buffer with the structures */
5434 smb_io_printer_driver_info_1("", buffer, info, 0);
5439 if (*needed > offered)
5440 return WERR_INSUFFICIENT_BUFFER;
5445 /****************************************************************************
5446 ****************************************************************************/
5448 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5450 DRIVER_INFO_2 *info=NULL;
5453 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5456 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5457 if (!W_ERROR_IS_OK(status)) {
5462 /* check the required size. */
5463 *needed += spoolss_size_printer_driver_info_2(info);
5465 if (!alloc_buffer_size(buffer, *needed)) {
5467 return WERR_INSUFFICIENT_BUFFER;
5470 /* fill the buffer with the structures */
5471 smb_io_printer_driver_info_2("", buffer, info, 0);
5476 if (*needed > offered)
5477 return WERR_INSUFFICIENT_BUFFER;
5482 /****************************************************************************
5483 ****************************************************************************/
5485 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5492 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5493 if (!W_ERROR_IS_OK(status)) {
5497 /* check the required size. */
5498 *needed += spoolss_size_printer_driver_info_3(&info);
5500 if (!alloc_buffer_size(buffer, *needed)) {
5501 free_printer_driver_info_3(&info);
5502 return WERR_INSUFFICIENT_BUFFER;
5505 /* fill the buffer with the structures */
5506 smb_io_printer_driver_info_3("", buffer, &info, 0);
5508 free_printer_driver_info_3(&info);
5510 if (*needed > offered)
5511 return WERR_INSUFFICIENT_BUFFER;
5516 /****************************************************************************
5517 ****************************************************************************/
5519 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5526 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5527 if (!W_ERROR_IS_OK(status)) {
5531 /* check the required size. */
5532 *needed += spoolss_size_printer_driver_info_6(&info);
5534 if (!alloc_buffer_size(buffer, *needed)) {
5535 free_printer_driver_info_6(&info);
5536 return WERR_INSUFFICIENT_BUFFER;
5539 /* fill the buffer with the structures */
5540 smb_io_printer_driver_info_6("", buffer, &info, 0);
5542 free_printer_driver_info_6(&info);
5544 if (*needed > offered)
5545 return WERR_INSUFFICIENT_BUFFER;
5550 /****************************************************************************
5551 ****************************************************************************/
5553 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5555 POLICY_HND *handle = &q_u->handle;
5556 UNISTR2 *uni_arch = &q_u->architecture;
5557 uint32 level = q_u->level;
5558 uint32 clientmajorversion = q_u->clientmajorversion;
5559 NEW_BUFFER *buffer = NULL;
5560 uint32 offered = q_u->offered;
5561 uint32 *needed = &r_u->needed;
5562 uint32 *servermajorversion = &r_u->servermajorversion;
5563 uint32 *serverminorversion = &r_u->serverminorversion;
5566 fstring architecture;
5569 /* that's an [in out] buffer */
5570 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5571 buffer = r_u->buffer;
5573 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5576 *servermajorversion = 0;
5577 *serverminorversion = 0;
5579 fstrcpy(servername, get_called_name());
5580 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5582 if (!get_printer_snum(p, handle, &snum))
5587 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5589 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5591 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5593 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5596 return WERR_UNKNOWN_LEVEL;
5599 /****************************************************************************
5600 ****************************************************************************/
5602 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5604 POLICY_HND *handle = &q_u->handle;
5606 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5609 DEBUG(3,("Error in startpageprinter printer handle\n"));
5613 Printer->page_started=True;
5617 /****************************************************************************
5618 ****************************************************************************/
5620 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5622 POLICY_HND *handle = &q_u->handle;
5625 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5628 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5632 if (!get_printer_snum(p, handle, &snum))
5635 Printer->page_started=False;
5636 print_job_endpage(snum, Printer->jobid);
5641 /********************************************************************
5642 * api_spoolss_getprinter
5643 * called from the spoolss dispatcher
5645 ********************************************************************/
5647 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5649 POLICY_HND *handle = &q_u->handle;
5650 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5651 uint32 *jobid = &r_u->jobid;
5653 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5657 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5658 struct current_user user;
5661 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5665 get_current_user(&user, p);
5668 * a nice thing with NT is it doesn't listen to what you tell it.
5669 * when asked to send _only_ RAW datas, it tries to send datas
5672 * So I add checks like in NT Server ...
5675 if (info_1->p_datatype != 0) {
5676 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5677 if (strcmp(datatype, "RAW") != 0) {
5679 return WERR_INVALID_DATATYPE;
5683 /* get the share number of the printer */
5684 if (!get_printer_snum(p, handle, &snum)) {
5688 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5690 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5692 /* An error occured in print_job_start() so return an appropriate
5695 if (Printer->jobid == -1) {
5696 return map_werror_from_unix(errno);
5699 Printer->document_started=True;
5700 (*jobid) = Printer->jobid;
5705 /********************************************************************
5706 * api_spoolss_getprinter
5707 * called from the spoolss dispatcher
5709 ********************************************************************/
5711 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5713 POLICY_HND *handle = &q_u->handle;
5715 return _spoolss_enddocprinter_internal(p, handle);
5718 /****************************************************************************
5719 ****************************************************************************/
5721 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5723 POLICY_HND *handle = &q_u->handle;
5724 uint32 buffer_size = q_u->buffer_size;
5725 uint8 *buffer = q_u->buffer;
5726 uint32 *buffer_written = &q_u->buffer_size2;
5728 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5731 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5732 r_u->buffer_written = q_u->buffer_size2;
5736 if (!get_printer_snum(p, handle, &snum))
5739 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5740 if (*buffer_written == -1) {
5741 r_u->buffer_written = 0;
5742 if (errno == ENOSPC)
5743 return WERR_NO_SPOOL_SPACE;
5745 return WERR_ACCESS_DENIED;
5748 r_u->buffer_written = q_u->buffer_size2;
5753 /********************************************************************
5754 * api_spoolss_getprinter
5755 * called from the spoolss dispatcher
5757 ********************************************************************/
5759 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5762 struct current_user user;
5764 WERROR errcode = WERR_BADFUNC;
5765 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5767 get_current_user(&user, p);
5770 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5774 if (!get_printer_snum(p, handle, &snum))
5778 case PRINTER_CONTROL_PAUSE:
5779 if (print_queue_pause(&user, snum, &errcode)) {
5783 case PRINTER_CONTROL_RESUME:
5784 case PRINTER_CONTROL_UNPAUSE:
5785 if (print_queue_resume(&user, snum, &errcode)) {
5789 case PRINTER_CONTROL_PURGE:
5790 if (print_queue_purge(&user, snum, &errcode)) {
5795 return WERR_UNKNOWN_LEVEL;
5801 /********************************************************************
5802 * api_spoolss_abortprinter
5803 * From MSDN: "Deletes printer's spool file if printer is configured
5805 ********************************************************************/
5807 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5809 POLICY_HND *handle = &q_u->handle;
5810 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5812 struct current_user user;
5813 WERROR errcode = WERR_OK;
5816 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5820 if (!get_printer_snum(p, handle, &snum))
5823 get_current_user( &user, p );
5825 print_job_delete( &user, snum, Printer->jobid, &errcode );
5830 /********************************************************************
5831 * called by spoolss_api_setprinter
5832 * when updating a printer description
5833 ********************************************************************/
5835 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5836 const SPOOL_PRINTER_INFO_LEVEL *info,
5837 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5839 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5840 struct current_user user;
5844 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5846 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5847 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5848 OUR_HANDLE(handle)));
5850 result = WERR_BADFID;
5854 /* NT seems to like setting the security descriptor even though
5855 nothing may have actually changed. This causes annoying
5856 dialog boxes when the user doesn't have permission to change
5857 the security descriptor. */
5859 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5861 if (DEBUGLEVEL >= 10) {
5865 the_acl = old_secdesc_ctr->sec->dacl;
5866 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5867 PRINTERNAME(snum), the_acl->num_aces));
5869 for (i = 0; i < the_acl->num_aces; i++) {
5872 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5874 DEBUG(10, ("%s 0x%08x\n", sid_str,
5875 the_acl->ace[i].info.mask));
5878 the_acl = secdesc_ctr->sec->dacl;
5881 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5882 PRINTERNAME(snum), the_acl->num_aces));
5884 for (i = 0; i < the_acl->num_aces; i++) {
5887 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5889 DEBUG(10, ("%s 0x%08x\n", sid_str,
5890 the_acl->ace[i].info.mask));
5893 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5897 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5899 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5904 /* Work out which user is performing the operation */
5906 get_current_user(&user, p);
5908 /* Check the user has permissions to change the security
5909 descriptor. By experimentation with two NT machines, the user
5910 requires Full Access to the printer to change security
5913 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5914 result = WERR_ACCESS_DENIED;
5918 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5925 /********************************************************************
5926 Do Samba sanity checks on a printer info struct.
5927 this has changed purpose: it now "canonicalises" printer
5928 info from a client rather than just checking it is correct
5929 ********************************************************************/
5931 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5933 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5934 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5936 /* we force some elements to "correct" values */
5937 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5938 fstrcpy(info->sharename, lp_servicename(snum));
5939 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5940 get_called_name(), info->sharename);
5941 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5947 /****************************************************************************
5948 ****************************************************************************/
5950 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5952 extern userdom_struct current_user_info;
5953 char *cmd = lp_addprinter_cmd();
5959 fstring remote_machine = "%m";
5961 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5963 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5964 cmd, printer->info_2->printername, printer->info_2->sharename,
5965 printer->info_2->portname, printer->info_2->drivername,
5966 printer->info_2->location, printer->info_2->comment, remote_machine);
5968 DEBUG(10,("Running [%s]\n", command));
5969 ret = smbrun(command, &fd);
5970 DEBUGADD(10,("returned [%d]\n", ret));
5979 /* Get lines and convert them back to dos-codepage */
5980 qlines = fd_lines_load(fd, &numlines);
5981 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5985 /* Set the portname to what the script says the portname should be. */
5986 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5987 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5989 /* Send SIGHUP to process group... is there a better way? */
5992 /* reload our services immediately */
5993 reload_services( False );
5996 file_lines_free(qlines);
6000 /********************************************************************
6001 * Called by spoolss_api_setprinter
6002 * when updating a printer description.
6003 ********************************************************************/
6005 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6006 const SPOOL_PRINTER_INFO_LEVEL *info,
6007 DEVICEMODE *devmode)
6010 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6011 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6016 DEBUG(8,("update_printer\n"));
6021 result = WERR_BADFID;
6025 if (!get_printer_snum(p, handle, &snum)) {
6026 result = WERR_BADFID;
6030 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6031 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6032 result = WERR_BADFID;
6036 DEBUGADD(8,("Converting info_2 struct\n"));
6039 * convert_printer_info converts the incoming
6040 * info from the client and overwrites the info
6041 * just read from the tdb in the pointer 'printer'.
6044 if (!convert_printer_info(info, printer, level)) {
6045 result = WERR_NOMEM;
6050 /* we have a valid devmode
6051 convert it and link it*/
6053 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6054 if (!convert_devicemode(printer->info_2->printername, devmode,
6055 &printer->info_2->devmode)) {
6056 result = WERR_NOMEM;
6061 /* Do sanity check on the requested changes for Samba */
6063 if (!check_printer_ok(printer->info_2, snum)) {
6064 result = WERR_INVALID_PARAM;
6068 /* FIXME!!! If the driver has changed we really should verify that
6069 it is installed before doing much else --jerry */
6071 /* Check calling user has permission to update printer description */
6073 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6074 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6075 result = WERR_ACCESS_DENIED;
6079 /* Call addprinter hook */
6080 /* Check changes to see if this is really needed */
6082 if ( *lp_addprinter_cmd()
6083 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6084 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6085 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6086 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6088 if ( !add_printer_hook(printer) ) {
6089 result = WERR_ACCESS_DENIED;
6094 * make sure we actually reload the services after
6095 * this as smb.conf could have a new section in it
6096 * .... shouldn't .... but could
6098 reload_services(False);
6102 * When a *new* driver is bound to a printer, the drivername is used to
6103 * lookup previously saved driver initialization info, which is then
6104 * bound to the printer, simulating what happens in the Windows arch.
6106 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6108 if (!set_driver_init(printer, 2))
6110 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6111 printer->info_2->drivername));
6114 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6115 printer->info_2->drivername));
6117 notify_printer_driver(snum, printer->info_2->drivername);
6121 * flag which changes actually occured. This is a small subset of
6122 * all the possible changes. We also have to update things in the
6126 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6127 init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 );
6128 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6129 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6131 notify_printer_comment(snum, printer->info_2->comment);
6134 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6135 init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 );
6136 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6137 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6138 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6139 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6141 notify_printer_sharename(snum, printer->info_2->sharename);
6144 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6145 init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 );
6146 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6147 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6149 notify_printer_port(snum, printer->info_2->portname);
6152 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6153 init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 );
6154 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6155 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6157 notify_printer_location(snum, printer->info_2->location);
6160 /* here we need to update some more DsSpooler keys */
6161 /* uNCName, serverName, shortServerName */
6163 init_unistr2( &buffer, global_myname(), strlen(global_myname())+1 );
6164 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6165 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6166 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6167 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6169 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6170 global_myname(), printer->info_2->sharename );
6171 init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 );
6172 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6173 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6175 /* Update printer info */
6176 result = mod_a_printer(*printer, 2);
6179 free_a_printer(&printer, 2);
6180 free_a_printer(&old_printer, 2);
6186 /****************************************************************************
6187 ****************************************************************************/
6188 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6189 const SPOOL_PRINTER_INFO_LEVEL *info)
6192 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6194 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6197 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6204 if (!get_printer_snum(p, handle, &snum))
6207 nt_printer_publish(Printer, snum, info7->action);
6211 return WERR_UNKNOWN_LEVEL;
6214 /****************************************************************************
6215 ****************************************************************************/
6217 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6219 POLICY_HND *handle = &q_u->handle;
6220 uint32 level = q_u->level;
6221 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6222 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6223 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6224 uint32 command = q_u->command;
6226 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6229 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6233 /* check the level */
6236 return control_printer(handle, command, p);
6238 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6240 return update_printer_sec(handle, level, info, p,
6243 return publish_or_unpublish_printer(p, handle, info);
6245 return WERR_UNKNOWN_LEVEL;
6249 /****************************************************************************
6250 ****************************************************************************/
6252 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6254 POLICY_HND *handle = &q_u->handle;
6255 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6258 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6262 if (Printer->notify.client_connected==True) {
6265 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6267 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6268 !get_printer_snum(p, handle, &snum) )
6271 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6274 Printer->notify.flags=0;
6275 Printer->notify.options=0;
6276 Printer->notify.localmachine[0]='\0';
6277 Printer->notify.printerlocal=0;
6278 if (Printer->notify.option)
6279 free_spool_notify_option(&Printer->notify.option);
6280 Printer->notify.client_connected=False;
6285 /****************************************************************************
6286 ****************************************************************************/
6288 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6290 /* that's an [in out] buffer (despite appearences to the contrary) */
6291 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6294 return WERR_INVALID_PARAM; /* this is what a NT server
6295 returns for AddJob. AddJob
6296 must fail on non-local
6300 /****************************************************************************
6301 ****************************************************************************/
6303 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6304 int position, int snum)
6310 t=gmtime(&queue->time);
6311 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6313 job_info->jobid=queue->job;
6314 init_unistr(&job_info->printername, lp_servicename(snum));
6315 init_unistr(&job_info->machinename, temp_name);
6316 init_unistr(&job_info->username, queue->fs_user);
6317 init_unistr(&job_info->document, queue->fs_file);
6318 init_unistr(&job_info->datatype, "RAW");
6319 init_unistr(&job_info->text_status, "");
6320 job_info->status=nt_printj_status(queue->status);
6321 job_info->priority=queue->priority;
6322 job_info->position=position;
6323 job_info->totalpages=queue->page_count;
6324 job_info->pagesprinted=0;
6326 make_systemtime(&job_info->submitted, t);
6329 /****************************************************************************
6330 ****************************************************************************/
6332 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6333 int position, int snum,
6334 NT_PRINTER_INFO_LEVEL *ntprinter,
6335 DEVICEMODE *devmode)
6340 t=gmtime(&queue->time);
6341 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6343 job_info->jobid=queue->job;
6345 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6347 init_unistr(&job_info->machinename, temp_name);
6348 init_unistr(&job_info->username, queue->fs_user);
6349 init_unistr(&job_info->document, queue->fs_file);
6350 init_unistr(&job_info->notifyname, queue->fs_user);
6351 init_unistr(&job_info->datatype, "RAW");
6352 init_unistr(&job_info->printprocessor, "winprint");
6353 init_unistr(&job_info->parameters, "");
6354 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6355 init_unistr(&job_info->text_status, "");
6357 /* and here the security descriptor */
6359 job_info->status=nt_printj_status(queue->status);
6360 job_info->priority=queue->priority;
6361 job_info->position=position;
6362 job_info->starttime=0;
6363 job_info->untiltime=0;
6364 job_info->totalpages=queue->page_count;
6365 job_info->size=queue->size;
6366 make_systemtime(&(job_info->submitted), t);
6367 job_info->timeelapsed=0;
6368 job_info->pagesprinted=0;
6370 job_info->devmode = devmode;
6375 /****************************************************************************
6376 Enumjobs at level 1.
6377 ****************************************************************************/
6379 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6380 NEW_BUFFER *buffer, uint32 offered,
6381 uint32 *needed, uint32 *returned)
6386 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6393 for (i=0; i<*returned; i++)
6394 fill_job_info_1(&info[i], &queue[i], i, snum);
6398 /* check the required size. */
6399 for (i=0; i<*returned; i++)
6400 (*needed) += spoolss_size_job_info_1(&info[i]);
6402 if (!alloc_buffer_size(buffer, *needed)) {
6404 return WERR_INSUFFICIENT_BUFFER;
6407 /* fill the buffer with the structures */
6408 for (i=0; i<*returned; i++)
6409 smb_io_job_info_1("", buffer, &info[i], 0);
6414 if (*needed > offered) {
6416 return WERR_INSUFFICIENT_BUFFER;
6422 /****************************************************************************
6423 Enumjobs at level 2.
6424 ****************************************************************************/
6426 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6427 NEW_BUFFER *buffer, uint32 offered,
6428 uint32 *needed, uint32 *returned)
6430 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6431 JOB_INFO_2 *info = NULL;
6434 DEVICEMODE *devmode = NULL;
6436 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6439 result = WERR_NOMEM;
6443 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6444 if (!W_ERROR_IS_OK(result)) {
6449 /* this should not be a failure condition if the devmode is NULL */
6451 devmode = construct_dev_mode(snum);
6453 for (i=0; i<*returned; i++)
6454 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6457 free_a_printer(&ntprinter, 2);
6460 /* check the required size. */
6461 for (i=0; i<*returned; i++)
6462 (*needed) += spoolss_size_job_info_2(&info[i]);
6464 if (*needed > offered) {
6466 result = WERR_INSUFFICIENT_BUFFER;
6470 if (!alloc_buffer_size(buffer, *needed)) {
6472 result = WERR_INSUFFICIENT_BUFFER;
6476 /* fill the buffer with the structures */
6477 for (i=0; i<*returned; i++)
6478 smb_io_job_info_2("", buffer, &info[i], 0);
6483 free_a_printer(&ntprinter, 2);
6484 free_devmode(devmode);
6492 /****************************************************************************
6494 ****************************************************************************/
6496 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6498 POLICY_HND *handle = &q_u->handle;
6499 uint32 level = q_u->level;
6500 NEW_BUFFER *buffer = NULL;
6501 uint32 offered = q_u->offered;
6502 uint32 *needed = &r_u->needed;
6503 uint32 *returned = &r_u->returned;
6507 print_status_struct prt_status;
6508 print_queue_struct *queue=NULL;
6510 /* that's an [in out] buffer */
6511 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6512 buffer = r_u->buffer;
6514 DEBUG(4,("_spoolss_enumjobs\n"));
6519 if (!get_printer_snum(p, handle, &snum))
6522 *returned = print_queue_status(snum, &queue, &prt_status);
6523 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6525 if (*returned == 0) {
6526 set_enumjobs_timestamp(snum);
6533 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6534 set_enumjobs_timestamp(snum);
6537 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6538 set_enumjobs_timestamp(snum);
6543 return WERR_UNKNOWN_LEVEL;
6547 /****************************************************************************
6548 ****************************************************************************/
6550 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6555 /****************************************************************************
6556 ****************************************************************************/
6558 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6560 POLICY_HND *handle = &q_u->handle;
6561 uint32 jobid = q_u->jobid;
6562 uint32 command = q_u->command;
6564 struct current_user user;
6566 WERROR errcode = WERR_BADFUNC;
6568 if (!get_printer_snum(p, handle, &snum)) {
6572 if (!print_job_exists(snum, jobid)) {
6573 return WERR_INVALID_PRINTER_NAME;
6576 get_current_user(&user, p);
6579 case JOB_CONTROL_CANCEL:
6580 case JOB_CONTROL_DELETE:
6581 if (print_job_delete(&user, snum, jobid, &errcode)) {
6585 case JOB_CONTROL_PAUSE:
6586 if (print_job_pause(&user, snum, jobid, &errcode)) {
6590 case JOB_CONTROL_RESTART:
6591 case JOB_CONTROL_RESUME:
6592 if (print_job_resume(&user, snum, jobid, &errcode)) {
6597 return WERR_UNKNOWN_LEVEL;
6603 /****************************************************************************
6604 Enumerates all printer drivers at level 1.
6605 ****************************************************************************/
6607 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6612 fstring *list = NULL;
6614 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6615 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6619 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6621 ndrivers=get_ntdrivers(&list, architecture, version);
6622 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6628 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6629 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6630 SAFE_FREE(driver_info_1);
6634 else driver_info_1 = tdi1;
6637 for (i=0; i<ndrivers; i++) {
6639 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6640 ZERO_STRUCT(driver);
6641 status = get_a_printer_driver(&driver, 3, list[i],
6642 architecture, version);
6643 if (!W_ERROR_IS_OK(status)) {
6647 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6648 free_a_printer_driver(driver, 3);
6651 *returned+=ndrivers;
6655 /* check the required size. */
6656 for (i=0; i<*returned; i++) {
6657 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6658 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6661 if (!alloc_buffer_size(buffer, *needed)) {
6662 SAFE_FREE(driver_info_1);
6663 return WERR_INSUFFICIENT_BUFFER;
6666 /* fill the buffer with the driver structures */
6667 for (i=0; i<*returned; i++) {
6668 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6669 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6672 SAFE_FREE(driver_info_1);
6674 if (*needed > offered) {
6676 return WERR_INSUFFICIENT_BUFFER;
6682 /****************************************************************************
6683 Enumerates all printer drivers at level 2.
6684 ****************************************************************************/
6686 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6691 fstring *list = NULL;
6693 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6694 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6698 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6700 ndrivers=get_ntdrivers(&list, architecture, version);
6701 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6707 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6708 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6709 SAFE_FREE(driver_info_2);
6713 else driver_info_2 = tdi2;
6716 for (i=0; i<ndrivers; i++) {
6719 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6720 ZERO_STRUCT(driver);
6721 status = get_a_printer_driver(&driver, 3, list[i],
6722 architecture, version);
6723 if (!W_ERROR_IS_OK(status)) {
6727 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6728 free_a_printer_driver(driver, 3);
6731 *returned+=ndrivers;
6735 /* check the required size. */
6736 for (i=0; i<*returned; i++) {
6737 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6738 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6741 if (!alloc_buffer_size(buffer, *needed)) {
6742 SAFE_FREE(driver_info_2);
6743 return WERR_INSUFFICIENT_BUFFER;
6746 /* fill the buffer with the form structures */
6747 for (i=0; i<*returned; i++) {
6748 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6749 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6752 SAFE_FREE(driver_info_2);
6754 if (*needed > offered) {
6756 return WERR_INSUFFICIENT_BUFFER;
6762 /****************************************************************************
6763 Enumerates all printer drivers at level 3.
6764 ****************************************************************************/
6766 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6771 fstring *list = NULL;
6773 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6774 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6778 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6780 ndrivers=get_ntdrivers(&list, architecture, version);
6781 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6787 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6788 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6789 SAFE_FREE(driver_info_3);
6793 else driver_info_3 = tdi3;
6796 for (i=0; i<ndrivers; i++) {
6799 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6800 ZERO_STRUCT(driver);
6801 status = get_a_printer_driver(&driver, 3, list[i],
6802 architecture, version);
6803 if (!W_ERROR_IS_OK(status)) {
6807 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6808 free_a_printer_driver(driver, 3);
6811 *returned+=ndrivers;
6815 /* check the required size. */
6816 for (i=0; i<*returned; i++) {
6817 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6818 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6821 if (!alloc_buffer_size(buffer, *needed)) {
6822 SAFE_FREE(driver_info_3);
6823 return WERR_INSUFFICIENT_BUFFER;
6826 /* fill the buffer with the driver structures */
6827 for (i=0; i<*returned; i++) {
6828 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6829 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6832 for (i=0; i<*returned; i++)
6833 SAFE_FREE(driver_info_3[i].dependentfiles);
6835 SAFE_FREE(driver_info_3);
6837 if (*needed > offered) {
6839 return WERR_INSUFFICIENT_BUFFER;
6845 /****************************************************************************
6846 Enumerates all printer drivers.
6847 ****************************************************************************/
6849 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6851 UNISTR2 *environment = &q_u->environment;
6852 uint32 level = q_u->level;
6853 NEW_BUFFER *buffer = NULL;
6854 uint32 offered = q_u->offered;
6855 uint32 *needed = &r_u->needed;
6856 uint32 *returned = &r_u->returned;
6858 fstring *list = NULL;
6860 fstring architecture;
6862 /* that's an [in out] buffer */
6863 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6864 buffer = r_u->buffer;
6866 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6867 fstrcpy(servername, get_called_name());
6871 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6875 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6877 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6879 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6883 return WERR_UNKNOWN_LEVEL;
6887 /****************************************************************************
6888 ****************************************************************************/
6890 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6892 form->flag=list->flag;
6893 init_unistr(&form->name, list->name);
6894 form->width=list->width;
6895 form->length=list->length;
6896 form->left=list->left;
6897 form->top=list->top;
6898 form->right=list->right;
6899 form->bottom=list->bottom;
6902 /****************************************************************************
6903 ****************************************************************************/
6905 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6907 uint32 level = q_u->level;
6908 NEW_BUFFER *buffer = NULL;
6909 uint32 offered = q_u->offered;
6910 uint32 *needed = &r_u->needed;
6911 uint32 *numofforms = &r_u->numofforms;
6912 uint32 numbuiltinforms;
6914 nt_forms_struct *list=NULL;
6915 nt_forms_struct *builtinlist=NULL;
6920 /* that's an [in out] buffer */
6921 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6922 buffer = r_u->buffer;
6924 DEBUG(4,("_spoolss_enumforms\n"));
6925 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6926 DEBUGADD(5,("Info level [%d]\n", level));
6928 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6929 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6930 *numofforms = get_ntforms(&list);
6931 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6932 *numofforms += numbuiltinforms;
6934 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6938 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6943 /* construct the list of form structures */
6944 for (i=0; i<numbuiltinforms; i++) {
6945 DEBUGADD(6,("Filling form number [%d]\n",i));
6946 fill_form_1(&forms_1[i], &builtinlist[i]);
6949 SAFE_FREE(builtinlist);
6951 for (; i<*numofforms; i++) {
6952 DEBUGADD(6,("Filling form number [%d]\n",i));
6953 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6958 /* check the required size. */
6959 for (i=0; i<numbuiltinforms; i++) {
6960 DEBUGADD(6,("adding form [%d]'s size\n",i));
6961 buffer_size += spoolss_size_form_1(&forms_1[i]);
6963 for (; i<*numofforms; i++) {
6964 DEBUGADD(6,("adding form [%d]'s size\n",i));
6965 buffer_size += spoolss_size_form_1(&forms_1[i]);
6968 *needed=buffer_size;
6970 if (!alloc_buffer_size(buffer, buffer_size)){
6972 return WERR_INSUFFICIENT_BUFFER;
6975 /* fill the buffer with the form structures */
6976 for (i=0; i<numbuiltinforms; i++) {
6977 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6978 smb_io_form_1("", buffer, &forms_1[i], 0);
6980 for (; i<*numofforms; i++) {
6981 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6982 smb_io_form_1("", buffer, &forms_1[i], 0);
6987 if (*needed > offered) {
6989 return WERR_INSUFFICIENT_BUFFER;
6996 SAFE_FREE(builtinlist);
6997 return WERR_UNKNOWN_LEVEL;
7002 /****************************************************************************
7003 ****************************************************************************/
7005 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7007 uint32 level = q_u->level;
7008 UNISTR2 *uni_formname = &q_u->formname;
7009 NEW_BUFFER *buffer = NULL;
7010 uint32 offered = q_u->offered;
7011 uint32 *needed = &r_u->needed;
7013 nt_forms_struct *list=NULL;
7014 nt_forms_struct builtin_form;
7019 int numofforms=0, i=0;
7021 /* that's an [in out] buffer */
7022 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7023 buffer = r_u->buffer;
7025 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7027 DEBUG(4,("_spoolss_getform\n"));
7028 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7029 DEBUGADD(5,("Info level [%d]\n", level));
7031 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7032 if (!foundBuiltin) {
7033 numofforms = get_ntforms(&list);
7034 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7036 if (numofforms == 0)
7043 fill_form_1(&form_1, &builtin_form);
7046 /* Check if the requested name is in the list of form structures */
7047 for (i=0; i<numofforms; i++) {
7049 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7051 if (strequal(form_name, list[i].name)) {
7052 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7053 fill_form_1(&form_1, &list[i]);
7059 if (i == numofforms) {
7063 /* check the required size. */
7065 *needed=spoolss_size_form_1(&form_1);
7067 if (!alloc_buffer_size(buffer, buffer_size)){
7068 return WERR_INSUFFICIENT_BUFFER;
7071 if (*needed > offered) {
7072 return WERR_INSUFFICIENT_BUFFER;
7075 /* fill the buffer with the form structures */
7076 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7077 smb_io_form_1("", buffer, &form_1, 0);
7083 return WERR_UNKNOWN_LEVEL;
7087 /****************************************************************************
7088 ****************************************************************************/
7090 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7092 init_unistr(&port->port_name, name);
7095 /****************************************************************************
7096 ****************************************************************************/
7098 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7100 init_unistr(&port->port_name, name);
7101 init_unistr(&port->monitor_name, "Local Monitor");
7102 init_unistr(&port->description, "Local Port");
7103 #define PORT_TYPE_WRITE 1
7104 port->port_type=PORT_TYPE_WRITE;
7108 /****************************************************************************
7110 ****************************************************************************/
7112 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7114 PORT_INFO_1 *ports=NULL;
7117 if (*lp_enumports_cmd()) {
7118 char *cmd = lp_enumports_cmd();
7125 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7127 DEBUG(10,("Running [%s]\n", command));
7128 ret = smbrun(command, &fd);
7129 DEBUG(10,("Returned [%d]\n", ret));
7133 /* Is this the best error to return here? */
7134 return WERR_ACCESS_DENIED;
7138 qlines = fd_lines_load(fd, &numlines);
7139 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7143 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7144 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7145 dos_errstr(WERR_NOMEM)));
7146 file_lines_free(qlines);
7150 for (i=0; i<numlines; i++) {
7151 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7152 fill_port_1(&ports[i], qlines[i]);
7155 file_lines_free(qlines);
7158 *returned = numlines;
7161 *returned = 1; /* Sole Samba port returned. */
7163 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7166 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7168 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7171 /* check the required size. */
7172 for (i=0; i<*returned; i++) {
7173 DEBUGADD(6,("adding port [%d]'s size\n", i));
7174 *needed += spoolss_size_port_info_1(&ports[i]);
7177 if (!alloc_buffer_size(buffer, *needed)) {
7179 return WERR_INSUFFICIENT_BUFFER;
7182 /* fill the buffer with the ports structures */
7183 for (i=0; i<*returned; i++) {
7184 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7185 smb_io_port_1("", buffer, &ports[i], 0);
7190 if (*needed > offered) {
7192 return WERR_INSUFFICIENT_BUFFER;
7198 /****************************************************************************
7200 ****************************************************************************/
7202 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7204 PORT_INFO_2 *ports=NULL;
7207 if (*lp_enumports_cmd()) {
7208 char *cmd = lp_enumports_cmd();
7217 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7218 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7220 path = lp_lockdir();
7222 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7223 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7226 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7227 ret = smbrun(command, &fd);
7228 DEBUGADD(10,("returned [%d]\n", ret));
7232 /* Is this the best error to return here? */
7233 return WERR_ACCESS_DENIED;
7237 qlines = fd_lines_load(fd, &numlines);
7238 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7242 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7243 file_lines_free(qlines);
7247 for (i=0; i<numlines; i++) {
7248 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7249 fill_port_2(&(ports[i]), qlines[i]);
7252 file_lines_free(qlines);
7255 *returned = numlines;
7261 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7264 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7266 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7269 /* check the required size. */
7270 for (i=0; i<*returned; i++) {
7271 DEBUGADD(6,("adding port [%d]'s size\n", i));
7272 *needed += spoolss_size_port_info_2(&ports[i]);
7275 if (!alloc_buffer_size(buffer, *needed)) {
7277 return WERR_INSUFFICIENT_BUFFER;
7280 /* fill the buffer with the ports structures */
7281 for (i=0; i<*returned; i++) {
7282 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7283 smb_io_port_2("", buffer, &ports[i], 0);
7288 if (*needed > offered) {
7290 return WERR_INSUFFICIENT_BUFFER;
7296 /****************************************************************************
7298 ****************************************************************************/
7300 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7302 uint32 level = q_u->level;
7303 NEW_BUFFER *buffer = NULL;
7304 uint32 offered = q_u->offered;
7305 uint32 *needed = &r_u->needed;
7306 uint32 *returned = &r_u->returned;
7308 /* that's an [in out] buffer */
7309 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7310 buffer = r_u->buffer;
7312 DEBUG(4,("_spoolss_enumports\n"));
7319 return enumports_level_1(buffer, offered, needed, returned);
7321 return enumports_level_2(buffer, offered, needed, returned);
7323 return WERR_UNKNOWN_LEVEL;
7327 /****************************************************************************
7328 ****************************************************************************/
7330 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7331 const SPOOL_PRINTER_INFO_LEVEL *info,
7332 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7333 uint32 user_switch, const SPOOL_USER_CTR *user,
7336 NT_PRINTER_INFO_LEVEL *printer = NULL;
7339 WERROR err = WERR_OK;
7341 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7342 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7346 ZERO_STRUCTP(printer);
7348 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7349 if (!convert_printer_info(info, printer, 2)) {
7350 free_a_printer(&printer, 2);
7354 /* check to see if the printer already exists */
7356 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7357 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7358 printer->info_2->sharename));
7359 free_a_printer(&printer, 2);
7360 return WERR_PRINTER_ALREADY_EXISTS;
7363 /* FIXME!!! smbd should check to see if the driver is installed before
7364 trying to add a printer like this --jerry */
7366 if (*lp_addprinter_cmd() ) {
7367 if ( !add_printer_hook(printer) ) {
7368 free_a_printer(&printer,2);
7369 return WERR_ACCESS_DENIED;
7373 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7374 printer->info_2->sharename);
7377 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7378 free_a_printer(&printer,2);
7379 return WERR_ACCESS_DENIED;
7382 /* you must be a printer admin to add a new printer */
7383 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7384 free_a_printer(&printer,2);
7385 return WERR_ACCESS_DENIED;
7389 * Do sanity check on the requested changes for Samba.
7392 if (!check_printer_ok(printer->info_2, snum)) {
7393 free_a_printer(&printer,2);
7394 return WERR_INVALID_PARAM;
7398 * When a printer is created, the drivername bound to the printer is used
7399 * to lookup previously saved driver initialization info, which is then
7400 * bound to the new printer, simulating what happens in the Windows arch.
7405 set_driver_init(printer, 2);
7409 /* A valid devmode was included, convert and link it
7411 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7413 if (!convert_devicemode(printer->info_2->printername, devmode,
7414 &printer->info_2->devmode))
7418 /* write the ASCII on disk */
7419 err = mod_a_printer(*printer, 2);
7420 if (!W_ERROR_IS_OK(err)) {
7421 free_a_printer(&printer,2);
7425 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7426 /* Handle open failed - remove addition. */
7427 del_a_printer(printer->info_2->sharename);
7428 free_a_printer(&printer,2);
7429 return WERR_ACCESS_DENIED;
7432 update_c_setprinter(False);
7433 free_a_printer(&printer,2);
7438 /****************************************************************************
7439 ****************************************************************************/
7441 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7443 UNISTR2 *uni_srv_name = &q_u->server_name;
7444 uint32 level = q_u->level;
7445 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7446 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7447 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7448 uint32 user_switch = q_u->user_switch;
7449 SPOOL_USER_CTR *user = &q_u->user_ctr;
7450 POLICY_HND *handle = &r_u->handle;
7454 /* we don't handle yet */
7455 /* but I know what to do ... */
7456 return WERR_UNKNOWN_LEVEL;
7458 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7460 user_switch, user, handle);
7462 return WERR_UNKNOWN_LEVEL;
7466 /****************************************************************************
7467 ****************************************************************************/
7469 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7471 uint32 level = q_u->level;
7472 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7473 WERROR err = WERR_OK;
7474 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7475 struct current_user user;
7476 fstring driver_name;
7479 ZERO_STRUCT(driver);
7481 get_current_user(&user, p);
7483 if (!convert_printer_driver_info(info, &driver, level)) {
7488 DEBUG(5,("Cleaning driver's information\n"));
7489 err = clean_up_driver_struct(driver, level, &user);
7490 if (!W_ERROR_IS_OK(err))
7493 DEBUG(5,("Moving driver to final destination\n"));
7494 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7495 if (W_ERROR_IS_OK(err))
7496 err = WERR_ACCESS_DENIED;
7500 if (add_a_printer_driver(driver, level)!=0) {
7501 err = WERR_ACCESS_DENIED;
7505 /* BEGIN_ADMIN_LOG */
7508 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7509 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7510 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7513 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7514 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7515 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7521 * I think this is where he DrvUpgradePrinter() hook would be
7522 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7523 * server. Right now, we just need to send ourselves a message
7524 * to update each printer bound to this driver. --jerry
7527 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7528 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7533 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7534 * decide if the driver init data should be deleted. The rules are:
7535 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7536 * 2) delete init data only if there is no 2k/Xp driver
7537 * 3) always delete init data
7538 * The generalized rule is always use init data from the highest order driver.
7539 * It is necessary to follow the driver install by an initialization step to
7540 * finish off this process.
7543 version = driver.info_3->cversion;
7544 else if (level == 6)
7545 version = driver.info_6->version;
7550 * 9x printer driver - never delete init data
7553 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7558 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7559 * there is no 2k/Xp driver init data for this driver name.
7563 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7565 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7567 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7569 if (!del_driver_init(driver_name))
7570 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7573 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7575 free_a_printer_driver(driver1,3);
7576 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7583 * 2k or Xp printer driver - always delete init data
7586 if (!del_driver_init(driver_name))
7587 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7591 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7597 free_a_printer_driver(driver, level);
7601 /********************************************************************
7602 * spoolss_addprinterdriverex
7603 ********************************************************************/
7605 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7607 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7608 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7611 * we only support the semantics of AddPrinterDriver()
7612 * i.e. only copy files that are newer than existing ones
7615 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7616 return WERR_ACCESS_DENIED;
7618 ZERO_STRUCT(q_u_local);
7619 ZERO_STRUCT(r_u_local);
7621 /* just pass the information off to _spoolss_addprinterdriver() */
7622 q_u_local.server_name_ptr = q_u->server_name_ptr;
7623 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7624 q_u_local.level = q_u->level;
7625 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7627 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7630 /****************************************************************************
7631 ****************************************************************************/
7633 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7635 init_unistr(&info->name, name);
7638 /****************************************************************************
7639 ****************************************************************************/
7641 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7645 const char *short_archi;
7646 DRIVER_DIRECTORY_1 *info=NULL;
7648 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7650 if (!(short_archi = get_short_archi(long_archi)))
7651 return WERR_INVALID_ENVIRONMENT;
7653 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7656 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7658 DEBUG(4,("printer driver directory: [%s]\n", path));
7660 fill_driverdir_1(info, path);
7662 *needed += spoolss_size_driverdir_info_1(info);
7664 if (!alloc_buffer_size(buffer, *needed)) {
7666 return WERR_INSUFFICIENT_BUFFER;
7669 smb_io_driverdir_1("", buffer, info, 0);
7673 if (*needed > offered)
7674 return WERR_INSUFFICIENT_BUFFER;
7679 /****************************************************************************
7680 ****************************************************************************/
7682 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7684 UNISTR2 *name = &q_u->name;
7685 UNISTR2 *uni_environment = &q_u->environment;
7686 uint32 level = q_u->level;
7687 NEW_BUFFER *buffer = NULL;
7688 uint32 offered = q_u->offered;
7689 uint32 *needed = &r_u->needed;
7691 /* that's an [in out] buffer */
7692 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7693 buffer = r_u->buffer;
7695 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7701 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7703 return WERR_UNKNOWN_LEVEL;
7707 /****************************************************************************
7708 ****************************************************************************/
7710 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7712 POLICY_HND *handle = &q_u->handle;
7713 uint32 idx = q_u->index;
7714 uint32 in_value_len = q_u->valuesize;
7715 uint32 in_data_len = q_u->datasize;
7716 uint32 *out_max_value_len = &r_u->valuesize;
7717 uint16 **out_value = &r_u->value;
7718 uint32 *out_value_len = &r_u->realvaluesize;
7719 uint32 *out_type = &r_u->type;
7720 uint32 *out_max_data_len = &r_u->datasize;
7721 uint8 **data_out = &r_u->data;
7722 uint32 *out_data_len = &r_u->realdatasize;
7724 NT_PRINTER_INFO_LEVEL *printer = NULL;
7727 uint32 biggest_valuesize;
7728 uint32 biggest_datasize;
7730 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7733 REGISTRY_VALUE *val = NULL;
7734 NT_PRINTER_DATA *p_data;
7735 int i, key_index, num_values;
7738 ZERO_STRUCT( printer );
7742 *out_max_data_len = 0;
7746 DEBUG(5,("spoolss_enumprinterdata\n"));
7749 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7753 if (!get_printer_snum(p,handle, &snum))
7756 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7757 if (!W_ERROR_IS_OK(result))
7760 p_data = &printer->info_2->data;
7761 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7766 * The NT machine wants to know the biggest size of value and data
7768 * cf: MSDN EnumPrinterData remark section
7771 if ( !in_value_len && !in_data_len && (key_index != -1) )
7773 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7776 biggest_valuesize = 0;
7777 biggest_datasize = 0;
7779 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7781 for ( i=0; i<num_values; i++ )
7783 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7785 name_length = strlen(val->valuename);
7786 if ( strlen(val->valuename) > biggest_valuesize )
7787 biggest_valuesize = name_length;
7789 if ( val->size > biggest_datasize )
7790 biggest_datasize = val->size;
7792 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7796 /* the value is an UNICODE string but real_value_size is the length
7797 in bytes including the trailing 0 */
7799 *out_value_len = 2 * (1+biggest_valuesize);
7800 *out_data_len = biggest_datasize;
7802 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7808 * the value len is wrong in NT sp3
7809 * that's the number of bytes not the number of unicode chars
7812 if ( key_index != -1 )
7813 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7818 /* out_value should default to "" or else NT4 has
7819 problems unmarshalling the response */
7821 *out_max_value_len=(in_value_len/sizeof(uint16));
7823 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7825 result = WERR_NOMEM;
7829 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7831 /* the data is counted in bytes */
7833 *out_max_data_len = in_data_len;
7834 *out_data_len = in_data_len;
7836 /* only allocate when given a non-zero data_len */
7838 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7840 result = WERR_NOMEM;
7844 result = WERR_NO_MORE_ITEMS;
7850 * - counted in bytes in the request
7851 * - counted in UNICODE chars in the max reply
7852 * - counted in bytes in the real size
7854 * take a pause *before* coding not *during* coding
7858 *out_max_value_len=(in_value_len/sizeof(uint16));
7859 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7861 result = WERR_NOMEM;
7865 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7869 *out_type = regval_type( val );
7871 /* data - counted in bytes */
7873 *out_max_data_len = in_data_len;
7874 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7876 result = WERR_NOMEM;
7879 data_len = (size_t)regval_size(val);
7880 memcpy( *data_out, regval_data_p(val), data_len );
7881 *out_data_len = data_len;
7885 free_a_printer(&printer, 2);
7889 /****************************************************************************
7890 ****************************************************************************/
7892 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7894 POLICY_HND *handle = &q_u->handle;
7895 UNISTR2 *value = &q_u->value;
7896 uint32 type = q_u->type;
7897 uint8 *data = q_u->data;
7898 uint32 real_len = q_u->real_len;
7900 NT_PRINTER_INFO_LEVEL *printer = NULL;
7902 WERROR status = WERR_OK;
7903 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7906 DEBUG(5,("spoolss_setprinterdata\n"));
7909 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7913 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7914 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7915 return WERR_INVALID_PARAM;
7918 if (!get_printer_snum(p,handle, &snum))
7922 * Access check : NT returns "access denied" if you make a
7923 * SetPrinterData call without the necessary privildge.
7924 * we were originally returning OK if nothing changed
7925 * which made Win2k issue **a lot** of SetPrinterData
7926 * when connecting to a printer --jerry
7929 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7931 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7932 status = WERR_ACCESS_DENIED;
7936 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7937 if (!W_ERROR_IS_OK(status))
7940 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7943 * When client side code sets a magic printer data key, detect it and save
7944 * the current printer data and the magic key's data (its the DEVMODE) for
7945 * future printer/driver initializations.
7947 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7949 /* Set devmode and printer initialization info */
7950 status = save_driver_init( printer, 2, data, real_len );
7952 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7956 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7957 type, data, real_len );
7958 if ( W_ERROR_IS_OK(status) )
7959 status = mod_a_printer(*printer, 2);
7963 free_a_printer(&printer, 2);
7968 /****************************************************************************
7969 ****************************************************************************/
7971 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7973 POLICY_HND *handle = &q_u->handle;
7974 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7977 DEBUG(5,("_spoolss_resetprinter\n"));
7980 * All we do is to check to see if the handle and queue is valid.
7981 * This call really doesn't mean anything to us because we only
7982 * support RAW printing. --jerry
7986 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7990 if (!get_printer_snum(p,handle, &snum))
7994 /* blindly return success */
7999 /****************************************************************************
8000 ****************************************************************************/
8002 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8004 POLICY_HND *handle = &q_u->handle;
8005 UNISTR2 *value = &q_u->valuename;
8007 NT_PRINTER_INFO_LEVEL *printer = NULL;
8009 WERROR status = WERR_OK;
8010 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8013 DEBUG(5,("spoolss_deleteprinterdata\n"));
8016 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8020 if (!get_printer_snum(p, handle, &snum))
8023 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8024 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8025 return WERR_ACCESS_DENIED;
8028 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8029 if (!W_ERROR_IS_OK(status))
8032 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8034 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8036 free_a_printer(&printer, 2);
8041 /****************************************************************************
8042 ****************************************************************************/
8044 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8046 POLICY_HND *handle = &q_u->handle;
8047 FORM *form = &q_u->form;
8048 nt_forms_struct tmpForm;
8050 WERROR status = WERR_OK;
8051 NT_PRINTER_INFO_LEVEL *printer = NULL;
8054 nt_forms_struct *list=NULL;
8055 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8057 DEBUG(5,("spoolss_addform\n"));
8060 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8065 /* forms can be added on printer of on the print server handle */
8067 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8069 if (!get_printer_snum(p,handle, &snum))
8072 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8073 if (!W_ERROR_IS_OK(status))
8077 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8078 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8079 status = WERR_ACCESS_DENIED;
8083 /* can't add if builtin */
8085 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8086 status = WERR_ALREADY_EXISTS;
8090 count = get_ntforms(&list);
8092 if(!add_a_form(&list, form, &count)) {
8093 status = WERR_NOMEM;
8097 write_ntforms(&list, count);
8100 * ChangeID must always be set if this is a printer
8103 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8104 status = mod_a_printer(*printer, 2);
8108 free_a_printer(&printer, 2);
8114 /****************************************************************************
8115 ****************************************************************************/
8117 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8119 POLICY_HND *handle = &q_u->handle;
8120 UNISTR2 *form_name = &q_u->name;
8121 nt_forms_struct tmpForm;
8123 nt_forms_struct *list=NULL;
8124 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8126 WERROR status = WERR_OK;
8127 NT_PRINTER_INFO_LEVEL *printer = NULL;
8129 DEBUG(5,("spoolss_deleteform\n"));
8132 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8136 /* forms can be deleted on printer of on the print server handle */
8138 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8140 if (!get_printer_snum(p,handle, &snum))
8143 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8144 if (!W_ERROR_IS_OK(status))
8148 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8149 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8150 status = WERR_ACCESS_DENIED;
8154 /* can't delete if builtin */
8156 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8157 status = WERR_INVALID_PARAM;
8161 count = get_ntforms(&list);
8163 if ( !delete_a_form(&list, form_name, &count, &status ))
8167 * ChangeID must always be set if this is a printer
8170 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8171 status = mod_a_printer(*printer, 2);
8175 free_a_printer(&printer, 2);
8181 /****************************************************************************
8182 ****************************************************************************/
8184 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8186 POLICY_HND *handle = &q_u->handle;
8187 FORM *form = &q_u->form;
8188 nt_forms_struct tmpForm;
8190 WERROR status = WERR_OK;
8191 NT_PRINTER_INFO_LEVEL *printer = NULL;
8194 nt_forms_struct *list=NULL;
8195 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8197 DEBUG(5,("spoolss_setform\n"));
8200 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8204 /* forms can be modified on printer of on the print server handle */
8206 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8208 if (!get_printer_snum(p,handle, &snum))
8211 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8212 if (!W_ERROR_IS_OK(status))
8216 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8217 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8218 status = WERR_ACCESS_DENIED;
8222 /* can't set if builtin */
8223 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8224 status = WERR_INVALID_PARAM;
8228 count = get_ntforms(&list);
8229 update_a_form(&list, form, count);
8230 write_ntforms(&list, count);
8233 * ChangeID must always be set if this is a printer
8236 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8237 status = mod_a_printer(*printer, 2);
8242 free_a_printer(&printer, 2);
8248 /****************************************************************************
8249 enumprintprocessors level 1.
8250 ****************************************************************************/
8252 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8254 PRINTPROCESSOR_1 *info_1=NULL;
8256 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8261 init_unistr(&info_1->name, "winprint");
8263 *needed += spoolss_size_printprocessor_info_1(info_1);
8265 if (!alloc_buffer_size(buffer, *needed))
8266 return WERR_INSUFFICIENT_BUFFER;
8268 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8272 if (*needed > offered) {
8274 return WERR_INSUFFICIENT_BUFFER;
8280 /****************************************************************************
8281 ****************************************************************************/
8283 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8285 uint32 level = q_u->level;
8286 NEW_BUFFER *buffer = NULL;
8287 uint32 offered = q_u->offered;
8288 uint32 *needed = &r_u->needed;
8289 uint32 *returned = &r_u->returned;
8291 /* that's an [in out] buffer */
8292 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8293 buffer = r_u->buffer;
8295 DEBUG(5,("spoolss_enumprintprocessors\n"));
8298 * Enumerate the print processors ...
8300 * Just reply with "winprint", to keep NT happy
8301 * and I can use my nice printer checker.
8309 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8311 return WERR_UNKNOWN_LEVEL;
8315 /****************************************************************************
8316 enumprintprocdatatypes level 1.
8317 ****************************************************************************/
8319 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8321 PRINTPROCDATATYPE_1 *info_1=NULL;
8323 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8328 init_unistr(&info_1->name, "RAW");
8330 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8332 if (!alloc_buffer_size(buffer, *needed))
8333 return WERR_INSUFFICIENT_BUFFER;
8335 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8339 if (*needed > offered) {
8341 return WERR_INSUFFICIENT_BUFFER;
8347 /****************************************************************************
8348 ****************************************************************************/
8350 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8352 uint32 level = q_u->level;
8353 NEW_BUFFER *buffer = NULL;
8354 uint32 offered = q_u->offered;
8355 uint32 *needed = &r_u->needed;
8356 uint32 *returned = &r_u->returned;
8358 /* that's an [in out] buffer */
8359 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8360 buffer = r_u->buffer;
8362 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8369 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8371 return WERR_UNKNOWN_LEVEL;
8375 /****************************************************************************
8376 enumprintmonitors level 1.
8377 ****************************************************************************/
8379 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8381 PRINTMONITOR_1 *info_1=NULL;
8383 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8388 init_unistr(&info_1->name, "Local Port");
8390 *needed += spoolss_size_printmonitor_info_1(info_1);
8392 if (!alloc_buffer_size(buffer, *needed))
8393 return WERR_INSUFFICIENT_BUFFER;
8395 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8399 if (*needed > offered) {
8401 return WERR_INSUFFICIENT_BUFFER;
8407 /****************************************************************************
8408 enumprintmonitors level 2.
8409 ****************************************************************************/
8411 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8413 PRINTMONITOR_2 *info_2=NULL;
8415 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8420 init_unistr(&info_2->name, "Local Port");
8421 init_unistr(&info_2->environment, "Windows NT X86");
8422 init_unistr(&info_2->dll_name, "localmon.dll");
8424 *needed += spoolss_size_printmonitor_info_2(info_2);
8426 if (!alloc_buffer_size(buffer, *needed))
8427 return WERR_INSUFFICIENT_BUFFER;
8429 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8433 if (*needed > offered) {
8435 return WERR_INSUFFICIENT_BUFFER;
8441 /****************************************************************************
8442 ****************************************************************************/
8444 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8446 uint32 level = q_u->level;
8447 NEW_BUFFER *buffer = NULL;
8448 uint32 offered = q_u->offered;
8449 uint32 *needed = &r_u->needed;
8450 uint32 *returned = &r_u->returned;
8452 /* that's an [in out] buffer */
8453 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8454 buffer = r_u->buffer;
8456 DEBUG(5,("spoolss_enumprintmonitors\n"));
8459 * Enumerate the print monitors ...
8461 * Just reply with "Local Port", to keep NT happy
8462 * and I can use my nice printer checker.
8470 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8472 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8474 return WERR_UNKNOWN_LEVEL;
8478 /****************************************************************************
8479 ****************************************************************************/
8481 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8485 JOB_INFO_1 *info_1=NULL;
8487 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8489 if (info_1 == NULL) {
8493 for (i=0; i<count && found==False; i++) {
8494 if ((*queue)[i].job==(int)jobid)
8500 /* NT treats not found as bad param... yet another bad choice */
8501 return WERR_INVALID_PARAM;
8504 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8506 *needed += spoolss_size_job_info_1(info_1);
8508 if (!alloc_buffer_size(buffer, *needed)) {
8510 return WERR_INSUFFICIENT_BUFFER;
8513 smb_io_job_info_1("", buffer, info_1, 0);
8517 if (*needed > offered)
8518 return WERR_INSUFFICIENT_BUFFER;
8523 /****************************************************************************
8524 ****************************************************************************/
8526 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8531 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8533 DEVICEMODE *devmode = NULL;
8534 NT_DEVICEMODE *nt_devmode = NULL;
8536 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8538 ZERO_STRUCTP(info_2);
8540 if (info_2 == NULL) {
8545 for ( i=0; i<count && found==False; i++ )
8547 if ((*queue)[i].job == (int)jobid)
8553 /* NT treats not found as bad param... yet another bad
8555 ret = WERR_INVALID_PARAM;
8559 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8560 if (!W_ERROR_IS_OK(ret))
8564 * if the print job does not have a DEVMODE associated with it,
8565 * just use the one for the printer. A NULL devicemode is not
8566 * a failure condition
8569 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8570 devmode = construct_dev_mode(snum);
8572 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8573 ZERO_STRUCTP( devmode );
8574 convert_nt_devicemode( devmode, nt_devmode );
8578 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8580 *needed += spoolss_size_job_info_2(info_2);
8582 if (!alloc_buffer_size(buffer, *needed)) {
8583 ret = WERR_INSUFFICIENT_BUFFER;
8587 smb_io_job_info_2("", buffer, info_2, 0);
8589 if (*needed > offered) {
8590 ret = WERR_INSUFFICIENT_BUFFER;
8597 /* Cleanup allocated memory */
8599 free_job_info_2(info_2); /* Also frees devmode */
8601 free_a_printer(&ntprinter, 2);
8606 /****************************************************************************
8607 ****************************************************************************/
8609 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8611 POLICY_HND *handle = &q_u->handle;
8612 uint32 jobid = q_u->jobid;
8613 uint32 level = q_u->level;
8614 NEW_BUFFER *buffer = NULL;
8615 uint32 offered = q_u->offered;
8616 uint32 *needed = &r_u->needed;
8617 WERROR wstatus = WERR_OK;
8621 print_queue_struct *queue = NULL;
8622 print_status_struct prt_status;
8624 /* that's an [in out] buffer */
8625 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8626 buffer = r_u->buffer;
8628 DEBUG(5,("spoolss_getjob\n"));
8632 if (!get_printer_snum(p, handle, &snum))
8635 count = print_queue_status(snum, &queue, &prt_status);
8637 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8638 count, prt_status.status, prt_status.message));
8642 wstatus = getjob_level_1(&queue, count, snum, jobid,
8643 buffer, offered, needed);
8646 wstatus = getjob_level_2(&queue, count, snum, jobid,
8647 buffer, offered, needed);
8650 wstatus = WERR_UNKNOWN_LEVEL;
8658 /********************************************************************
8659 spoolss_getprinterdataex
8661 From MSDN documentation of GetPrinterDataEx: pass request
8662 to GetPrinterData if key is "PrinterDriverData".
8663 ********************************************************************/
8665 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8667 POLICY_HND *handle = &q_u->handle;
8668 uint32 in_size = q_u->size;
8669 uint32 *type = &r_u->type;
8670 uint32 *out_size = &r_u->size;
8671 uint8 **data = &r_u->data;
8672 uint32 *needed = &r_u->needed;
8673 fstring keyname, valuename;
8675 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8677 NT_PRINTER_INFO_LEVEL *printer = NULL;
8679 WERROR status = WERR_OK;
8681 DEBUG(4,("_spoolss_getprinterdataex\n"));
8683 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8684 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8686 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8687 keyname, valuename));
8689 /* in case of problem, return some default values */
8693 *out_size = in_size;
8696 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8697 status = WERR_BADFID;
8701 /* Is the handle to a printer or to the server? */
8703 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8704 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8705 status = WERR_INVALID_PARAM;
8709 if ( !get_printer_snum(p,handle, &snum) )
8712 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8713 if ( !W_ERROR_IS_OK(status) )
8716 /* check to see if the keyname is valid */
8717 if ( !strlen(keyname) ) {
8718 status = WERR_INVALID_PARAM;
8722 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8723 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8724 free_a_printer( &printer, 2 );
8725 status = WERR_BADFILE;
8729 /* When given a new keyname, we should just create it */
8731 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8733 if (*needed > *out_size)
8734 status = WERR_MORE_DATA;
8737 if ( !W_ERROR_IS_OK(status) )
8739 DEBUG(5, ("error: allocating %d\n", *out_size));
8741 /* reply this param doesn't exist */
8745 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8746 status = WERR_NOMEM;
8756 free_a_printer( &printer, 2 );
8761 /********************************************************************
8762 * spoolss_setprinterdataex
8763 ********************************************************************/
8765 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8767 POLICY_HND *handle = &q_u->handle;
8768 uint32 type = q_u->type;
8769 uint8 *data = q_u->data;
8770 uint32 real_len = q_u->real_len;
8772 NT_PRINTER_INFO_LEVEL *printer = NULL;
8774 WERROR status = WERR_OK;
8775 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8780 DEBUG(4,("_spoolss_setprinterdataex\n"));
8782 /* From MSDN documentation of SetPrinterDataEx: pass request to
8783 SetPrinterData if key is "PrinterDriverData" */
8786 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8790 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8791 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8792 return WERR_INVALID_PARAM;
8795 if ( !get_printer_snum(p,handle, &snum) )
8799 * Access check : NT returns "access denied" if you make a
8800 * SetPrinterData call without the necessary privildge.
8801 * we were originally returning OK if nothing changed
8802 * which made Win2k issue **a lot** of SetPrinterData
8803 * when connecting to a printer --jerry
8806 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8808 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8809 return WERR_ACCESS_DENIED;
8812 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8813 if (!W_ERROR_IS_OK(status))
8816 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8817 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8819 /* check for OID in valuename */
8821 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8827 /* save the registry data */
8829 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8831 if ( W_ERROR_IS_OK(status) )
8833 /* save the OID if one was specified */
8835 fstrcat( keyname, "\\" );
8836 fstrcat( keyname, SPOOL_OID_KEY );
8839 * I'm not checking the status here on purpose. Don't know
8840 * if this is right, but I'm returning the status from the
8841 * previous set_printer_dataex() call. I have no idea if
8842 * this is right. --jerry
8845 set_printer_dataex( printer, keyname, valuename,
8846 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8849 status = mod_a_printer(*printer, 2);
8852 free_a_printer(&printer, 2);
8858 /********************************************************************
8859 * spoolss_deleteprinterdataex
8860 ********************************************************************/
8862 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8864 POLICY_HND *handle = &q_u->handle;
8865 UNISTR2 *value = &q_u->valuename;
8866 UNISTR2 *key = &q_u->keyname;
8868 NT_PRINTER_INFO_LEVEL *printer = NULL;
8870 WERROR status = WERR_OK;
8871 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8872 pstring valuename, keyname;
8874 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8877 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8881 if (!get_printer_snum(p, handle, &snum))
8884 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8885 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8886 return WERR_ACCESS_DENIED;
8889 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8890 if (!W_ERROR_IS_OK(status))
8893 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8894 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8896 status = delete_printer_dataex( printer, keyname, valuename );
8898 free_a_printer(&printer, 2);
8903 /********************************************************************
8904 * spoolss_enumprinterkey
8905 ********************************************************************/
8908 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8911 fstring *keynames = NULL;
8912 uint16 *enumkeys = NULL;
8915 POLICY_HND *handle = &q_u->handle;
8916 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8917 NT_PRINTER_DATA *data;
8918 NT_PRINTER_INFO_LEVEL *printer = NULL;
8920 WERROR status = WERR_BADFILE;
8923 DEBUG(4,("_spoolss_enumprinterkey\n"));
8926 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8930 if ( !get_printer_snum(p,handle, &snum) )
8933 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8934 if (!W_ERROR_IS_OK(status))
8937 /* get the list of subkey names */
8939 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8940 data = &printer->info_2->data;
8942 num_keys = get_printer_subkeys( data, key, &keynames );
8944 if ( num_keys == -1 ) {
8945 status = WERR_BADFILE;
8949 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8951 r_u->needed = printerkey_len*2;
8953 if ( q_u->size < r_u->needed ) {
8954 status = WERR_MORE_DATA;
8958 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8959 status = WERR_NOMEM;
8965 if ( q_u->size < r_u->needed )
8966 status = WERR_MORE_DATA;
8969 free_a_printer( &printer, 2 );
8970 SAFE_FREE( keynames );
8975 /********************************************************************
8976 * spoolss_deleteprinterkey
8977 ********************************************************************/
8979 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8981 POLICY_HND *handle = &q_u->handle;
8982 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8984 NT_PRINTER_INFO_LEVEL *printer = NULL;
8988 DEBUG(5,("spoolss_deleteprinterkey\n"));
8991 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8995 /* if keyname == NULL, return error */
8997 if ( !q_u->keyname.buffer )
8998 return WERR_INVALID_PARAM;
9000 if (!get_printer_snum(p, handle, &snum))
9003 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9004 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9005 return WERR_ACCESS_DENIED;
9008 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9009 if (!W_ERROR_IS_OK(status))
9012 /* delete the key and all subneys */
9014 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9016 status = delete_all_printer_data( printer->info_2, key );
9018 if ( W_ERROR_IS_OK(status) )
9019 status = mod_a_printer(*printer, 2);
9021 free_a_printer( &printer, 2 );
9027 /********************************************************************
9028 * spoolss_enumprinterdataex
9029 ********************************************************************/
9031 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9033 POLICY_HND *handle = &q_u->handle;
9034 uint32 in_size = q_u->size;
9037 NT_PRINTER_INFO_LEVEL *printer = NULL;
9038 PRINTER_ENUM_VALUES *enum_values = NULL;
9039 NT_PRINTER_DATA *p_data;
9041 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9046 REGISTRY_VALUE *val;
9051 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9054 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9059 * first check for a keyname of NULL or "". Win2k seems to send
9060 * this a lot and we should send back WERR_INVALID_PARAM
9061 * no need to spend time looking up the printer in this case.
9065 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9066 if ( !strlen(key) ) {
9067 result = WERR_INVALID_PARAM;
9071 /* get the printer off of disk */
9073 if (!get_printer_snum(p,handle, &snum))
9076 ZERO_STRUCT(printer);
9077 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9078 if (!W_ERROR_IS_OK(result))
9081 /* now look for a match on the key name */
9083 p_data = &printer->info_2->data;
9085 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9086 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9088 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9089 result = WERR_INVALID_PARAM;
9096 /* allocate the memory for the array of pointers -- if necessary */
9098 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9101 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9103 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9104 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9105 result = WERR_NOMEM;
9109 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9113 * loop through all params and build the array to pass
9114 * back to the client
9117 for ( i=0; i<num_entries; i++ )
9119 /* lookup the registry value */
9121 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9122 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9126 value_name = regval_name( val );
9127 init_unistr( &enum_values[i].valuename, value_name );
9128 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9129 enum_values[i].type = regval_type( val );
9131 data_len = regval_size( val );
9133 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9135 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9137 result = WERR_NOMEM;
9141 enum_values[i].data_len = data_len;
9143 /* keep track of the size of the array in bytes */
9145 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9148 /* housekeeping information in the reply */
9150 r_u->needed = needed;
9151 r_u->returned = num_entries;
9153 if (needed > in_size) {
9154 result = WERR_MORE_DATA;
9158 /* copy data into the reply */
9160 r_u->ctr.size = r_u->needed;
9161 r_u->ctr.size_of_array = r_u->returned;
9162 r_u->ctr.values = enum_values;
9168 free_a_printer(&printer, 2);
9173 /****************************************************************************
9174 ****************************************************************************/
9176 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9178 init_unistr(&info->name, name);
9181 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9182 UNISTR2 *environment,
9189 const char *short_archi;
9190 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9192 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9194 if (!(short_archi = get_short_archi(long_archi)))
9195 return WERR_INVALID_ENVIRONMENT;
9197 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9200 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9202 fill_printprocessordirectory_1(info, path);
9204 *needed += spoolss_size_printprocessordirectory_info_1(info);
9206 if (!alloc_buffer_size(buffer, *needed)) {
9208 return WERR_INSUFFICIENT_BUFFER;
9211 smb_io_printprocessordirectory_1("", buffer, info, 0);
9215 if (*needed > offered)
9216 return WERR_INSUFFICIENT_BUFFER;
9221 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9223 uint32 level = q_u->level;
9224 NEW_BUFFER *buffer = NULL;
9225 uint32 offered = q_u->offered;
9226 uint32 *needed = &r_u->needed;
9229 /* that's an [in out] buffer */
9230 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9231 buffer = r_u->buffer;
9233 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9239 result = getprintprocessordirectory_level_1
9240 (&q_u->name, &q_u->environment, buffer, offered, needed);
9243 result = WERR_UNKNOWN_LEVEL;
9251 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9252 SPOOL_R_REPLYOPENPRINTER *r_u)
9254 DEBUG(5,("_spoolss_replyopenprinter\n"));
9256 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9261 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9262 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9264 DEBUG(5,("_spoolss_replycloseprinter\n"));