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-2004,
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_PRINT_NOTIFY
);
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
316 && StrCaseCmp(p
->dev
.handlename
, printername
)==0)
318 DEBUG(10,("invalidating printer_info cache for handl:\n"));
319 free_a_printer( &p
->printer_info
, 2 );
320 p
->printer_info
= NULL
;
326 /****************************************************************************
327 Close printer index by handle.
328 ****************************************************************************/
330 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
332 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
335 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
339 close_policy_hnd(p
, hnd
);
344 /****************************************************************************
345 Delete a printer given a handle.
346 ****************************************************************************/
348 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
350 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
353 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
358 * It turns out that Windows allows delete printer on a handle
359 * opened by an admin user, then used on a pipe handle created
360 * by an anonymous user..... but they're working on security.... riiight !
364 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
365 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
366 return WERR_ACCESS_DENIED
;
370 /* Check calling user has permission to delete printer. Note that
371 since we set the snum parameter to -1 only administrators can
372 delete the printer. This stops people with the Full Control
373 permission from deleting the printer. */
375 if (!print_access_check(NULL
, -1, PRINTER_ACCESS_ADMINISTER
)) {
376 DEBUG(3, ("printer delete denied by security descriptor\n"));
377 return WERR_ACCESS_DENIED
;
381 if (del_a_printer(Printer
->dev
.handlename
) != 0) {
382 DEBUG(3,("Error deleting printer %s\n", Printer
->dev
.handlename
));
386 if (*lp_deleteprinter_cmd()) {
388 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 ( 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();
477 char *aprinter
, *printername
;
480 NT_PRINTER_INFO_LEVEL
*printer
;
483 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
, (unsigned long)strlen(handlename
)));
485 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTSERVER
) {
486 ZERO_STRUCT(Printer
->dev
.printerservername
);
487 strncpy(Printer
->dev
.printerservername
, handlename
, strlen(handlename
));
491 if (Printer
->printer_type
!=PRINTER_HANDLE_IS_PRINTER
)
494 if (*handlename
=='\\') {
495 aprinter
=strchr_m(handlename
+2, '\\');
502 DEBUGADD(5, ("searching for [%s] (len=%lu)\n", aprinter
, (unsigned long)strlen(aprinter
)));
504 /* have to search on sharename and PRINTER_INFO2->printername */
506 for (snum
=0; snum
<n_services
; snum
++) {
508 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
511 /* ------ sharename ------ */
513 fstrcpy(sname
, lp_servicename(snum
));
515 DEBUGADD(10, ("share: %s\n",sname
));
517 if ( strequal(sname
, aprinter
) ) {
522 /* ------ printername ------ */
525 result
= get_a_printer( NULL
, &printer
, 2, sname
);
526 if ( !W_ERROR_IS_OK(result
) ) {
527 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
528 sname
, dos_errstr(result
)));
532 /* printername is always returned as \\server\printername */
533 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
534 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
535 printer
->info_2
->printername
));
536 free_a_printer( &printer
, 2);
542 if ( strequal(printername
, aprinter
) ) {
546 DEBUGADD(10, ("printername: %s\n", printername
));
548 free_a_printer( &printer
, 2);
556 DEBUGADD(4,("Printer not found\n"));
560 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
562 ZERO_STRUCT(Printer
->dev
.handlename
);
563 fstrcpy(Printer
->dev
.handlename
, sname
);
568 /****************************************************************************
569 Find first available printer slot. creates a printer handle for you.
570 ****************************************************************************/
572 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
574 Printer_entry
*new_printer
;
576 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
578 if((new_printer
=(Printer_entry
*)malloc(sizeof(Printer_entry
))) == NULL
)
581 ZERO_STRUCTP(new_printer
);
583 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
584 SAFE_FREE(new_printer
);
588 /* Add to the internal list. */
589 DLIST_ADD(printers_list
, new_printer
);
591 new_printer
->notify
.option
=NULL
;
593 if ( !(new_printer
->ctx
= talloc_init("Printer Entry [%p]", hnd
)) ) {
594 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
595 close_printer_handle(p
, hnd
);
599 if (!set_printer_hnd_printertype(new_printer
, name
)) {
600 close_printer_handle(p
, hnd
);
604 if (!set_printer_hnd_name(new_printer
, name
)) {
605 close_printer_handle(p
, hnd
);
609 new_printer
->access_granted
= access_granted
;
611 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
616 /****************************************************************************
617 Allocate more memory for a BUFFER.
618 ****************************************************************************/
620 static BOOL
alloc_buffer_size(NEW_BUFFER
*buffer
, uint32 buffer_size
)
628 /* damn, I'm doing the reverse operation of prs_grow() :) */
629 if (buffer_size
< prs_data_size(ps
))
632 extra_space
= buffer_size
- prs_data_size(ps
);
635 * save the offset and move to the end of the buffer
636 * prs_grow() checks the extra_space against the offset
638 old_offset
=prs_offset(ps
);
639 prs_set_offset(ps
, prs_data_size(ps
));
641 if (!prs_grow(ps
, extra_space
))
644 prs_set_offset(ps
, old_offset
);
646 buffer
->string_at_end
=prs_data_size(ps
);
651 /***************************************************************************
652 check to see if the client motify handle is monitoring the notification
653 given by (notify_type, notify_field).
654 **************************************************************************/
656 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
662 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
665 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
669 * Flags should always be zero when the change notify
670 * is registered by the client's spooler. A user Win32 app
671 * might use the flags though instead of the NOTIFY_OPTION_INFO
680 return is_monitoring_event_flags(
681 p
->notify
.flags
, notify_type
, notify_field
);
683 for (i
= 0; i
< option
->count
; i
++) {
685 /* Check match for notify_type */
687 if (option
->ctr
.type
[i
].type
!= notify_type
)
690 /* Check match for field */
692 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
693 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
699 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
700 (p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) ?
701 p
->dev
.handlename
: p
->dev
.printerservername
,
702 notify_type
, notify_field
));
707 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
709 static void notify_one_value(struct spoolss_notify_msg
*msg
,
710 SPOOL_NOTIFY_INFO_DATA
*data
,
713 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
714 data
->notify_data
.value
[1] = 0;
717 static void notify_string(struct spoolss_notify_msg
*msg
,
718 SPOOL_NOTIFY_INFO_DATA
*data
,
723 /* The length of the message includes the trailing \0 */
725 init_unistr2(&unistr
, msg
->notify
.data
, UNI_STR_TERMINATE
);
727 data
->notify_data
.data
.length
= msg
->len
* 2;
728 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, msg
->len
* 2);
730 if (!data
->notify_data
.data
.string
) {
731 data
->notify_data
.data
.length
= 0;
735 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
738 static void notify_system_time(struct spoolss_notify_msg
*msg
,
739 SPOOL_NOTIFY_INFO_DATA
*data
,
745 if (msg
->len
!= sizeof(time_t)) {
746 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
751 if (!prs_init(&ps
, MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
752 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
756 if (!make_systemtime(&systime
, gmtime((time_t *)msg
->notify
.data
))) {
757 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
761 if (!spoolss_io_system_time("", &ps
, 0, &systime
))
764 data
->notify_data
.data
.length
= prs_offset(&ps
);
765 data
->notify_data
.data
.string
= talloc(mem_ctx
, prs_offset(&ps
));
767 prs_copy_all_data_out((char *)data
->notify_data
.data
.string
, &ps
);
772 struct notify2_message_table
{
774 void (*fn
)(struct spoolss_notify_msg
*msg
,
775 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
778 static struct notify2_message_table printer_notify_table
[] = {
779 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
780 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
781 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
782 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
783 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
784 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
785 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
786 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
787 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
788 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
789 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
790 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
791 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
792 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
793 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
794 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
795 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
796 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
797 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
800 static struct notify2_message_table job_notify_table
[] = {
801 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
802 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
803 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
804 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
805 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
806 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
807 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
808 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
809 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
810 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
811 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
812 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
813 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
814 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
815 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
816 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
817 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
818 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
819 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
820 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
821 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
822 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
823 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
824 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
828 /***********************************************************************
829 Allocate talloc context for container object
830 **********************************************************************/
832 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
837 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
842 /***********************************************************************
843 release all allocated memory and zero out structure
844 **********************************************************************/
846 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
852 talloc_destroy(ctr
->ctx
);
859 /***********************************************************************
860 **********************************************************************/
862 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
870 /***********************************************************************
871 **********************************************************************/
873 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
875 if ( !ctr
|| !ctr
->msg_groups
)
878 if ( idx
>= ctr
->num_groups
)
881 return &ctr
->msg_groups
[idx
];
885 /***********************************************************************
886 How many groups of change messages do we have ?
887 **********************************************************************/
889 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
894 return ctr
->num_groups
;
897 /***********************************************************************
898 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
899 **********************************************************************/
901 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
903 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
904 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
905 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
911 /* loop over all groups looking for a matching printer name */
913 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
914 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
918 /* add a new group? */
920 if ( i
== ctr
->num_groups
) {
923 if ( !(groups
= talloc_realloc( ctr
->ctx
, ctr
->msg_groups
, sizeof(SPOOLSS_NOTIFY_MSG_GROUP
)*ctr
->num_groups
)) ) {
924 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
927 ctr
->msg_groups
= groups
;
929 /* clear the new entry and set the printer name */
931 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
932 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
935 /* add the change messages; 'i' is the correct index now regardless */
937 msg_grp
= &ctr
->msg_groups
[i
];
941 if ( !(msg_list
= talloc_realloc( ctr
->ctx
, msg_grp
->msgs
, sizeof(SPOOLSS_NOTIFY_MSG
)*msg_grp
->num_msgs
)) ) {
942 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
945 msg_grp
->msgs
= msg_list
;
947 new_slot
= msg_grp
->num_msgs
-1;
948 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
950 /* need to allocate own copy of data */
953 msg_grp
->msgs
[new_slot
].notify
.data
= talloc_memdup( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
955 return ctr
->num_groups
;
958 /***********************************************************************
959 Send a change notication message on all handles which have a call
961 **********************************************************************/
963 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
966 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
967 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
968 SPOOLSS_NOTIFY_MSG
*messages
;
969 int sending_msg_count
;
972 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
976 messages
= msg_group
->msgs
;
979 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
983 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
985 /* loop over all printers */
987 for (p
= printers_list
; p
; p
= p
->next
) {
988 SPOOL_NOTIFY_INFO_DATA
*data
;
993 /* Is there notification on this handle? */
995 if ( !p
->notify
.client_connected
)
998 DEBUG(10,("Client connected! [%s]\n", p
->dev
.handlename
));
1000 /* For this printer? Print servers always receive
1003 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
1004 ( !strequal(msg_group
->printername
, p
->dev
.handlename
) ) )
1007 DEBUG(10,("Our printer\n"));
1009 /* allocate the max entries possible */
1011 data
= talloc( mem_ctx
, msg_group
->num_msgs
*sizeof(SPOOL_NOTIFY_INFO_DATA
) );
1014 /* build the array of change notifications */
1016 sending_msg_count
= 0;
1018 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
1019 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
1021 /* Are we monitoring this event? */
1023 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1026 sending_msg_count
++;
1029 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1030 msg
->type
, msg
->field
, p
->dev
.handlename
));
1033 * if the is a printer notification handle and not a job notification
1034 * type, then set the id to 0. Other wise just use what was specified
1037 * When registering change notification on a print server handle
1038 * we always need to send back the id (snum) matching the printer
1039 * for which the change took place. For change notify registered
1040 * on a printer handle, this does not matter and the id should be 0.
1045 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1051 /* Convert unix jobid to smb jobid */
1053 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1054 id
= sysjob_to_jobid(msg
->id
);
1057 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1062 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1065 case PRINTER_NOTIFY_TYPE
:
1066 if ( printer_notify_table
[msg
->field
].fn
)
1067 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1070 case JOB_NOTIFY_TYPE
:
1071 if ( job_notify_table
[msg
->field
].fn
)
1072 job_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1076 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1083 if ( sending_msg_count
) {
1084 cli_spoolss_rrpcn( ¬ify_cli
, mem_ctx
, &p
->notify
.client_hnd
,
1085 data_len
, data
, p
->notify
.change
, 0 );
1090 DEBUG(8,("send_notify2_changes: Exit...\n"));
1094 /***********************************************************************
1095 **********************************************************************/
1097 static BOOL
notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1100 uint32 tv_sec
, tv_usec
;
1103 /* Unpack message */
1105 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
1108 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddddd",
1110 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1113 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
1114 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1116 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
1117 &msg
->len
, &msg
->notify
.data
);
1119 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1120 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1122 tv
->tv_sec
= tv_sec
;
1123 tv
->tv_usec
= tv_usec
;
1126 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1127 msg
->notify
.value
[1]));
1129 dump_data(3, msg
->notify
.data
, msg
->len
);
1134 /********************************************************************
1135 Receive a notify2 message list
1136 ********************************************************************/
1138 static void receive_notify2_message_list(int msg_type
, pid_t src
, void *msg
, size_t len
)
1140 size_t msg_count
, i
;
1141 char *buf
= (char *)msg
;
1144 SPOOLSS_NOTIFY_MSG notify
;
1145 SPOOLSS_NOTIFY_MSG_CTR messages
;
1149 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1153 msg_count
= IVAL(buf
, 0);
1156 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1158 if (msg_count
== 0) {
1159 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1163 /* initialize the container */
1165 ZERO_STRUCT( messages
);
1166 notify_msg_ctr_init( &messages
);
1169 * build message groups for each printer identified
1170 * in a change_notify msg. Remember that a PCN message
1171 * includes the handle returned for the srv_spoolss_replyopenprinter()
1172 * call. Therefore messages are grouped according to printer handle.
1175 for ( i
=0; i
<msg_count
; i
++ ) {
1176 struct timeval msg_tv
;
1178 if (msg_ptr
+ 4 - buf
> len
) {
1179 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1183 msg_len
= IVAL(msg_ptr
,0);
1186 if (msg_ptr
+ msg_len
- buf
> len
) {
1187 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1191 /* unpack messages */
1193 ZERO_STRUCT( notify
);
1194 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1197 /* add to correct list in container */
1199 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1201 /* free memory that might have been allocated by notify2_unpack_msg() */
1203 if ( notify
.len
!= 0 )
1204 SAFE_FREE( notify
.notify
.data
);
1207 /* process each group of messages */
1209 num_groups
= notify_msg_ctr_numgroups( &messages
);
1210 for ( i
=0; i
<num_groups
; i
++ )
1211 send_notify2_changes( &messages
, i
);
1216 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1218 notify_msg_ctr_destroy( &messages
);
1223 /********************************************************************
1224 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1225 one smbd, all of processes must clear their printer cache immediately.
1226 ********************************************************************/
1228 void receive_printer_mod_msg(int msg_type
, pid_t src
, void *buf
, size_t len
)
1230 fstring printername
;
1232 fstrcpy( printername
, buf
);
1234 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername
));
1236 invalidate_printer_hnd_cache( printername
);
1239 /********************************************************************
1240 Send a message to ourself about new driver being installed
1241 so we can upgrade the information for each printer bound to this
1243 ********************************************************************/
1245 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
1247 int len
= strlen(drivername
);
1252 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1255 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
1260 /**********************************************************************
1261 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1262 over all printers, upgrading ones as necessary
1263 **********************************************************************/
1265 void do_drv_upgrade_printer(int msg_type
, pid_t src
, void *buf
, size_t len
)
1269 int n_services
= lp_numservices();
1271 len
= MIN(len
,sizeof(drivername
)-1);
1272 strncpy(drivername
, buf
, len
);
1274 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1276 /* Iterate the printer list */
1278 for (snum
=0; snum
<n_services
; snum
++)
1280 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1283 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1285 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1286 if (!W_ERROR_IS_OK(result
))
1289 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1291 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1293 /* all we care about currently is the change_id */
1295 result
= mod_a_printer(*printer
, 2);
1296 if (!W_ERROR_IS_OK(result
)) {
1297 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1298 dos_errstr(result
)));
1302 free_a_printer(&printer
, 2);
1309 /********************************************************************
1310 Update the cache for all printq's with a registered client
1312 ********************************************************************/
1314 void update_monitored_printq_cache( void )
1316 Printer_entry
*printer
= printers_list
;
1319 /* loop through all printers and update the cache where
1320 client_connected == True */
1323 if ( (printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
1324 && printer
->notify
.client_connected
)
1326 snum
= print_queue_snum(printer
->dev
.handlename
);
1327 print_queue_status( snum
, NULL
, NULL
);
1330 printer
= printer
->next
;
1335 /********************************************************************
1336 Send a message to ourself about new driver being installed
1337 so we can upgrade the information for each printer bound to this
1339 ********************************************************************/
1341 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1343 int len
= strlen(drivername
);
1348 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1351 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1356 /**********************************************************************
1357 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1358 over all printers, resetting printer data as neessary
1359 **********************************************************************/
1361 void reset_all_printerdata(int msg_type
, pid_t src
, void *buf
, size_t len
)
1365 int n_services
= lp_numservices();
1367 len
= MIN( len
, sizeof(drivername
)-1 );
1368 strncpy( drivername
, buf
, len
);
1370 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1372 /* Iterate the printer list */
1374 for ( snum
=0; snum
<n_services
; snum
++ )
1376 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1379 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1381 result
= get_a_printer( NULL
, &printer
, 2, lp_const_servicename(snum
) );
1382 if ( !W_ERROR_IS_OK(result
) )
1386 * if the printer is bound to the driver,
1387 * then reset to the new driver initdata
1390 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1392 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1394 if ( !set_driver_init(printer
, 2) ) {
1395 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1396 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1399 result
= mod_a_printer( *printer
, 2 );
1400 if ( !W_ERROR_IS_OK(result
) ) {
1401 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1402 get_dos_error_msg(result
)));
1406 free_a_printer( &printer
, 2 );
1415 /********************************************************************
1416 Copy routines used by convert_to_openprinterex()
1417 *******************************************************************/
1419 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1427 DEBUG (8,("dup_devmode\n"));
1429 /* bulk copy first */
1431 d
= talloc_memdup(ctx
, devmode
, sizeof(DEVICEMODE
));
1435 /* dup the pointer members separately */
1437 len
= unistrlen(devmode
->devicename
.buffer
);
1439 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1440 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1445 len
= unistrlen(devmode
->formname
.buffer
);
1447 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1448 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1452 d
->private = talloc_memdup(ctx
, devmode
->private, devmode
->driverextra
);
1457 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1459 if (!new_ctr
|| !ctr
)
1462 DEBUG(8,("copy_devmode_ctr\n"));
1464 new_ctr
->size
= ctr
->size
;
1465 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1467 if(ctr
->devmode_ptr
)
1468 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1471 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1473 if (!new_def
|| !def
)
1476 DEBUG(8,("copy_printer_defaults\n"));
1478 new_def
->datatype_ptr
= def
->datatype_ptr
;
1480 if (def
->datatype_ptr
)
1481 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1483 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1485 new_def
->access_required
= def
->access_required
;
1488 /********************************************************************
1489 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1490 * SPOOL_Q_OPEN_PRINTER_EX structure
1491 ********************************************************************/
1493 static void convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1495 if (!q_u_ex
|| !q_u
)
1498 DEBUG(8,("convert_to_openprinterex\n"));
1500 q_u_ex
->printername_ptr
= q_u
->printername_ptr
;
1502 if (q_u
->printername_ptr
)
1503 copy_unistr2(&q_u_ex
->printername
, &q_u
->printername
);
1505 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1508 /********************************************************************
1509 * spoolss_open_printer
1511 * called from the spoolss dispatcher
1512 ********************************************************************/
1514 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1516 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1517 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1522 ZERO_STRUCT(q_u_ex
);
1523 ZERO_STRUCT(r_u_ex
);
1525 /* convert the OpenPrinter() call to OpenPrinterEx() */
1527 convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1529 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1531 /* convert back to OpenPrinter() */
1533 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1538 /********************************************************************
1539 * spoolss_open_printer
1541 * If the openprinterex rpc call contains a devmode,
1542 * it's a per-user one. This per-user devmode is derivated
1543 * from the global devmode. Openprinterex() contains a per-user
1544 * devmode for when you do EMF printing and spooling.
1545 * In the EMF case, the NT workstation is only doing half the job
1546 * of rendering the page. The other half is done by running the printer
1547 * driver on the server.
1548 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1549 * The EMF file only contains what is to be printed on the page.
1550 * So in order for the server to know how to print, the NT client sends
1551 * a devicemode attached to the openprinterex call.
1552 * But this devicemode is short lived, it's only valid for the current print job.
1554 * If Samba would have supported EMF spooling, this devicemode would
1555 * have been attached to the handle, to sent it to the driver to correctly
1556 * rasterize the EMF file.
1558 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1559 * we just act as a pass-thru between windows and the printer.
1561 * In order to know that Samba supports only RAW spooling, NT has to call
1562 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1563 * and until NT sends a RAW job, we refuse it.
1565 * But to call getprinter() or startdoc(), you first need a valid handle,
1566 * and to get an handle you have to call openprintex(). Hence why you have
1567 * a devicemode in the openprinterex() call.
1570 * Differences between NT4 and NT 2000.
1573 * On NT4, you only have a global devicemode. This global devicemode can be changed
1574 * by the administrator (or by a user with enough privs). Everytime a user
1575 * wants to print, the devicemode is resetted to the default. In Word, everytime
1576 * you print, the printer's characteristics are always reset to the global devicemode.
1580 * In W2K, there is the notion of per-user devicemode. The first time you use
1581 * a printer, a per-user devicemode is build from the global devicemode.
1582 * If you change your per-user devicemode, it is saved in the registry, under the
1583 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1584 * printer preferences available.
1586 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1587 * on the General Tab of the printer properties windows.
1589 * To change the global devicemode: it's the "Printing Defaults..." button
1590 * on the Advanced Tab of the printer properties window.
1593 ********************************************************************/
1595 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1597 UNISTR2
*printername
= NULL
;
1598 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1599 POLICY_HND
*handle
= &r_u
->handle
;
1603 struct current_user user
;
1604 Printer_entry
*Printer
=NULL
;
1606 if (q_u
->printername_ptr
!= 0)
1607 printername
= &q_u
->printername
;
1609 if (printername
== NULL
)
1610 return WERR_INVALID_PRINTER_NAME
;
1612 /* some sanity check because you can open a printer or a print server */
1613 /* aka: \\server\printer or \\server */
1614 unistr2_to_ascii(name
, printername
, sizeof(name
)-1);
1616 DEBUGADD(3,("checking name: %s\n",name
));
1618 if (!open_printer_hnd(p
, handle
, name
, 0))
1619 return WERR_INVALID_PRINTER_NAME
;
1621 Printer
=find_printer_index_by_hnd(p
, handle
);
1623 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1624 Can't find printer handle we created for printer %s\n", name
));
1625 close_printer_handle(p
,handle
);
1626 return WERR_INVALID_PRINTER_NAME
;
1629 get_current_user(&user
, p
);
1632 * First case: the user is opening the print server:
1634 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1635 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1637 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1638 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1639 * or if the user is listed in the smb.conf printer admin parameter.
1641 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1642 * client view printer folder, but does not show the MSAPW.
1644 * Note: this test needs code to check access rights here too. Jeremy
1645 * could you look at this?
1647 * Second case: the user is opening a printer:
1648 * NT doesn't let us connect to a printer if the connecting user
1649 * doesn't have print permission.
1652 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1654 /* Printserver handles use global struct... */
1658 /* Map standard access rights to object specific access rights */
1660 se_map_standard(&printer_default
->access_required
,
1661 &printserver_std_mapping
);
1663 /* Deny any object specific bits that don't apply to print
1664 servers (i.e printer and job specific bits) */
1666 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1668 if (printer_default
->access_required
&
1669 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1670 DEBUG(3, ("access DENIED for non-printserver bits"));
1671 close_printer_handle(p
, handle
);
1672 return WERR_ACCESS_DENIED
;
1675 /* Allow admin access */
1677 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1679 if (!lp_ms_add_printer_wizard()) {
1680 close_printer_handle(p
, handle
);
1681 return WERR_ACCESS_DENIED
;
1684 /* if the user is not root and not a printer admin, then fail */
1687 && !user_in_list(uidtoname(user
.uid
), lp_printer_admin(snum
), user
.groups
, user
.ngroups
) )
1689 close_printer_handle(p
, handle
);
1690 return WERR_ACCESS_DENIED
;
1693 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1697 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1700 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1701 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1703 /* We fall through to return WERR_OK */
1708 /* NT doesn't let us connect to a printer if the connecting user
1709 doesn't have print permission. */
1711 if (!get_printer_snum(p
, handle
, &snum
)) {
1712 close_printer_handle(p
, handle
);
1716 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1718 /* map an empty access mask to the minimum access mask */
1719 if (printer_default
->access_required
== 0x0)
1720 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1723 * If we are not serving the printer driver for this printer,
1724 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1725 * will keep NT clients happy --jerry
1728 if (lp_use_client_driver(snum
)
1729 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1731 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1734 /* check smb.conf parameters and the the sec_desc */
1736 if (!user_ok(uidtoname(user
.uid
), snum
, user
.groups
, user
.ngroups
) || !print_access_check(&user
, snum
, printer_default
->access_required
)) {
1737 DEBUG(3, ("access DENIED for printer open\n"));
1738 close_printer_handle(p
, handle
);
1739 return WERR_ACCESS_DENIED
;
1742 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1743 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1744 close_printer_handle(p
, handle
);
1745 return WERR_ACCESS_DENIED
;
1748 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1749 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1751 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1753 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1754 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1758 Printer
->access_granted
= printer_default
->access_required
;
1761 * If the client sent a devmode in the OpenPrinter() call, then
1762 * save it here in case we get a job submission on this handle
1765 if ( (Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTSERVER
)
1766 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1768 convert_devicemode( Printer
->dev
.handlename
, q_u
->printer_default
.devmode_cont
.devmode
,
1769 &Printer
->nt_devmode
);
1772 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1773 optimization in Windows 2000 clients --jerry */
1775 if ( (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1776 && (RA_WIN2K
== get_remote_arch()) )
1778 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1779 sys_usleep( 500000 );
1785 /****************************************************************************
1786 ****************************************************************************/
1788 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1789 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1795 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
1804 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1805 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1811 printer
->info_3
=NULL
;
1812 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1816 printer
->info_6
=NULL
;
1817 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1827 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1828 NT_DEVICEMODE
**pp_nt_devmode
)
1830 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1833 * Ensure nt_devmode is a valid pointer
1834 * as we will be overwriting it.
1837 if (nt_devmode
== NULL
) {
1838 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1839 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1843 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1844 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1846 nt_devmode
->specversion
=devmode
->specversion
;
1847 nt_devmode
->driverversion
=devmode
->driverversion
;
1848 nt_devmode
->size
=devmode
->size
;
1849 nt_devmode
->fields
=devmode
->fields
;
1850 nt_devmode
->orientation
=devmode
->orientation
;
1851 nt_devmode
->papersize
=devmode
->papersize
;
1852 nt_devmode
->paperlength
=devmode
->paperlength
;
1853 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1854 nt_devmode
->scale
=devmode
->scale
;
1855 nt_devmode
->copies
=devmode
->copies
;
1856 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1857 nt_devmode
->printquality
=devmode
->printquality
;
1858 nt_devmode
->color
=devmode
->color
;
1859 nt_devmode
->duplex
=devmode
->duplex
;
1860 nt_devmode
->yresolution
=devmode
->yresolution
;
1861 nt_devmode
->ttoption
=devmode
->ttoption
;
1862 nt_devmode
->collate
=devmode
->collate
;
1864 nt_devmode
->logpixels
=devmode
->logpixels
;
1865 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1866 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1867 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1868 nt_devmode
->displayflags
=devmode
->displayflags
;
1869 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1870 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1871 nt_devmode
->icmintent
=devmode
->icmintent
;
1872 nt_devmode
->mediatype
=devmode
->mediatype
;
1873 nt_devmode
->dithertype
=devmode
->dithertype
;
1874 nt_devmode
->reserved1
=devmode
->reserved1
;
1875 nt_devmode
->reserved2
=devmode
->reserved2
;
1876 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1877 nt_devmode
->panningheight
=devmode
->panningheight
;
1880 * Only change private and driverextra if the incoming devmode
1881 * has a new one. JRA.
1884 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1885 SAFE_FREE(nt_devmode
->private);
1886 nt_devmode
->driverextra
=devmode
->driverextra
;
1887 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
1889 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1892 *pp_nt_devmode
= nt_devmode
;
1897 /********************************************************************
1898 * _spoolss_enddocprinter_internal.
1899 ********************************************************************/
1901 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1903 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1907 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1911 if (!get_printer_snum(p
, handle
, &snum
))
1914 Printer
->document_started
=False
;
1915 print_job_end(snum
, Printer
->jobid
,True
);
1916 /* error codes unhandled so far ... */
1921 /********************************************************************
1922 * api_spoolss_closeprinter
1923 ********************************************************************/
1925 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1927 POLICY_HND
*handle
= &q_u
->handle
;
1929 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1931 if (Printer
&& Printer
->document_started
)
1932 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1934 if (!close_printer_handle(p
, handle
))
1937 /* clear the returned printer handle. Observed behavior
1938 from Win2k server. Don't think this really matters.
1939 Previous code just copied the value of the closed
1942 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1947 /********************************************************************
1948 * api_spoolss_deleteprinter
1950 ********************************************************************/
1952 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1954 POLICY_HND
*handle
= &q_u
->handle
;
1955 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1958 if (Printer
&& Printer
->document_started
)
1959 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1961 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1963 result
= delete_printer_handle(p
, handle
);
1965 update_c_setprinter(False
);
1970 /*******************************************************************
1971 * static function to lookup the version id corresponding to an
1972 * long architecture string
1973 ******************************************************************/
1975 static int get_version_id (char * arch
)
1978 struct table_node archi_table
[]= {
1980 {"Windows 4.0", "WIN40", 0 },
1981 {"Windows NT x86", "W32X86", 2 },
1982 {"Windows NT R4000", "W32MIPS", 2 },
1983 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1984 {"Windows NT PowerPC", "W32PPC", 2 },
1988 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1990 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1991 return (archi_table
[i
].version
);
1997 /********************************************************************
1998 * _spoolss_deleteprinterdriver
1999 ********************************************************************/
2001 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
2005 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2006 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2008 struct current_user user
;
2010 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2012 get_current_user(&user
, p
);
2014 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2015 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2017 /* check that we have a valid driver name first */
2019 if ((version
=get_version_id(arch
)) == -1)
2020 return WERR_INVALID_ENVIRONMENT
;
2023 ZERO_STRUCT(info_win2k
);
2025 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
2027 /* try for Win2k driver if "Windows NT x86" */
2029 if ( version
== 2 ) {
2031 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2032 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2036 /* otherwise it was a failure */
2038 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2044 if (printer_driver_in_use(info
.info_3
)) {
2045 status
= WERR_PRINTER_DRIVER_IN_USE
;
2051 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2053 /* if we get to here, we now have 2 driver info structures to remove */
2054 /* remove the Win2k driver first*/
2056 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, False
);
2057 free_a_printer_driver( info_win2k
, 3 );
2059 /* this should not have failed---if it did, report to client */
2060 if ( !W_ERROR_IS_OK(status_win2k
) )
2065 status
= delete_printer_driver(info
.info_3
, &user
, version
, False
);
2067 /* if at least one of the deletes succeeded return OK */
2069 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2073 free_a_printer_driver( info
, 3 );
2078 /********************************************************************
2079 * spoolss_deleteprinterdriverex
2080 ********************************************************************/
2082 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
2086 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2087 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2089 uint32 flags
= q_u
->delete_flags
;
2091 struct current_user user
;
2093 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2095 get_current_user(&user
, p
);
2097 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2098 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2100 /* check that we have a valid driver name first */
2101 if ((version
=get_version_id(arch
)) == -1) {
2102 /* this is what NT returns */
2103 return WERR_INVALID_ENVIRONMENT
;
2106 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2107 version
= q_u
->version
;
2110 ZERO_STRUCT(info_win2k
);
2112 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2114 if ( !W_ERROR_IS_OK(status
) )
2117 * if the client asked for a specific version,
2118 * or this is something other than Windows NT x86,
2122 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2125 /* try for Win2k driver if "Windows NT x86" */
2128 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2129 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2134 if ( printer_driver_in_use(info
.info_3
) ) {
2135 status
= WERR_PRINTER_DRIVER_IN_USE
;
2140 * we have a couple of cases to consider.
2141 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2142 * then the delete should fail if **any** files overlap with
2144 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2145 * non-overlapping files
2146 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2147 * is set, the do not delete any files
2148 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2151 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2153 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2155 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2156 /* no idea of the correct error here */
2157 status
= WERR_ACCESS_DENIED
;
2162 /* also check for W32X86/3 if necessary; maybe we already have? */
2164 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2165 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2168 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2169 /* no idea of the correct error here */
2170 free_a_printer_driver( info_win2k
, 3 );
2171 status
= WERR_ACCESS_DENIED
;
2175 /* if we get to here, we now have 2 driver info structures to remove */
2176 /* remove the Win2k driver first*/
2178 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, delete_files
);
2179 free_a_printer_driver( info_win2k
, 3 );
2181 /* this should not have failed---if it did, report to client */
2183 if ( !W_ERROR_IS_OK(status_win2k
) )
2188 status
= delete_printer_driver(info
.info_3
, &user
, version
, delete_files
);
2190 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2193 free_a_printer_driver( info
, 3 );
2199 /****************************************************************************
2200 Internal routine for retreiving printerdata
2201 ***************************************************************************/
2203 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2204 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2205 uint32
*needed
, uint32 in_size
)
2207 REGISTRY_VALUE
*val
;
2210 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2211 return WERR_BADFILE
;
2213 *type
= regval_type( val
);
2215 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2217 size
= regval_size( val
);
2219 /* copy the min(in_size, len) */
2222 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2224 /* special case for 0 length values */
2226 if ( (*data
= (uint8
*)talloc_memdup(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2230 if ( (*data
= (uint8
*)talloc_zero(ctx
, in_size
)) == NULL
)
2239 DEBUG(5,("get_printer_dataex: copy done\n"));
2244 /****************************************************************************
2245 Internal routine for removing printerdata
2246 ***************************************************************************/
2248 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2250 return delete_printer_data( printer
->info_2
, key
, value
);
2253 /****************************************************************************
2254 Internal routine for storing printerdata
2255 ***************************************************************************/
2257 static WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2258 uint32 type
, uint8
*data
, int real_len
)
2260 delete_printer_data( printer
->info_2
, key
, value
);
2262 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2265 /********************************************************************
2266 GetPrinterData on a printer server Handle.
2267 ********************************************************************/
2269 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2273 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2275 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2277 if((*data
= (uint8
*)talloc_zero(ctx
, 4*sizeof(uint8
) )) == NULL
)
2283 if (!StrCaseCmp(value
, "BeepEnabled")) {
2285 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2287 SIVAL(*data
, 0, 0x00);
2292 if (!StrCaseCmp(value
, "EventLog")) {
2294 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2296 /* formally was 0x1b */
2297 SIVAL(*data
, 0, 0x0);
2302 if (!StrCaseCmp(value
, "NetPopup")) {
2304 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2306 SIVAL(*data
, 0, 0x00);
2311 if (!StrCaseCmp(value
, "MajorVersion")) {
2313 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2316 /* Windows NT 4.0 seems to not allow uploading of drivers
2317 to a server that reports 0x3 as the MajorVersion.
2318 need to investigate more how Win2k gets around this .
2321 if ( RA_WINNT
== get_remote_arch() )
2330 if (!StrCaseCmp(value
, "MinorVersion")) {
2332 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2340 * uint32 size = 0x114
2342 * uint32 minor = [0|1]
2343 * uint32 build = [2195|2600]
2344 * extra unicode string = e.g. "Service Pack 3"
2346 if (!StrCaseCmp(value
, "OSVersion")) {
2350 if((*data
= (uint8
*)talloc(ctx
, (*needed
)*sizeof(uint8
) )) == NULL
)
2352 ZERO_STRUCTP( *data
);
2354 SIVAL(*data
, 0, *needed
); /* size */
2355 SIVAL(*data
, 4, 5); /* Windows 2000 == 5.0 */
2357 SIVAL(*data
, 12, 2195); /* build */
2359 /* leave extra string empty */
2365 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2366 const char *string
="C:\\PRINTERS";
2368 *needed
= 2*(strlen(string
)+1);
2369 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2371 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2373 /* it's done by hand ready to go on the wire */
2374 for (i
=0; i
<strlen(string
); i
++) {
2375 (*data
)[2*i
]=string
[i
];
2376 (*data
)[2*i
+1]='\0';
2381 if (!StrCaseCmp(value
, "Architecture")) {
2382 const char *string
="Windows NT x86";
2384 *needed
= 2*(strlen(string
)+1);
2385 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2387 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2388 for (i
=0; i
<strlen(string
); i
++) {
2389 (*data
)[2*i
]=string
[i
];
2390 (*data
)[2*i
+1]='\0';
2395 if (!StrCaseCmp(value
, "DsPresent")) {
2397 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2399 SIVAL(*data
, 0, 0x01);
2404 if (!StrCaseCmp(value
, "DNSMachineName")) {
2407 if (!get_mydnsfullname(hostname
))
2408 return WERR_BADFILE
;
2410 *needed
= 2*(strlen(hostname
)+1);
2411 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2413 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2414 for (i
=0; i
<strlen(hostname
); i
++) {
2415 (*data
)[2*i
]=hostname
[i
];
2416 (*data
)[2*i
+1]='\0';
2422 return WERR_BADFILE
;
2425 /********************************************************************
2426 * spoolss_getprinterdata
2427 ********************************************************************/
2429 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2431 POLICY_HND
*handle
= &q_u
->handle
;
2432 UNISTR2
*valuename
= &q_u
->valuename
;
2433 uint32 in_size
= q_u
->size
;
2434 uint32
*type
= &r_u
->type
;
2435 uint32
*out_size
= &r_u
->size
;
2436 uint8
**data
= &r_u
->data
;
2437 uint32
*needed
= &r_u
->needed
;
2440 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2441 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2445 * Reminder: when it's a string, the length is in BYTES
2446 * even if UNICODE is negociated.
2451 *out_size
= in_size
;
2453 /* in case of problem, return some default values */
2458 DEBUG(4,("_spoolss_getprinterdata\n"));
2461 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2462 status
= WERR_BADFID
;
2466 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2468 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2469 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2472 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2473 status
= WERR_BADFID
;
2477 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
2478 if ( !W_ERROR_IS_OK(status
) )
2481 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2483 if ( strequal(value
, "ChangeId") ) {
2485 *needed
= sizeof(uint32
);
2486 if ( (*data
= (uint8
*)talloc(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2487 status
= WERR_NOMEM
;
2490 SIVAL( *data
, 0, printer
->info_2
->changeid
);
2494 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2497 if (*needed
> *out_size
)
2498 status
= WERR_MORE_DATA
;
2501 if ( !W_ERROR_IS_OK(status
) )
2503 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2505 /* reply this param doesn't exist */
2508 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
2510 free_a_printer( &printer
, 2 );
2519 /* cleanup & exit */
2522 free_a_printer( &printer
, 2 );
2527 /*********************************************************
2528 Connect to the client machine.
2529 **********************************************************/
2531 static BOOL
spoolss_connect_to_client(struct cli_state
*the_cli
,
2532 struct in_addr
*client_ip
, const char *remote_machine
)
2534 ZERO_STRUCTP(the_cli
);
2536 if(cli_initialise(the_cli
) == NULL
) {
2537 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2541 if ( is_zero_ip(*client_ip
) ) {
2542 if(!resolve_name( remote_machine
, &the_cli
->dest_ip
, 0x20)) {
2543 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2544 cli_shutdown(the_cli
);
2548 if (ismyip(the_cli
->dest_ip
)) {
2549 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2550 cli_shutdown(the_cli
);
2555 the_cli
->dest_ip
.s_addr
= client_ip
->s_addr
;
2556 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2557 inet_ntoa(*client_ip
) ));
2560 if (!cli_connect(the_cli
, remote_machine
, &the_cli
->dest_ip
)) {
2561 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
) ));
2562 cli_shutdown(the_cli
);
2566 if (!attempt_netbios_session_request(the_cli
, global_myname(), remote_machine
, &the_cli
->dest_ip
)) {
2567 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2569 cli_shutdown(the_cli
);
2573 the_cli
->protocol
= PROTOCOL_NT1
;
2574 cli_setup_signing_state(the_cli
, lp_client_signing());
2576 if (!cli_negprot(the_cli
)) {
2577 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2578 cli_shutdown(the_cli
);
2582 if (the_cli
->protocol
!= PROTOCOL_NT1
) {
2583 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2584 cli_shutdown(the_cli
);
2589 * Do an anonymous session setup.
2592 if (!cli_session_setup(the_cli
, "", "", 0, "", 0, "")) {
2593 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2594 cli_shutdown(the_cli
);
2598 if (!(the_cli
->sec_mode
& 1)) {
2599 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine
));
2600 cli_shutdown(the_cli
);
2604 if (!cli_send_tconX(the_cli
, "IPC$", "IPC", "", 1)) {
2605 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
) ));
2606 cli_shutdown(the_cli
);
2611 * Ok - we have an anonymous connection to the IPC$ share.
2612 * Now start the NT Domain stuff :-).
2615 if(cli_nt_session_open(the_cli
, PI_SPOOLSS
) == False
) {
2616 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
)));
2617 cli_nt_session_close(the_cli
);
2618 cli_ulogoff(the_cli
);
2619 cli_shutdown(the_cli
);
2626 /***************************************************************************
2627 Connect to the client.
2628 ****************************************************************************/
2630 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2631 uint32 localprinter
, uint32 type
,
2632 POLICY_HND
*handle
, struct in_addr
*client_ip
)
2637 * If it's the first connection, contact the client
2638 * and connect to the IPC$ share anonymously
2640 if (smb_connections
==0) {
2641 fstring unix_printer
;
2643 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2645 ZERO_STRUCT(notify_cli
);
2647 if(!spoolss_connect_to_client(¬ify_cli
, client_ip
, unix_printer
))
2650 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message_list
);
2651 /* Tell the connections db we're now interested in printer
2652 * notify messages. */
2653 register_message_flags( True
, FLAG_MSG_PRINT_NOTIFY
);
2657 * Tell the specific printing tdb we want messages for this printer
2658 * by registering our PID.
2661 if (!print_notify_register_pid(snum
))
2662 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2666 result
= cli_spoolss_reply_open_printer(¬ify_cli
, notify_cli
.mem_ctx
, printer
, localprinter
,
2669 if (!W_ERROR_IS_OK(result
))
2670 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2671 dos_errstr(result
)));
2673 return (W_ERROR_IS_OK(result
));
2676 /********************************************************************
2678 * ReplyFindFirstPrinterChangeNotifyEx
2680 * before replying OK: status=0 a rpc call is made to the workstation
2681 * asking ReplyOpenPrinter
2683 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2684 * called from api_spoolss_rffpcnex
2685 ********************************************************************/
2687 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2689 POLICY_HND
*handle
= &q_u
->handle
;
2690 uint32 flags
= q_u
->flags
;
2691 uint32 options
= q_u
->options
;
2692 UNISTR2
*localmachine
= &q_u
->localmachine
;
2693 uint32 printerlocal
= q_u
->printerlocal
;
2695 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2696 struct in_addr client_ip
;
2698 /* store the notify value in the printer struct */
2700 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2703 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2707 Printer
->notify
.flags
=flags
;
2708 Printer
->notify
.options
=options
;
2709 Printer
->notify
.printerlocal
=printerlocal
;
2711 if (Printer
->notify
.option
)
2712 free_spool_notify_option(&Printer
->notify
.option
);
2714 Printer
->notify
.option
=dup_spool_notify_option(option
);
2716 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2717 sizeof(Printer
->notify
.localmachine
)-1);
2719 /* Connect to the client machine and send a ReplyOpenPrinter */
2721 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2723 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
2724 !get_printer_snum(p
, handle
, &snum
) )
2727 client_ip
.s_addr
= inet_addr(p
->conn
->client_address
);
2729 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2730 Printer
->notify
.printerlocal
, 1,
2731 &Printer
->notify
.client_hnd
, &client_ip
))
2732 return WERR_SERVER_UNAVAILABLE
;
2734 Printer
->notify
.client_connected
=True
;
2739 /*******************************************************************
2740 * fill a notify_info_data with the servername
2741 ********************************************************************/
2743 void spoolss_notify_server_name(int snum
,
2744 SPOOL_NOTIFY_INFO_DATA
*data
,
2745 print_queue_struct
*queue
,
2746 NT_PRINTER_INFO_LEVEL
*printer
,
2747 TALLOC_CTX
*mem_ctx
)
2749 pstring temp_name
, temp
;
2752 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
2754 len
= rpcstr_push(temp
, temp_name
, sizeof(temp
)-2, STR_TERMINATE
);
2756 data
->notify_data
.data
.length
= len
;
2757 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2759 if (!data
->notify_data
.data
.string
) {
2760 data
->notify_data
.data
.length
= 0;
2764 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2767 /*******************************************************************
2768 * fill a notify_info_data with the printername (not including the servername).
2769 ********************************************************************/
2771 void spoolss_notify_printer_name(int snum
,
2772 SPOOL_NOTIFY_INFO_DATA
*data
,
2773 print_queue_struct
*queue
,
2774 NT_PRINTER_INFO_LEVEL
*printer
,
2775 TALLOC_CTX
*mem_ctx
)
2780 /* the notify name should not contain the \\server\ part */
2781 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2784 p
= printer
->info_2
->printername
;
2789 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2791 data
->notify_data
.data
.length
= len
;
2792 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2794 if (!data
->notify_data
.data
.string
) {
2795 data
->notify_data
.data
.length
= 0;
2799 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2802 /*******************************************************************
2803 * fill a notify_info_data with the servicename
2804 ********************************************************************/
2806 void spoolss_notify_share_name(int snum
,
2807 SPOOL_NOTIFY_INFO_DATA
*data
,
2808 print_queue_struct
*queue
,
2809 NT_PRINTER_INFO_LEVEL
*printer
,
2810 TALLOC_CTX
*mem_ctx
)
2815 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2817 data
->notify_data
.data
.length
= len
;
2818 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2820 if (!data
->notify_data
.data
.string
) {
2821 data
->notify_data
.data
.length
= 0;
2825 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2828 /*******************************************************************
2829 * fill a notify_info_data with the port name
2830 ********************************************************************/
2832 void spoolss_notify_port_name(int snum
,
2833 SPOOL_NOTIFY_INFO_DATA
*data
,
2834 print_queue_struct
*queue
,
2835 NT_PRINTER_INFO_LEVEL
*printer
,
2836 TALLOC_CTX
*mem_ctx
)
2841 /* even if it's strange, that's consistant in all the code */
2843 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2845 data
->notify_data
.data
.length
= len
;
2846 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2848 if (!data
->notify_data
.data
.string
) {
2849 data
->notify_data
.data
.length
= 0;
2853 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2856 /*******************************************************************
2857 * fill a notify_info_data with the printername
2858 * but it doesn't exist, have to see what to do
2859 ********************************************************************/
2861 void spoolss_notify_driver_name(int snum
,
2862 SPOOL_NOTIFY_INFO_DATA
*data
,
2863 print_queue_struct
*queue
,
2864 NT_PRINTER_INFO_LEVEL
*printer
,
2865 TALLOC_CTX
*mem_ctx
)
2870 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, 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 comment
2885 ********************************************************************/
2887 void spoolss_notify_comment(int snum
,
2888 SPOOL_NOTIFY_INFO_DATA
*data
,
2889 print_queue_struct
*queue
,
2890 NT_PRINTER_INFO_LEVEL
*printer
,
2891 TALLOC_CTX
*mem_ctx
)
2896 if (*printer
->info_2
->comment
== '\0')
2897 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2899 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2901 data
->notify_data
.data
.length
= len
;
2902 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2904 if (!data
->notify_data
.data
.string
) {
2905 data
->notify_data
.data
.length
= 0;
2909 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2912 /*******************************************************************
2913 * fill a notify_info_data with the comment
2914 * location = "Room 1, floor 2, building 3"
2915 ********************************************************************/
2917 void spoolss_notify_location(int snum
,
2918 SPOOL_NOTIFY_INFO_DATA
*data
,
2919 print_queue_struct
*queue
,
2920 NT_PRINTER_INFO_LEVEL
*printer
,
2921 TALLOC_CTX
*mem_ctx
)
2926 len
= rpcstr_push(temp
, printer
->info_2
->location
,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 device mode
2941 * jfm:xxxx don't to it for know but that's a real problem !!!
2942 ********************************************************************/
2944 static void spoolss_notify_devmode(int snum
,
2945 SPOOL_NOTIFY_INFO_DATA
*data
,
2946 print_queue_struct
*queue
,
2947 NT_PRINTER_INFO_LEVEL
*printer
,
2948 TALLOC_CTX
*mem_ctx
)
2952 /*******************************************************************
2953 * fill a notify_info_data with the separator file name
2954 ********************************************************************/
2956 void spoolss_notify_sepfile(int snum
,
2957 SPOOL_NOTIFY_INFO_DATA
*data
,
2958 print_queue_struct
*queue
,
2959 NT_PRINTER_INFO_LEVEL
*printer
,
2960 TALLOC_CTX
*mem_ctx
)
2965 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2967 data
->notify_data
.data
.length
= len
;
2968 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2970 if (!data
->notify_data
.data
.string
) {
2971 data
->notify_data
.data
.length
= 0;
2975 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2978 /*******************************************************************
2979 * fill a notify_info_data with the print processor
2980 * jfm:xxxx return always winprint to indicate we don't do anything to it
2981 ********************************************************************/
2983 void spoolss_notify_print_processor(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
->printprocessor
, 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 options
3007 * jfm:xxxx send an empty string
3008 ********************************************************************/
3010 void spoolss_notify_parameters(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
->parameters
, 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 data type
3034 * jfm:xxxx always send RAW as data type
3035 ********************************************************************/
3037 void spoolss_notify_datatype(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
->datatype
, sizeof(pstring
)-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 security descriptor
3061 * jfm:xxxx send an null pointer to say no security desc
3062 * have to implement security before !
3063 ********************************************************************/
3065 static void spoolss_notify_security_desc(int snum
,
3066 SPOOL_NOTIFY_INFO_DATA
*data
,
3067 print_queue_struct
*queue
,
3068 NT_PRINTER_INFO_LEVEL
*printer
,
3069 TALLOC_CTX
*mem_ctx
)
3071 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
3072 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
3075 /*******************************************************************
3076 * fill a notify_info_data with the attributes
3077 * jfm:xxxx a samba printer is always shared
3078 ********************************************************************/
3080 void spoolss_notify_attributes(int snum
,
3081 SPOOL_NOTIFY_INFO_DATA
*data
,
3082 print_queue_struct
*queue
,
3083 NT_PRINTER_INFO_LEVEL
*printer
,
3084 TALLOC_CTX
*mem_ctx
)
3086 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
3087 data
->notify_data
.value
[1] = 0;
3090 /*******************************************************************
3091 * fill a notify_info_data with the priority
3092 ********************************************************************/
3094 static void spoolss_notify_priority(int snum
,
3095 SPOOL_NOTIFY_INFO_DATA
*data
,
3096 print_queue_struct
*queue
,
3097 NT_PRINTER_INFO_LEVEL
*printer
,
3098 TALLOC_CTX
*mem_ctx
)
3100 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
3101 data
->notify_data
.value
[1] = 0;
3104 /*******************************************************************
3105 * fill a notify_info_data with the default priority
3106 ********************************************************************/
3108 static void spoolss_notify_default_priority(int snum
,
3109 SPOOL_NOTIFY_INFO_DATA
*data
,
3110 print_queue_struct
*queue
,
3111 NT_PRINTER_INFO_LEVEL
*printer
,
3112 TALLOC_CTX
*mem_ctx
)
3114 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
3115 data
->notify_data
.value
[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the start time
3120 ********************************************************************/
3122 static void spoolss_notify_start_time(int snum
,
3123 SPOOL_NOTIFY_INFO_DATA
*data
,
3124 print_queue_struct
*queue
,
3125 NT_PRINTER_INFO_LEVEL
*printer
,
3126 TALLOC_CTX
*mem_ctx
)
3128 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
3129 data
->notify_data
.value
[1] = 0;
3132 /*******************************************************************
3133 * fill a notify_info_data with the until time
3134 ********************************************************************/
3136 static void spoolss_notify_until_time(int snum
,
3137 SPOOL_NOTIFY_INFO_DATA
*data
,
3138 print_queue_struct
*queue
,
3139 NT_PRINTER_INFO_LEVEL
*printer
,
3140 TALLOC_CTX
*mem_ctx
)
3142 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
3143 data
->notify_data
.value
[1] = 0;
3146 /*******************************************************************
3147 * fill a notify_info_data with the status
3148 ********************************************************************/
3150 static void spoolss_notify_status(int snum
,
3151 SPOOL_NOTIFY_INFO_DATA
*data
,
3152 print_queue_struct
*queue
,
3153 NT_PRINTER_INFO_LEVEL
*printer
,
3154 TALLOC_CTX
*mem_ctx
)
3156 print_status_struct status
;
3158 print_queue_length(snum
, &status
);
3159 data
->notify_data
.value
[0]=(uint32
) status
.status
;
3160 data
->notify_data
.value
[1] = 0;
3163 /*******************************************************************
3164 * fill a notify_info_data with the number of jobs queued
3165 ********************************************************************/
3167 void spoolss_notify_cjobs(int snum
,
3168 SPOOL_NOTIFY_INFO_DATA
*data
,
3169 print_queue_struct
*queue
,
3170 NT_PRINTER_INFO_LEVEL
*printer
,
3171 TALLOC_CTX
*mem_ctx
)
3173 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3174 data
->notify_data
.value
[1] = 0;
3177 /*******************************************************************
3178 * fill a notify_info_data with the average ppm
3179 ********************************************************************/
3181 static void spoolss_notify_average_ppm(int snum
,
3182 SPOOL_NOTIFY_INFO_DATA
*data
,
3183 print_queue_struct
*queue
,
3184 NT_PRINTER_INFO_LEVEL
*printer
,
3185 TALLOC_CTX
*mem_ctx
)
3187 /* always respond 8 pages per minutes */
3188 /* a little hard ! */
3189 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3190 data
->notify_data
.value
[1] = 0;
3193 /*******************************************************************
3194 * fill a notify_info_data with username
3195 ********************************************************************/
3197 static void spoolss_notify_username(int snum
,
3198 SPOOL_NOTIFY_INFO_DATA
*data
,
3199 print_queue_struct
*queue
,
3200 NT_PRINTER_INFO_LEVEL
*printer
,
3201 TALLOC_CTX
*mem_ctx
)
3206 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3208 data
->notify_data
.data
.length
= len
;
3209 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3211 if (!data
->notify_data
.data
.string
) {
3212 data
->notify_data
.data
.length
= 0;
3216 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3219 /*******************************************************************
3220 * fill a notify_info_data with job status
3221 ********************************************************************/
3223 static void spoolss_notify_job_status(int snum
,
3224 SPOOL_NOTIFY_INFO_DATA
*data
,
3225 print_queue_struct
*queue
,
3226 NT_PRINTER_INFO_LEVEL
*printer
,
3227 TALLOC_CTX
*mem_ctx
)
3229 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3230 data
->notify_data
.value
[1] = 0;
3233 /*******************************************************************
3234 * fill a notify_info_data with job name
3235 ********************************************************************/
3237 static void spoolss_notify_job_name(int snum
,
3238 SPOOL_NOTIFY_INFO_DATA
*data
,
3239 print_queue_struct
*queue
,
3240 NT_PRINTER_INFO_LEVEL
*printer
,
3241 TALLOC_CTX
*mem_ctx
)
3246 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3248 data
->notify_data
.data
.length
= len
;
3249 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3251 if (!data
->notify_data
.data
.string
) {
3252 data
->notify_data
.data
.length
= 0;
3256 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3259 /*******************************************************************
3260 * fill a notify_info_data with job status
3261 ********************************************************************/
3263 static void spoolss_notify_job_status_string(int snum
,
3264 SPOOL_NOTIFY_INFO_DATA
*data
,
3265 print_queue_struct
*queue
,
3266 NT_PRINTER_INFO_LEVEL
*printer
,
3267 TALLOC_CTX
*mem_ctx
)
3270 * Now we're returning job status codes we just return a "" here. JRA.
3277 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3280 switch (queue
->status
) {
3285 p
= ""; /* NT provides the paused string */
3294 #endif /* NO LONGER NEEDED. */
3296 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3298 data
->notify_data
.data
.length
= len
;
3299 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3301 if (!data
->notify_data
.data
.string
) {
3302 data
->notify_data
.data
.length
= 0;
3306 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3309 /*******************************************************************
3310 * fill a notify_info_data with job time
3311 ********************************************************************/
3313 static void spoolss_notify_job_time(int snum
,
3314 SPOOL_NOTIFY_INFO_DATA
*data
,
3315 print_queue_struct
*queue
,
3316 NT_PRINTER_INFO_LEVEL
*printer
,
3317 TALLOC_CTX
*mem_ctx
)
3319 data
->notify_data
.value
[0]=0x0;
3320 data
->notify_data
.value
[1]=0;
3323 /*******************************************************************
3324 * fill a notify_info_data with job size
3325 ********************************************************************/
3327 static void spoolss_notify_job_size(int snum
,
3328 SPOOL_NOTIFY_INFO_DATA
*data
,
3329 print_queue_struct
*queue
,
3330 NT_PRINTER_INFO_LEVEL
*printer
,
3331 TALLOC_CTX
*mem_ctx
)
3333 data
->notify_data
.value
[0]=queue
->size
;
3334 data
->notify_data
.value
[1]=0;
3337 /*******************************************************************
3338 * fill a notify_info_data with page info
3339 ********************************************************************/
3340 static void spoolss_notify_total_pages(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]=queue
->page_count
;
3347 data
->notify_data
.value
[1]=0;
3350 /*******************************************************************
3351 * fill a notify_info_data with pages printed info.
3352 ********************************************************************/
3353 static void spoolss_notify_pages_printed(int snum
,
3354 SPOOL_NOTIFY_INFO_DATA
*data
,
3355 print_queue_struct
*queue
,
3356 NT_PRINTER_INFO_LEVEL
*printer
,
3357 TALLOC_CTX
*mem_ctx
)
3359 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3360 data
->notify_data
.value
[1]=0;
3363 /*******************************************************************
3364 Fill a notify_info_data with job position.
3365 ********************************************************************/
3367 static void spoolss_notify_job_position(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
->job
;
3374 data
->notify_data
.value
[1]=0;
3377 /*******************************************************************
3378 Fill a notify_info_data with submitted time.
3379 ********************************************************************/
3381 static void spoolss_notify_submitted_time(int snum
,
3382 SPOOL_NOTIFY_INFO_DATA
*data
,
3383 print_queue_struct
*queue
,
3384 NT_PRINTER_INFO_LEVEL
*printer
,
3385 TALLOC_CTX
*mem_ctx
)
3392 t
=gmtime(&queue
->time
);
3394 len
= sizeof(SYSTEMTIME
);
3396 data
->notify_data
.data
.length
= len
;
3397 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3399 if (!data
->notify_data
.data
.string
) {
3400 data
->notify_data
.data
.length
= 0;
3404 make_systemtime(&st
, t
);
3407 * Systemtime must be linearized as a set of UINT16's.
3408 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3411 p
= (char *)data
->notify_data
.data
.string
;
3412 SSVAL(p
, 0, st
.year
);
3413 SSVAL(p
, 2, st
.month
);
3414 SSVAL(p
, 4, st
.dayofweek
);
3415 SSVAL(p
, 6, st
.day
);
3416 SSVAL(p
, 8, st
.hour
);
3417 SSVAL(p
, 10, st
.minute
);
3418 SSVAL(p
, 12, st
.second
);
3419 SSVAL(p
, 14, st
.milliseconds
);
3422 struct s_notify_info_data_table
3428 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3429 print_queue_struct
*queue
,
3430 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3433 /* A table describing the various print notification constants and
3434 whether the notification data is a pointer to a variable sized
3435 buffer, a one value uint32 or a two value uint32. */
3437 static const struct s_notify_info_data_table notify_info_data_table
[] =
3439 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3440 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3441 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3442 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3443 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3444 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3445 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3446 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3447 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3448 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3449 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3450 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3451 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3452 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3453 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3454 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3455 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3456 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3457 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3458 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3459 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3460 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3461 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3462 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3463 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3464 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3465 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3466 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3467 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3468 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3469 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3470 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3471 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3472 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3473 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3474 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3475 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3476 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3477 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3478 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3479 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3480 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3481 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3482 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3483 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3484 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3485 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3486 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3487 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3490 /*******************************************************************
3491 Return the size of info_data structure.
3492 ********************************************************************/
3494 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3498 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++)
3500 if ( (notify_info_data_table
[i
].type
== type
)
3501 && (notify_info_data_table
[i
].field
== field
) )
3503 switch(notify_info_data_table
[i
].size
)
3505 case NOTIFY_ONE_VALUE
:
3506 case NOTIFY_TWO_VALUE
:
3511 /* The only pointer notify data I have seen on
3512 the wire is the submitted time and this has
3513 the notify size set to 4. -tpot */
3515 case NOTIFY_POINTER
:
3518 case NOTIFY_SECDESC
:
3524 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3529 /*******************************************************************
3530 Return the type of notify_info_data.
3531 ********************************************************************/
3533 static int type_of_notify_info_data(uint16 type
, uint16 field
)
3537 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3538 if (notify_info_data_table
[i
].type
== type
&&
3539 notify_info_data_table
[i
].field
== field
)
3540 return notify_info_data_table
[i
].size
;
3546 /****************************************************************************
3547 ****************************************************************************/
3549 static int search_notify(uint16 type
, uint16 field
, int *value
)
3553 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3554 if (notify_info_data_table
[i
].type
== type
&&
3555 notify_info_data_table
[i
].field
== field
&&
3556 notify_info_data_table
[i
].fn
!= NULL
) {
3565 /****************************************************************************
3566 ****************************************************************************/
3568 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3570 info_data
->type
= type
;
3571 info_data
->field
= field
;
3572 info_data
->reserved
= 0;
3574 info_data
->size
= size_of_notify_info_data(type
, field
);
3575 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3582 /*******************************************************************
3584 * fill a notify_info struct with info asked
3586 ********************************************************************/
3588 static BOOL
construct_notify_printer_info(Printer_entry
*print_hnd
, SPOOL_NOTIFY_INFO
*info
, int
3589 snum
, SPOOL_NOTIFY_OPTION_TYPE
3590 *option_type
, uint32 id
,
3591 TALLOC_CTX
*mem_ctx
)
3597 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3598 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3599 print_queue_struct
*queue
=NULL
;
3601 type
=option_type
->type
;
3603 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3604 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3605 option_type
->count
, lp_servicename(snum
)));
3607 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3610 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3611 field
= option_type
->fields
[field_num
];
3613 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3615 if (!search_notify(type
, field
, &j
) )
3618 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
3619 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3624 current_data
= &info
->data
[info
->count
];
3626 construct_info_data(current_data
, type
, field
, id
);
3628 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3629 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3631 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3637 free_a_printer(&printer
, 2);
3641 /*******************************************************************
3643 * fill a notify_info struct with info asked
3645 ********************************************************************/
3647 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3648 SPOOL_NOTIFY_INFO
*info
,
3649 NT_PRINTER_INFO_LEVEL
*printer
,
3650 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3651 *option_type
, uint32 id
,
3652 TALLOC_CTX
*mem_ctx
)
3658 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3660 DEBUG(4,("construct_notify_jobs_info\n"));
3662 type
= option_type
->type
;
3664 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3665 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3666 option_type
->count
));
3668 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3669 field
= option_type
->fields
[field_num
];
3671 if (!search_notify(type
, field
, &j
) )
3674 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
3675 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3678 else info
->data
= tid
;
3680 current_data
=&(info
->data
[info
->count
]);
3682 construct_info_data(current_data
, type
, field
, id
);
3683 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3692 * JFM: The enumeration is not that simple, it's even non obvious.
3694 * let's take an example: I want to monitor the PRINTER SERVER for
3695 * the printer's name and the number of jobs currently queued.
3696 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3697 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3699 * I have 3 printers on the back of my server.
3701 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3704 * 1 printer 1 name 1
3705 * 2 printer 1 cjob 1
3706 * 3 printer 2 name 2
3707 * 4 printer 2 cjob 2
3708 * 5 printer 3 name 3
3709 * 6 printer 3 name 3
3711 * that's the print server case, the printer case is even worse.
3714 /*******************************************************************
3716 * enumerate all printers on the printserver
3717 * fill a notify_info struct with info asked
3719 ********************************************************************/
3721 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3722 SPOOL_NOTIFY_INFO
*info
,
3723 TALLOC_CTX
*mem_ctx
)
3726 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3727 int n_services
=lp_numservices();
3729 SPOOL_NOTIFY_OPTION
*option
;
3730 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3732 DEBUG(4,("printserver_notify_info\n"));
3737 option
=Printer
->notify
.option
;
3742 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3743 sending a ffpcn() request first */
3748 for (i
=0; i
<option
->count
; i
++) {
3749 option_type
=&(option
->ctr
.type
[i
]);
3751 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3754 for (snum
=0; snum
<n_services
; snum
++)
3756 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3757 construct_notify_printer_info ( Printer
, info
, snum
, option_type
, snum
, mem_ctx
);
3763 * Debugging information, don't delete.
3766 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3767 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3768 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3770 for (i
=0; i
<info
->count
; i
++) {
3771 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3772 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3773 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3780 /*******************************************************************
3782 * fill a notify_info struct with info asked
3784 ********************************************************************/
3786 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3787 TALLOC_CTX
*mem_ctx
)
3790 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3793 SPOOL_NOTIFY_OPTION
*option
;
3794 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3796 print_queue_struct
*queue
=NULL
;
3797 print_status_struct status
;
3799 DEBUG(4,("printer_notify_info\n"));
3804 option
=Printer
->notify
.option
;
3810 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3811 sending a ffpcn() request first */
3816 get_printer_snum(p
, hnd
, &snum
);
3818 for (i
=0; i
<option
->count
; i
++) {
3819 option_type
=&option
->ctr
.type
[i
];
3821 switch ( option_type
->type
) {
3822 case PRINTER_NOTIFY_TYPE
:
3823 if(construct_notify_printer_info(Printer
, info
, snum
,
3829 case JOB_NOTIFY_TYPE
: {
3830 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3832 count
= print_queue_status(snum
, &queue
, &status
);
3834 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3837 for (j
=0; j
<count
; j
++) {
3838 construct_notify_jobs_info(&queue
[j
], info
,
3845 free_a_printer(&printer
, 2);
3855 * Debugging information, don't delete.
3858 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3859 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3860 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3862 for (i=0; i<info->count; i++) {
3863 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3864 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3865 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3871 /********************************************************************
3873 ********************************************************************/
3875 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3877 POLICY_HND
*handle
= &q_u
->handle
;
3878 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3880 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3881 WERROR result
= WERR_BADFID
;
3883 /* we always have a NOTIFY_INFO struct */
3887 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3888 OUR_HANDLE(handle
)));
3892 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3895 * We are now using the change value, and
3896 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3897 * I don't have a global notification system, I'm sending back all the
3898 * informations even when _NOTHING_ has changed.
3901 /* We need to keep track of the change value to send back in
3902 RRPCN replies otherwise our updates are ignored. */
3904 Printer
->notify
.fnpcn
= True
;
3906 if (Printer
->notify
.client_connected
) {
3907 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3908 Printer
->notify
.change
= q_u
->change
;
3911 /* just ignore the SPOOL_NOTIFY_OPTION */
3913 switch (Printer
->printer_type
) {
3914 case PRINTER_HANDLE_IS_PRINTSERVER
:
3915 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3918 case PRINTER_HANDLE_IS_PRINTER
:
3919 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3923 Printer
->notify
.fnpcn
= False
;
3929 /********************************************************************
3930 * construct_printer_info_0
3931 * fill a printer_info_0 struct
3932 ********************************************************************/
3934 static BOOL
construct_printer_info_0(Printer_entry
*print_hnd
, PRINTER_INFO_0
*printer
, int snum
)
3938 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3939 counter_printer_0
*session_counter
;
3940 uint32 global_counter
;
3943 print_status_struct status
;
3945 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
3948 count
= print_queue_length(snum
, &status
);
3950 /* check if we already have a counter for this printer */
3951 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
3953 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
3954 if (session_counter
->snum
== snum
)
3958 /* it's the first time, add it to the list */
3959 if (session_counter
==NULL
) {
3960 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
3961 free_a_printer(&ntprinter
, 2);
3964 ZERO_STRUCTP(session_counter
);
3965 session_counter
->snum
=snum
;
3966 session_counter
->counter
=0;
3967 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
3971 session_counter
->counter
++;
3974 * the global_counter should be stored in a TDB as it's common to all the clients
3975 * and should be zeroed on samba startup
3977 global_counter
=session_counter
->counter
;
3979 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3981 init_unistr(&printer
->printername
, chaine
);
3983 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_called_name());
3984 init_unistr(&printer
->servername
, chaine
);
3986 printer
->cjobs
= count
;
3987 printer
->total_jobs
= 0;
3988 printer
->total_bytes
= 0;
3990 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3991 t
=gmtime(&setuptime
);
3993 printer
->year
= t
->tm_year
+1900;
3994 printer
->month
= t
->tm_mon
+1;
3995 printer
->dayofweek
= t
->tm_wday
;
3996 printer
->day
= t
->tm_mday
;
3997 printer
->hour
= t
->tm_hour
;
3998 printer
->minute
= t
->tm_min
;
3999 printer
->second
= t
->tm_sec
;
4000 printer
->milliseconds
= 0;
4002 printer
->global_counter
= global_counter
;
4003 printer
->total_pages
= 0;
4005 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4006 printer
->major_version
= 0x0005; /* NT 5 */
4007 printer
->build_version
= 0x0893; /* build 2195 */
4009 printer
->unknown7
= 0x1;
4010 printer
->unknown8
= 0x0;
4011 printer
->unknown9
= 0x0;
4012 printer
->session_counter
= session_counter
->counter
;
4013 printer
->unknown11
= 0x0;
4014 printer
->printer_errors
= 0x0; /* number of print failure */
4015 printer
->unknown13
= 0x0;
4016 printer
->unknown14
= 0x1;
4017 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
4018 printer
->unknown16
= 0x0;
4019 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
4020 printer
->unknown18
= 0x0;
4021 printer
->status
= nt_printq_status(status
.status
);
4022 printer
->unknown20
= 0x0;
4023 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4024 printer
->unknown22
= 0x0;
4025 printer
->unknown23
= 0x6; /* 6 ???*/
4026 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
4027 printer
->unknown25
= 0;
4028 printer
->unknown26
= 0;
4029 printer
->unknown27
= 0;
4030 printer
->unknown28
= 0;
4031 printer
->unknown29
= 0;
4033 free_a_printer(&ntprinter
,2);
4037 /********************************************************************
4038 * construct_printer_info_1
4039 * fill a printer_info_1 struct
4040 ********************************************************************/
4041 static BOOL
construct_printer_info_1(Printer_entry
*print_hnd
, uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
4045 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4047 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4050 printer
->flags
=flags
;
4052 if (*ntprinter
->info_2
->comment
== '\0') {
4053 init_unistr(&printer
->comment
, lp_comment(snum
));
4054 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4055 ntprinter
->info_2
->drivername
, lp_comment(snum
));
4058 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4059 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4060 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
4063 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
4065 init_unistr(&printer
->description
, chaine
);
4066 init_unistr(&printer
->name
, chaine2
);
4068 free_a_printer(&ntprinter
,2);
4073 /****************************************************************************
4074 Free a DEVMODE struct.
4075 ****************************************************************************/
4077 static void free_dev_mode(DEVICEMODE
*dev
)
4082 SAFE_FREE(dev
->private);
4087 /****************************************************************************
4088 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4089 should be valid upon entry
4090 ****************************************************************************/
4092 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
4094 if ( !devmode
|| !ntdevmode
)
4097 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
4099 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
4101 devmode
->specversion
= ntdevmode
->specversion
;
4102 devmode
->driverversion
= ntdevmode
->driverversion
;
4103 devmode
->size
= ntdevmode
->size
;
4104 devmode
->driverextra
= ntdevmode
->driverextra
;
4105 devmode
->fields
= ntdevmode
->fields
;
4107 devmode
->orientation
= ntdevmode
->orientation
;
4108 devmode
->papersize
= ntdevmode
->papersize
;
4109 devmode
->paperlength
= ntdevmode
->paperlength
;
4110 devmode
->paperwidth
= ntdevmode
->paperwidth
;
4111 devmode
->scale
= ntdevmode
->scale
;
4112 devmode
->copies
= ntdevmode
->copies
;
4113 devmode
->defaultsource
= ntdevmode
->defaultsource
;
4114 devmode
->printquality
= ntdevmode
->printquality
;
4115 devmode
->color
= ntdevmode
->color
;
4116 devmode
->duplex
= ntdevmode
->duplex
;
4117 devmode
->yresolution
= ntdevmode
->yresolution
;
4118 devmode
->ttoption
= ntdevmode
->ttoption
;
4119 devmode
->collate
= ntdevmode
->collate
;
4120 devmode
->icmmethod
= ntdevmode
->icmmethod
;
4121 devmode
->icmintent
= ntdevmode
->icmintent
;
4122 devmode
->mediatype
= ntdevmode
->mediatype
;
4123 devmode
->dithertype
= ntdevmode
->dithertype
;
4125 if (ntdevmode
->private != NULL
) {
4126 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
4133 /****************************************************************************
4134 Create a DEVMODE struct. Returns malloced memory.
4135 ****************************************************************************/
4137 DEVICEMODE
*construct_dev_mode(int snum
)
4139 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4140 DEVICEMODE
*devmode
= NULL
;
4142 DEBUG(7,("construct_dev_mode\n"));
4144 DEBUGADD(8,("getting printer characteristics\n"));
4146 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
4149 if ( !printer
->info_2
->devmode
) {
4150 DEBUG(5, ("BONG! There was no device mode!\n"));
4154 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
4155 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4159 ZERO_STRUCTP(devmode
);
4161 DEBUGADD(8,("loading DEVICEMODE\n"));
4163 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
4164 free_dev_mode( devmode
);
4169 free_a_printer(&printer
,2);
4174 /********************************************************************
4175 * construct_printer_info_2
4176 * fill a printer_info_2 struct
4177 ********************************************************************/
4179 static BOOL
construct_printer_info_2(Printer_entry
*print_hnd
, PRINTER_INFO_2
*printer
, int snum
)
4182 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4184 print_status_struct status
;
4186 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4189 count
= print_queue_length(snum
, &status
);
4191 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4192 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4193 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4194 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4195 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4197 if (*ntprinter
->info_2
->comment
== '\0')
4198 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4200 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4202 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4203 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4204 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4205 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4206 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4208 printer
->attributes
= ntprinter
->info_2
->attributes
;
4210 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4211 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4212 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4213 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4214 printer
->status
= nt_printq_status(status
.status
); /* status */
4215 printer
->cjobs
= count
; /* jobs */
4216 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4218 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
4219 DEBUG(8, ("Returning NULL Devicemode!\n"));
4222 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4223 /* steal the printer info sec_desc structure. [badly done]. */
4224 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4225 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
4226 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
4227 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
4230 printer
->secdesc
= NULL
;
4233 free_a_printer(&ntprinter
, 2);
4237 /********************************************************************
4238 * construct_printer_info_3
4239 * fill a printer_info_3 struct
4240 ********************************************************************/
4242 static BOOL
construct_printer_info_3(Printer_entry
*print_hnd
, PRINTER_INFO_3
**pp_printer
, int snum
)
4244 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4245 PRINTER_INFO_3
*printer
= NULL
;
4247 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4251 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
4252 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4256 ZERO_STRUCTP(printer
);
4258 printer
->flags
= 4; /* These are the components of the SD we are returning. */
4259 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4260 /* steal the printer info sec_desc structure. [badly done]. */
4261 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4265 * Set the flags for the components we are returning.
4268 if (printer
->secdesc
->owner_sid
)
4269 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
4271 if (printer
->secdesc
->grp_sid
)
4272 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
4274 if (printer
->secdesc
->dacl
)
4275 printer
->flags
|= DACL_SECURITY_INFORMATION
;
4277 if (printer
->secdesc
->sacl
)
4278 printer
->flags
|= SACL_SECURITY_INFORMATION
;
4281 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
4282 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
4283 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
4286 free_a_printer(&ntprinter
, 2);
4288 *pp_printer
= printer
;
4292 /********************************************************************
4293 * construct_printer_info_4
4294 * fill a printer_info_4 struct
4295 ********************************************************************/
4297 static BOOL
construct_printer_info_4(Printer_entry
*print_hnd
, PRINTER_INFO_4
*printer
, int snum
)
4299 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4301 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4304 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4305 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4306 printer
->attributes
= ntprinter
->info_2
->attributes
;
4308 free_a_printer(&ntprinter
, 2);
4312 /********************************************************************
4313 * construct_printer_info_5
4314 * fill a printer_info_5 struct
4315 ********************************************************************/
4317 static BOOL
construct_printer_info_5(Printer_entry
*print_hnd
, PRINTER_INFO_5
*printer
, int snum
)
4319 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4321 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4324 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
);
4325 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
);
4326 printer
->attributes
= ntprinter
->info_2
->attributes
;
4328 /* these two are not used by NT+ according to MSDN */
4330 printer
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4331 printer
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4333 free_a_printer(&ntprinter
, 2);
4338 /********************************************************************
4339 * construct_printer_info_7
4340 * fill a printer_info_7 struct
4341 ********************************************************************/
4343 static BOOL
construct_printer_info_7(Printer_entry
*print_hnd
, PRINTER_INFO_7
*printer
, int snum
)
4345 char *guid_str
= NULL
;
4348 if (is_printer_published(print_hnd
, snum
, &guid
)) {
4349 asprintf(&guid_str
, "{%s}", smb_uuid_string_static(guid
));
4350 strupper_m(guid_str
);
4351 init_unistr(&printer
->guid
, guid_str
);
4352 printer
->action
= SPOOL_DS_PUBLISH
;
4354 init_unistr(&printer
->guid
, "");
4355 printer
->action
= SPOOL_DS_UNPUBLISH
;
4361 /********************************************************************
4362 Spoolss_enumprinters.
4363 ********************************************************************/
4365 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4369 int n_services
=lp_numservices();
4370 PRINTER_INFO_1
*tp
, *printers
=NULL
;
4371 PRINTER_INFO_1 current_prt
;
4373 DEBUG(4,("enum_all_printers_info_1\n"));
4375 for (snum
=0; snum
<n_services
; snum
++) {
4376 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4377 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4379 if (construct_printer_info_1(NULL
, flags
, ¤t_prt
, snum
)) {
4380 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
4381 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4382 SAFE_FREE(printers
);
4387 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4389 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4395 /* check the required size. */
4396 for (i
=0; i
<*returned
; i
++)
4397 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4399 if (!alloc_buffer_size(buffer
, *needed
))
4400 return WERR_INSUFFICIENT_BUFFER
;
4402 /* fill the buffer with the structures */
4403 for (i
=0; i
<*returned
; i
++)
4404 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4407 SAFE_FREE(printers
);
4409 if (*needed
> offered
) {
4411 return WERR_INSUFFICIENT_BUFFER
;
4417 /********************************************************************
4418 enum_all_printers_info_1_local.
4419 *********************************************************************/
4421 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4423 DEBUG(4,("enum_all_printers_info_1_local\n"));
4425 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4428 /********************************************************************
4429 enum_all_printers_info_1_name.
4430 *********************************************************************/
4432 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4436 DEBUG(4,("enum_all_printers_info_1_name\n"));
4438 if ((name
[0] == '\\') && (name
[1] == '\\'))
4441 if (is_myname_or_ipaddr(s
)) {
4442 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4445 return WERR_INVALID_NAME
;
4448 /********************************************************************
4449 enum_all_printers_info_1_remote.
4450 *********************************************************************/
4452 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4454 PRINTER_INFO_1
*printer
;
4455 fstring printername
;
4458 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4460 /* JFM: currently it's more a place holder than anything else.
4461 * In the spooler world there is a notion of server registration.
4462 * the print servers are registring (sp ?) on the PDC (in the same domain)
4464 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4467 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4472 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4473 slprintf(desc
, sizeof(desc
)-1,"%s", get_called_name());
4474 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4476 init_unistr(&printer
->description
, desc
);
4477 init_unistr(&printer
->name
, printername
);
4478 init_unistr(&printer
->comment
, comment
);
4479 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4481 /* check the required size. */
4482 *needed
+= spoolss_size_printer_info_1(printer
);
4484 if (!alloc_buffer_size(buffer
, *needed
)) {
4486 return WERR_INSUFFICIENT_BUFFER
;
4489 /* fill the buffer with the structures */
4490 smb_io_printer_info_1("", buffer
, printer
, 0);
4495 if (*needed
> offered
) {
4497 return WERR_INSUFFICIENT_BUFFER
;
4503 /********************************************************************
4504 enum_all_printers_info_1_network.
4505 *********************************************************************/
4507 static WERROR
enum_all_printers_info_1_network(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4511 DEBUG(4,("enum_all_printers_info_1_network\n"));
4513 /* If we respond to a enum_printers level 1 on our name with flags
4514 set to PRINTER_ENUM_REMOTE with a list of printers then these
4515 printers incorrectly appear in the APW browse list.
4516 Specifically the printers for the server appear at the workgroup
4517 level where all the other servers in the domain are
4518 listed. Windows responds to this call with a
4519 WERR_CAN_NOT_COMPLETE so we should do the same. */
4521 if (name
[0] == '\\' && name
[1] == '\\')
4524 if (is_myname_or_ipaddr(s
))
4525 return WERR_CAN_NOT_COMPLETE
;
4527 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4530 /********************************************************************
4531 * api_spoolss_enumprinters
4533 * called from api_spoolss_enumprinters (see this to understand)
4534 ********************************************************************/
4536 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4540 int n_services
=lp_numservices();
4541 PRINTER_INFO_2
*tp
, *printers
=NULL
;
4542 PRINTER_INFO_2 current_prt
;
4544 for (snum
=0; snum
<n_services
; snum
++) {
4545 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4546 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4548 if (construct_printer_info_2(NULL
, ¤t_prt
, snum
)) {
4549 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
4550 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4551 SAFE_FREE(printers
);
4556 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
4557 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4563 /* check the required size. */
4564 for (i
=0; i
<*returned
; i
++)
4565 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4567 if (!alloc_buffer_size(buffer
, *needed
)) {
4568 for (i
=0; i
<*returned
; i
++) {
4569 free_devmode(printers
[i
].devmode
);
4571 SAFE_FREE(printers
);
4572 return WERR_INSUFFICIENT_BUFFER
;
4575 /* fill the buffer with the structures */
4576 for (i
=0; i
<*returned
; i
++)
4577 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4580 for (i
=0; i
<*returned
; i
++) {
4581 free_devmode(printers
[i
].devmode
);
4583 SAFE_FREE(printers
);
4585 if (*needed
> offered
) {
4587 return WERR_INSUFFICIENT_BUFFER
;
4593 /********************************************************************
4594 * handle enumeration of printers at level 1
4595 ********************************************************************/
4597 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4598 NEW_BUFFER
*buffer
, uint32 offered
,
4599 uint32
*needed
, uint32
*returned
)
4601 /* Not all the flags are equals */
4603 if (flags
& PRINTER_ENUM_LOCAL
)
4604 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4606 if (flags
& PRINTER_ENUM_NAME
)
4607 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4609 if (flags
& PRINTER_ENUM_REMOTE
)
4610 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4612 if (flags
& PRINTER_ENUM_NETWORK
)
4613 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4615 return WERR_OK
; /* NT4sp5 does that */
4618 /********************************************************************
4619 * handle enumeration of printers at level 2
4620 ********************************************************************/
4622 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4623 NEW_BUFFER
*buffer
, uint32 offered
,
4624 uint32
*needed
, uint32
*returned
)
4626 char *s
= servername
;
4628 if (flags
& PRINTER_ENUM_LOCAL
) {
4629 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4632 if (flags
& PRINTER_ENUM_NAME
) {
4633 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4635 if (is_myname_or_ipaddr(s
))
4636 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4638 return WERR_INVALID_NAME
;
4641 if (flags
& PRINTER_ENUM_REMOTE
)
4642 return WERR_UNKNOWN_LEVEL
;
4647 /********************************************************************
4648 * handle enumeration of printers at level 5
4649 ********************************************************************/
4651 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4652 NEW_BUFFER
*buffer
, uint32 offered
,
4653 uint32
*needed
, uint32
*returned
)
4655 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4659 /********************************************************************
4660 * api_spoolss_enumprinters
4662 * called from api_spoolss_enumprinters (see this to understand)
4663 ********************************************************************/
4665 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4667 uint32 flags
= q_u
->flags
;
4668 UNISTR2
*servername
= &q_u
->servername
;
4669 uint32 level
= q_u
->level
;
4670 NEW_BUFFER
*buffer
= NULL
;
4671 uint32 offered
= q_u
->offered
;
4672 uint32
*needed
= &r_u
->needed
;
4673 uint32
*returned
= &r_u
->returned
;
4677 /* that's an [in out] buffer */
4678 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4679 buffer
= r_u
->buffer
;
4681 DEBUG(4,("_spoolss_enumprinters\n"));
4688 * flags==PRINTER_ENUM_NAME
4689 * if name=="" then enumerates all printers
4690 * if name!="" then enumerate the printer
4691 * flags==PRINTER_ENUM_REMOTE
4692 * name is NULL, enumerate printers
4693 * Level 2: name!="" enumerates printers, name can't be NULL
4694 * Level 3: doesn't exist
4695 * Level 4: does a local registry lookup
4696 * Level 5: same as Level 2
4699 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4704 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4706 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4708 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4713 return WERR_UNKNOWN_LEVEL
;
4716 /****************************************************************************
4717 ****************************************************************************/
4719 static WERROR
getprinter_level_0(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4721 PRINTER_INFO_0
*printer
=NULL
;
4723 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
4726 construct_printer_info_0(print_hnd
, printer
, snum
);
4728 /* check the required size. */
4729 *needed
+= spoolss_size_printer_info_0(printer
);
4731 if (!alloc_buffer_size(buffer
, *needed
)) {
4733 return WERR_INSUFFICIENT_BUFFER
;
4736 /* fill the buffer with the structures */
4737 smb_io_printer_info_0("", buffer
, printer
, 0);
4742 if (*needed
> offered
) {
4743 return WERR_INSUFFICIENT_BUFFER
;
4749 /****************************************************************************
4750 ****************************************************************************/
4752 static WERROR
getprinter_level_1(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4754 PRINTER_INFO_1
*printer
=NULL
;
4756 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4759 construct_printer_info_1(print_hnd
, PRINTER_ENUM_ICON8
, printer
, snum
);
4761 /* check the required size. */
4762 *needed
+= spoolss_size_printer_info_1(printer
);
4764 if (!alloc_buffer_size(buffer
, *needed
)) {
4766 return WERR_INSUFFICIENT_BUFFER
;
4769 /* fill the buffer with the structures */
4770 smb_io_printer_info_1("", buffer
, printer
, 0);
4775 if (*needed
> offered
) {
4776 return WERR_INSUFFICIENT_BUFFER
;
4782 /****************************************************************************
4783 ****************************************************************************/
4785 static WERROR
getprinter_level_2(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4787 PRINTER_INFO_2
*printer
=NULL
;
4789 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
4792 construct_printer_info_2(print_hnd
, printer
, snum
);
4794 /* check the required size. */
4795 *needed
+= spoolss_size_printer_info_2(printer
);
4797 if (!alloc_buffer_size(buffer
, *needed
)) {
4798 free_printer_info_2(printer
);
4799 return WERR_INSUFFICIENT_BUFFER
;
4802 /* fill the buffer with the structures */
4803 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
4804 free_printer_info_2(printer
);
4809 free_printer_info_2(printer
);
4811 if (*needed
> offered
) {
4812 return WERR_INSUFFICIENT_BUFFER
;
4818 /****************************************************************************
4819 ****************************************************************************/
4821 static WERROR
getprinter_level_3(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4823 PRINTER_INFO_3
*printer
=NULL
;
4825 if (!construct_printer_info_3(print_hnd
, &printer
, snum
))
4828 /* check the required size. */
4829 *needed
+= spoolss_size_printer_info_3(printer
);
4831 if (!alloc_buffer_size(buffer
, *needed
)) {
4832 free_printer_info_3(printer
);
4833 return WERR_INSUFFICIENT_BUFFER
;
4836 /* fill the buffer with the structures */
4837 smb_io_printer_info_3("", buffer
, printer
, 0);
4840 free_printer_info_3(printer
);
4842 if (*needed
> offered
) {
4843 return WERR_INSUFFICIENT_BUFFER
;
4849 /****************************************************************************
4850 ****************************************************************************/
4852 static WERROR
getprinter_level_4(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4854 PRINTER_INFO_4
*printer
=NULL
;
4856 if((printer
=(PRINTER_INFO_4
*)malloc(sizeof(PRINTER_INFO_4
)))==NULL
)
4859 if (!construct_printer_info_4(print_hnd
, printer
, snum
))
4862 /* check the required size. */
4863 *needed
+= spoolss_size_printer_info_4(printer
);
4865 if (!alloc_buffer_size(buffer
, *needed
)) {
4866 free_printer_info_4(printer
);
4867 return WERR_INSUFFICIENT_BUFFER
;
4870 /* fill the buffer with the structures */
4871 smb_io_printer_info_4("", buffer
, printer
, 0);
4874 free_printer_info_4(printer
);
4876 if (*needed
> offered
) {
4877 return WERR_INSUFFICIENT_BUFFER
;
4883 /****************************************************************************
4884 ****************************************************************************/
4886 static WERROR
getprinter_level_5(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4888 PRINTER_INFO_5
*printer
=NULL
;
4890 if((printer
=(PRINTER_INFO_5
*)malloc(sizeof(PRINTER_INFO_5
)))==NULL
)
4893 if (!construct_printer_info_5(print_hnd
, printer
, snum
))
4896 /* check the required size. */
4897 *needed
+= spoolss_size_printer_info_5(printer
);
4899 if (!alloc_buffer_size(buffer
, *needed
)) {
4900 free_printer_info_5(printer
);
4901 return WERR_INSUFFICIENT_BUFFER
;
4904 /* fill the buffer with the structures */
4905 smb_io_printer_info_5("", buffer
, printer
, 0);
4908 free_printer_info_5(printer
);
4910 if (*needed
> offered
) {
4911 return WERR_INSUFFICIENT_BUFFER
;
4917 static WERROR
getprinter_level_7(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4919 PRINTER_INFO_7
*printer
=NULL
;
4921 if((printer
=(PRINTER_INFO_7
*)malloc(sizeof(PRINTER_INFO_7
)))==NULL
)
4924 if (!construct_printer_info_7(print_hnd
, printer
, snum
))
4927 /* check the required size. */
4928 *needed
+= spoolss_size_printer_info_7(printer
);
4930 if (!alloc_buffer_size(buffer
, *needed
)) {
4931 free_printer_info_7(printer
);
4932 return WERR_INSUFFICIENT_BUFFER
;
4935 /* fill the buffer with the structures */
4936 smb_io_printer_info_7("", buffer
, printer
, 0);
4939 free_printer_info_7(printer
);
4941 if (*needed
> offered
) {
4942 return WERR_INSUFFICIENT_BUFFER
;
4948 /****************************************************************************
4949 ****************************************************************************/
4951 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
4953 POLICY_HND
*handle
= &q_u
->handle
;
4954 uint32 level
= q_u
->level
;
4955 NEW_BUFFER
*buffer
= NULL
;
4956 uint32 offered
= q_u
->offered
;
4957 uint32
*needed
= &r_u
->needed
;
4958 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
4962 /* that's an [in out] buffer */
4963 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4964 buffer
= r_u
->buffer
;
4968 if (!get_printer_snum(p
, handle
, &snum
))
4973 return getprinter_level_0(Printer
, snum
, buffer
, offered
, needed
);
4975 return getprinter_level_1(Printer
, snum
, buffer
, offered
, needed
);
4977 return getprinter_level_2(Printer
, snum
, buffer
, offered
, needed
);
4979 return getprinter_level_3(Printer
, snum
, buffer
, offered
, needed
);
4981 return getprinter_level_4(Printer
, snum
, buffer
, offered
, needed
);
4983 return getprinter_level_5(Printer
, snum
, buffer
, offered
, needed
);
4985 return getprinter_level_7(Printer
, snum
, buffer
, offered
, needed
);
4987 return WERR_UNKNOWN_LEVEL
;
4990 /********************************************************************
4991 * fill a DRIVER_INFO_1 struct
4992 ********************************************************************/
4994 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
4996 init_unistr( &info
->name
, driver
.info_3
->name
);
4999 /********************************************************************
5000 * construct_printer_driver_info_1
5001 ********************************************************************/
5003 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5005 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5006 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5008 ZERO_STRUCT(driver
);
5010 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5011 return WERR_INVALID_PRINTER_NAME
;
5013 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
5014 return WERR_UNKNOWN_PRINTER_DRIVER
;
5016 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
5018 free_a_printer(&printer
,2);
5023 /********************************************************************
5024 * construct_printer_driver_info_2
5025 * fill a printer_info_2 struct
5026 ********************************************************************/
5028 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5032 info
->version
=driver
.info_3
->cversion
;
5034 init_unistr( &info
->name
, driver
.info_3
->name
);
5035 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5038 if (strlen(driver
.info_3
->driverpath
)) {
5039 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5040 init_unistr( &info
->driverpath
, temp
);
5042 init_unistr( &info
->driverpath
, "" );
5044 if (strlen(driver
.info_3
->datafile
)) {
5045 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5046 init_unistr( &info
->datafile
, temp
);
5048 init_unistr( &info
->datafile
, "" );
5050 if (strlen(driver
.info_3
->configfile
)) {
5051 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5052 init_unistr( &info
->configfile
, temp
);
5054 init_unistr( &info
->configfile
, "" );
5057 /********************************************************************
5058 * construct_printer_driver_info_2
5059 * fill a printer_info_2 struct
5060 ********************************************************************/
5062 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5064 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5065 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5067 ZERO_STRUCT(printer
);
5068 ZERO_STRUCT(driver
);
5070 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5071 return WERR_INVALID_PRINTER_NAME
;
5073 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
5074 return WERR_UNKNOWN_PRINTER_DRIVER
;
5076 fill_printer_driver_info_2(info
, driver
, servername
);
5078 free_a_printer(&printer
,2);
5083 /********************************************************************
5084 * copy a strings array and convert to UNICODE
5086 * convert an array of ascii string to a UNICODE string
5087 ********************************************************************/
5089 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
5097 DEBUG(6,("init_unistr_array\n"));
5108 v
= ""; /* hack to handle null lists */
5111 /* hack to allow this to be used in places other than when generating
5112 the list of dependent files */
5115 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
5119 DEBUGADD(6,("%d:%s:%lu\n", i
, line
, (unsigned long)strlen(line
)));
5121 /* add one extra unit16 for the second terminating NULL */
5123 if ( (tuary
=Realloc(*uni_array
, (j
+1+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
5124 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5132 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
5137 /* special case for ""; we need to add both NULL's here */
5139 (*uni_array
)[j
++]=0x0000;
5140 (*uni_array
)[j
]=0x0000;
5143 DEBUGADD(6,("last one:done\n"));
5145 /* return size of array in uint16's */
5150 /********************************************************************
5151 * construct_printer_info_3
5152 * fill a printer_info_3 struct
5153 ********************************************************************/
5155 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5161 info
->version
=driver
.info_3
->cversion
;
5163 init_unistr( &info
->name
, driver
.info_3
->name
);
5164 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5166 if (strlen(driver
.info_3
->driverpath
)) {
5167 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5168 init_unistr( &info
->driverpath
, temp
);
5170 init_unistr( &info
->driverpath
, "" );
5172 if (strlen(driver
.info_3
->datafile
)) {
5173 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5174 init_unistr( &info
->datafile
, temp
);
5176 init_unistr( &info
->datafile
, "" );
5178 if (strlen(driver
.info_3
->configfile
)) {
5179 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5180 init_unistr( &info
->configfile
, temp
);
5182 init_unistr( &info
->configfile
, "" );
5184 if (strlen(driver
.info_3
->helpfile
)) {
5185 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5186 init_unistr( &info
->helpfile
, temp
);
5188 init_unistr( &info
->helpfile
, "" );
5190 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5191 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5193 info
->dependentfiles
=NULL
;
5194 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5197 /********************************************************************
5198 * construct_printer_info_3
5199 * fill a printer_info_3 struct
5200 ********************************************************************/
5202 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5204 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5205 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5207 ZERO_STRUCT(driver
);
5209 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5210 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5211 if (!W_ERROR_IS_OK(status
))
5212 return WERR_INVALID_PRINTER_NAME
;
5214 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5215 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5220 * I put this code in during testing. Helpful when commenting out the
5221 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5222 * as win2k always queries the driver using an infor level of 6.
5223 * I've left it in (but ifdef'd out) because I'll probably
5224 * use it in experimentation again in the future. --jerry 22/01/2002
5227 if (!W_ERROR_IS_OK(status
)) {
5229 * Is this a W2k client ?
5232 /* Yes - try again with a WinNT driver. */
5234 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5235 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5239 if (!W_ERROR_IS_OK(status
)) {
5240 free_a_printer(&printer
,2);
5241 return WERR_UNKNOWN_PRINTER_DRIVER
;
5249 fill_printer_driver_info_3(info
, driver
, servername
);
5251 free_a_printer(&printer
,2);
5256 /********************************************************************
5257 * construct_printer_info_6
5258 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5259 ********************************************************************/
5261 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5267 memset(&nullstr
, '\0', sizeof(fstring
));
5269 info
->version
=driver
.info_3
->cversion
;
5271 init_unistr( &info
->name
, driver
.info_3
->name
);
5272 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5274 if (strlen(driver
.info_3
->driverpath
)) {
5275 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5276 init_unistr( &info
->driverpath
, temp
);
5278 init_unistr( &info
->driverpath
, "" );
5280 if (strlen(driver
.info_3
->datafile
)) {
5281 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5282 init_unistr( &info
->datafile
, temp
);
5284 init_unistr( &info
->datafile
, "" );
5286 if (strlen(driver
.info_3
->configfile
)) {
5287 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5288 init_unistr( &info
->configfile
, temp
);
5290 init_unistr( &info
->configfile
, "" );
5292 if (strlen(driver
.info_3
->helpfile
)) {
5293 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5294 init_unistr( &info
->helpfile
, temp
);
5296 init_unistr( &info
->helpfile
, "" );
5298 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5299 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5301 info
->dependentfiles
= NULL
;
5302 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5304 info
->previousdrivernames
=NULL
;
5305 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5307 info
->driver_date
.low
=0;
5308 info
->driver_date
.high
=0;
5311 info
->driver_version_low
=0;
5312 info
->driver_version_high
=0;
5314 init_unistr( &info
->mfgname
, "");
5315 init_unistr( &info
->oem_url
, "");
5316 init_unistr( &info
->hardware_id
, "");
5317 init_unistr( &info
->provider
, "");
5320 /********************************************************************
5321 * construct_printer_info_6
5322 * fill a printer_info_6 struct
5323 ********************************************************************/
5325 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5326 fstring servername
, fstring architecture
, uint32 version
)
5328 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5329 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5332 ZERO_STRUCT(driver
);
5334 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5336 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5338 if (!W_ERROR_IS_OK(status
))
5339 return WERR_INVALID_PRINTER_NAME
;
5341 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5343 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5345 if (!W_ERROR_IS_OK(status
))
5348 * Is this a W2k client ?
5352 free_a_printer(&printer
,2);
5353 return WERR_UNKNOWN_PRINTER_DRIVER
;
5356 /* Yes - try again with a WinNT driver. */
5358 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5359 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5360 if (!W_ERROR_IS_OK(status
)) {
5361 free_a_printer(&printer
,2);
5362 return WERR_UNKNOWN_PRINTER_DRIVER
;
5366 fill_printer_driver_info_6(info
, driver
, servername
);
5368 free_a_printer(&printer
,2);
5369 free_a_printer_driver(driver
, 3);
5374 /****************************************************************************
5375 ****************************************************************************/
5377 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5379 SAFE_FREE(info
->dependentfiles
);
5382 /****************************************************************************
5383 ****************************************************************************/
5385 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5387 SAFE_FREE(info
->dependentfiles
);
5391 /****************************************************************************
5392 ****************************************************************************/
5394 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5396 DRIVER_INFO_1
*info
=NULL
;
5399 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
5402 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5403 if (!W_ERROR_IS_OK(status
)) {
5408 /* check the required size. */
5409 *needed
+= spoolss_size_printer_driver_info_1(info
);
5411 if (!alloc_buffer_size(buffer
, *needed
)) {
5413 return WERR_INSUFFICIENT_BUFFER
;
5416 /* fill the buffer with the structures */
5417 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5422 if (*needed
> offered
)
5423 return WERR_INSUFFICIENT_BUFFER
;
5428 /****************************************************************************
5429 ****************************************************************************/
5431 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5433 DRIVER_INFO_2
*info
=NULL
;
5436 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
5439 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5440 if (!W_ERROR_IS_OK(status
)) {
5445 /* check the required size. */
5446 *needed
+= spoolss_size_printer_driver_info_2(info
);
5448 if (!alloc_buffer_size(buffer
, *needed
)) {
5450 return WERR_INSUFFICIENT_BUFFER
;
5453 /* fill the buffer with the structures */
5454 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5459 if (*needed
> offered
)
5460 return WERR_INSUFFICIENT_BUFFER
;
5465 /****************************************************************************
5466 ****************************************************************************/
5468 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5475 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5476 if (!W_ERROR_IS_OK(status
)) {
5480 /* check the required size. */
5481 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5483 if (!alloc_buffer_size(buffer
, *needed
)) {
5484 free_printer_driver_info_3(&info
);
5485 return WERR_INSUFFICIENT_BUFFER
;
5488 /* fill the buffer with the structures */
5489 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5491 free_printer_driver_info_3(&info
);
5493 if (*needed
> offered
)
5494 return WERR_INSUFFICIENT_BUFFER
;
5499 /****************************************************************************
5500 ****************************************************************************/
5502 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5509 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5510 if (!W_ERROR_IS_OK(status
)) {
5514 /* check the required size. */
5515 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5517 if (!alloc_buffer_size(buffer
, *needed
)) {
5518 free_printer_driver_info_6(&info
);
5519 return WERR_INSUFFICIENT_BUFFER
;
5522 /* fill the buffer with the structures */
5523 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5525 free_printer_driver_info_6(&info
);
5527 if (*needed
> offered
)
5528 return WERR_INSUFFICIENT_BUFFER
;
5533 /****************************************************************************
5534 ****************************************************************************/
5536 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5538 POLICY_HND
*handle
= &q_u
->handle
;
5539 UNISTR2
*uni_arch
= &q_u
->architecture
;
5540 uint32 level
= q_u
->level
;
5541 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5542 NEW_BUFFER
*buffer
= NULL
;
5543 uint32 offered
= q_u
->offered
;
5544 uint32
*needed
= &r_u
->needed
;
5545 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5546 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5549 fstring architecture
;
5552 /* that's an [in out] buffer */
5553 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5554 buffer
= r_u
->buffer
;
5556 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5559 *servermajorversion
= 0;
5560 *serverminorversion
= 0;
5562 fstrcpy(servername
, get_called_name());
5563 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5565 if (!get_printer_snum(p
, handle
, &snum
))
5570 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5572 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5574 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5576 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5579 /* apparently this call is the equivalent of
5580 EnumPrinterDataEx() for the DsDriver key */
5585 return WERR_UNKNOWN_LEVEL
;
5588 /****************************************************************************
5589 ****************************************************************************/
5591 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5593 POLICY_HND
*handle
= &q_u
->handle
;
5595 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5598 DEBUG(3,("Error in startpageprinter printer handle\n"));
5602 Printer
->page_started
=True
;
5606 /****************************************************************************
5607 ****************************************************************************/
5609 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5611 POLICY_HND
*handle
= &q_u
->handle
;
5614 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5617 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5621 if (!get_printer_snum(p
, handle
, &snum
))
5624 Printer
->page_started
=False
;
5625 print_job_endpage(snum
, Printer
->jobid
);
5630 /********************************************************************
5631 * api_spoolss_getprinter
5632 * called from the spoolss dispatcher
5634 ********************************************************************/
5636 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5638 POLICY_HND
*handle
= &q_u
->handle
;
5639 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5640 uint32
*jobid
= &r_u
->jobid
;
5642 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5646 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5647 struct current_user user
;
5650 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5654 get_current_user(&user
, p
);
5657 * a nice thing with NT is it doesn't listen to what you tell it.
5658 * when asked to send _only_ RAW datas, it tries to send datas
5661 * So I add checks like in NT Server ...
5664 if (info_1
->p_datatype
!= 0) {
5665 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5666 if (strcmp(datatype
, "RAW") != 0) {
5668 return WERR_INVALID_DATATYPE
;
5672 /* get the share number of the printer */
5673 if (!get_printer_snum(p
, handle
, &snum
)) {
5677 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5679 Printer
->jobid
= print_job_start(&user
, snum
, jobname
, Printer
->nt_devmode
);
5681 /* An error occured in print_job_start() so return an appropriate
5684 if (Printer
->jobid
== -1) {
5685 return map_werror_from_unix(errno
);
5688 Printer
->document_started
=True
;
5689 (*jobid
) = Printer
->jobid
;
5694 /********************************************************************
5695 * api_spoolss_getprinter
5696 * called from the spoolss dispatcher
5698 ********************************************************************/
5700 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5702 POLICY_HND
*handle
= &q_u
->handle
;
5704 return _spoolss_enddocprinter_internal(p
, handle
);
5707 /****************************************************************************
5708 ****************************************************************************/
5710 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5712 POLICY_HND
*handle
= &q_u
->handle
;
5713 uint32 buffer_size
= q_u
->buffer_size
;
5714 uint8
*buffer
= q_u
->buffer
;
5715 uint32
*buffer_written
= &q_u
->buffer_size2
;
5717 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5720 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5721 r_u
->buffer_written
= q_u
->buffer_size2
;
5725 if (!get_printer_snum(p
, handle
, &snum
))
5728 (*buffer_written
) = print_job_write(snum
, Printer
->jobid
, (char *)buffer
, buffer_size
);
5729 if (*buffer_written
== -1) {
5730 r_u
->buffer_written
= 0;
5731 if (errno
== ENOSPC
)
5732 return WERR_NO_SPOOL_SPACE
;
5734 return WERR_ACCESS_DENIED
;
5737 r_u
->buffer_written
= q_u
->buffer_size2
;
5742 /********************************************************************
5743 * api_spoolss_getprinter
5744 * called from the spoolss dispatcher
5746 ********************************************************************/
5748 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5751 struct current_user user
;
5753 WERROR errcode
= WERR_BADFUNC
;
5754 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5756 get_current_user(&user
, p
);
5759 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5763 if (!get_printer_snum(p
, handle
, &snum
))
5767 case PRINTER_CONTROL_PAUSE
:
5768 if (print_queue_pause(&user
, snum
, &errcode
)) {
5772 case PRINTER_CONTROL_RESUME
:
5773 case PRINTER_CONTROL_UNPAUSE
:
5774 if (print_queue_resume(&user
, snum
, &errcode
)) {
5778 case PRINTER_CONTROL_PURGE
:
5779 if (print_queue_purge(&user
, snum
, &errcode
)) {
5784 return WERR_UNKNOWN_LEVEL
;
5790 /********************************************************************
5791 * api_spoolss_abortprinter
5792 * From MSDN: "Deletes printer's spool file if printer is configured
5794 ********************************************************************/
5796 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5798 POLICY_HND
*handle
= &q_u
->handle
;
5799 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5801 struct current_user user
;
5802 WERROR errcode
= WERR_OK
;
5805 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5809 if (!get_printer_snum(p
, handle
, &snum
))
5812 get_current_user( &user
, p
);
5814 print_job_delete( &user
, snum
, Printer
->jobid
, &errcode
);
5819 /********************************************************************
5820 * called by spoolss_api_setprinter
5821 * when updating a printer description
5822 ********************************************************************/
5824 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5825 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5826 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5828 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5829 struct current_user user
;
5833 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5835 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5836 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5837 OUR_HANDLE(handle
)));
5839 result
= WERR_BADFID
;
5843 /* NT seems to like setting the security descriptor even though
5844 nothing may have actually changed. This causes annoying
5845 dialog boxes when the user doesn't have permission to change
5846 the security descriptor. */
5848 nt_printing_getsec(p
->mem_ctx
, Printer
->dev
.handlename
, &old_secdesc_ctr
);
5850 if (DEBUGLEVEL
>= 10) {
5854 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5855 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5856 PRINTERNAME(snum
), the_acl
->num_aces
));
5858 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5861 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5863 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5864 the_acl
->ace
[i
].info
.mask
));
5867 the_acl
= secdesc_ctr
->sec
->dacl
;
5870 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5871 PRINTERNAME(snum
), the_acl
->num_aces
));
5873 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5876 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5878 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5879 the_acl
->ace
[i
].info
.mask
));
5882 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5886 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5888 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5893 /* Work out which user is performing the operation */
5895 get_current_user(&user
, p
);
5897 /* Check the user has permissions to change the security
5898 descriptor. By experimentation with two NT machines, the user
5899 requires Full Access to the printer to change security
5902 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5903 result
= WERR_ACCESS_DENIED
;
5907 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
5914 /********************************************************************
5915 Do Samba sanity checks on a printer info struct.
5916 this has changed purpose: it now "canonicalises" printer
5917 info from a client rather than just checking it is correct
5918 ********************************************************************/
5920 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5922 fstring printername
;
5925 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5926 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5928 /* we force some elements to "correct" values */
5929 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", get_called_name());
5930 fstrcpy(info
->sharename
, lp_servicename(snum
));
5932 /* make sure printername is in \\server\printername format */
5934 fstrcpy( printername
, info
->printername
);
5936 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5937 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5941 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5942 get_called_name(), p
);
5944 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5945 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5952 /****************************************************************************
5953 ****************************************************************************/
5955 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
5957 extern userdom_struct current_user_info
;
5958 char *cmd
= lp_addprinter_cmd();
5964 fstring remote_machine
= "%m";
5966 standard_sub_basic(current_user_info
.smb_name
, remote_machine
,sizeof(remote_machine
));
5968 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5969 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5970 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5971 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
5973 DEBUG(10,("Running [%s]\n", command
));
5974 ret
= smbrun(command
, &fd
);
5975 DEBUGADD(10,("returned [%d]\n", ret
));
5984 /* Get lines and convert them back to dos-codepage */
5985 qlines
= fd_lines_load(fd
, &numlines
);
5986 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5990 /* Set the portname to what the script says the portname should be. */
5991 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5992 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5994 /* Send SIGHUP to process group... is there a better way? */
5997 /* reload our services immediately */
5998 reload_services( False
);
6001 file_lines_free(qlines
);
6005 /********************************************************************
6006 * Called by spoolss_api_setprinter
6007 * when updating a printer description.
6008 ********************************************************************/
6010 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
6011 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6012 DEVICEMODE
*devmode
)
6015 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
6016 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6021 DEBUG(8,("update_printer\n"));
6026 result
= WERR_BADFID
;
6030 if (!get_printer_snum(p
, handle
, &snum
)) {
6031 result
= WERR_BADFID
;
6035 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
6036 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
6037 result
= WERR_BADFID
;
6041 DEBUGADD(8,("Converting info_2 struct\n"));
6044 * convert_printer_info converts the incoming
6045 * info from the client and overwrites the info
6046 * just read from the tdb in the pointer 'printer'.
6049 if (!convert_printer_info(info
, printer
, level
)) {
6050 result
= WERR_NOMEM
;
6055 /* we have a valid devmode
6056 convert it and link it*/
6058 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6059 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6060 &printer
->info_2
->devmode
)) {
6061 result
= WERR_NOMEM
;
6066 /* Do sanity check on the requested changes for Samba */
6068 if (!check_printer_ok(printer
->info_2
, snum
)) {
6069 result
= WERR_INVALID_PARAM
;
6073 /* FIXME!!! If the driver has changed we really should verify that
6074 it is installed before doing much else --jerry */
6076 /* Check calling user has permission to update printer description */
6078 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6079 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6080 result
= WERR_ACCESS_DENIED
;
6084 /* Call addprinter hook */
6085 /* Check changes to see if this is really needed */
6087 if ( *lp_addprinter_cmd()
6088 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
6089 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
6090 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
6091 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
6093 if ( !add_printer_hook(printer
) ) {
6094 result
= WERR_ACCESS_DENIED
;
6099 * make sure we actually reload the services after
6100 * this as smb.conf could have a new section in it
6101 * .... shouldn't .... but could
6103 reload_services(False
);
6107 * When a *new* driver is bound to a printer, the drivername is used to
6108 * lookup previously saved driver initialization info, which is then
6109 * bound to the printer, simulating what happens in the Windows arch.
6111 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
6113 if (!set_driver_init(printer
, 2))
6115 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6116 printer
->info_2
->drivername
));
6119 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6120 printer
->info_2
->drivername
));
6122 notify_printer_driver(snum
, printer
->info_2
->drivername
);
6126 * flag which changes actually occured. This is a small subset of
6127 * all the possible changes. We also have to update things in the
6131 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
6132 init_unistr2( &buffer
, printer
->info_2
->comment
, UNI_STR_TERMINATE
);
6133 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
6134 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6136 notify_printer_comment(snum
, printer
->info_2
->comment
);
6139 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
6140 init_unistr2( &buffer
, printer
->info_2
->sharename
, UNI_STR_TERMINATE
);
6141 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
6142 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6144 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
6147 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
6150 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
6153 pname
= printer
->info_2
->printername
;
6156 init_unistr2( &buffer
, pname
, UNI_STR_TERMINATE
);
6157 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
6158 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6160 notify_printer_printername( snum
, pname
);
6163 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
6164 init_unistr2( &buffer
, printer
->info_2
->portname
, UNI_STR_TERMINATE
);
6165 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
6166 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6168 notify_printer_port(snum
, printer
->info_2
->portname
);
6171 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6172 init_unistr2( &buffer
, printer
->info_2
->location
, UNI_STR_TERMINATE
);
6173 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6174 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6176 notify_printer_location(snum
, printer
->info_2
->location
);
6179 /* here we need to update some more DsSpooler keys */
6180 /* uNCName, serverName, shortServerName */
6182 init_unistr2( &buffer
, global_myname(), UNI_STR_TERMINATE
);
6183 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6184 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6185 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6186 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6188 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6189 global_myname(), printer
->info_2
->sharename
);
6190 init_unistr2( &buffer
, asc_buffer
, UNI_STR_TERMINATE
);
6191 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6192 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6194 /* Update printer info */
6195 result
= mod_a_printer(*printer
, 2);
6198 free_a_printer(&printer
, 2);
6199 free_a_printer(&old_printer
, 2);
6205 /****************************************************************************
6206 ****************************************************************************/
6207 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
6208 const SPOOL_PRINTER_INFO_LEVEL
*info
)
6211 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
6213 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6215 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6220 if (!get_printer_snum(p
, handle
, &snum
))
6223 nt_printer_publish(Printer
, snum
, info7
->action
);
6227 return WERR_UNKNOWN_LEVEL
;
6230 /****************************************************************************
6231 ****************************************************************************/
6233 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
6235 POLICY_HND
*handle
= &q_u
->handle
;
6236 uint32 level
= q_u
->level
;
6237 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6238 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
6239 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
6240 uint32 command
= q_u
->command
;
6242 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6245 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6249 /* check the level */
6252 return control_printer(handle
, command
, p
);
6254 return update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6256 return update_printer_sec(handle
, level
, info
, p
,
6259 return publish_or_unpublish_printer(p
, handle
, info
);
6261 return WERR_UNKNOWN_LEVEL
;
6265 /****************************************************************************
6266 ****************************************************************************/
6268 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6270 POLICY_HND
*handle
= &q_u
->handle
;
6271 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6274 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6278 if (Printer
->notify
.client_connected
==True
) {
6281 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
6283 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
6284 !get_printer_snum(p
, handle
, &snum
) )
6287 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6290 Printer
->notify
.flags
=0;
6291 Printer
->notify
.options
=0;
6292 Printer
->notify
.localmachine
[0]='\0';
6293 Printer
->notify
.printerlocal
=0;
6294 if (Printer
->notify
.option
)
6295 free_spool_notify_option(&Printer
->notify
.option
);
6296 Printer
->notify
.client_connected
=False
;
6301 /****************************************************************************
6302 ****************************************************************************/
6304 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6306 /* that's an [in out] buffer (despite appearences to the contrary) */
6307 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6310 return WERR_INVALID_PARAM
; /* this is what a NT server
6311 returns for AddJob. AddJob
6312 must fail on non-local
6316 /****************************************************************************
6317 ****************************************************************************/
6319 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
6320 int position
, int snum
)
6326 t
=gmtime(&queue
->time
);
6327 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
6329 job_info
->jobid
=queue
->job
;
6330 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6331 init_unistr(&job_info
->machinename
, temp_name
);
6332 init_unistr(&job_info
->username
, queue
->fs_user
);
6333 init_unistr(&job_info
->document
, queue
->fs_file
);
6334 init_unistr(&job_info
->datatype
, "RAW");
6335 init_unistr(&job_info
->text_status
, "");
6336 job_info
->status
=nt_printj_status(queue
->status
);
6337 job_info
->priority
=queue
->priority
;
6338 job_info
->position
=position
;
6339 job_info
->totalpages
=queue
->page_count
;
6340 job_info
->pagesprinted
=0;
6342 make_systemtime(&job_info
->submitted
, t
);
6345 /****************************************************************************
6346 ****************************************************************************/
6348 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
6349 int position
, int snum
,
6350 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6351 DEVICEMODE
*devmode
)
6356 t
=gmtime(&queue
->time
);
6357 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
6359 job_info
->jobid
=queue
->job
;
6361 init_unistr(&job_info
->printername
, ntprinter
->info_2
->printername
);
6363 init_unistr(&job_info
->machinename
, temp_name
);
6364 init_unistr(&job_info
->username
, queue
->fs_user
);
6365 init_unistr(&job_info
->document
, queue
->fs_file
);
6366 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6367 init_unistr(&job_info
->datatype
, "RAW");
6368 init_unistr(&job_info
->printprocessor
, "winprint");
6369 init_unistr(&job_info
->parameters
, "");
6370 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6371 init_unistr(&job_info
->text_status
, "");
6373 /* and here the security descriptor */
6375 job_info
->status
=nt_printj_status(queue
->status
);
6376 job_info
->priority
=queue
->priority
;
6377 job_info
->position
=position
;
6378 job_info
->starttime
=0;
6379 job_info
->untiltime
=0;
6380 job_info
->totalpages
=queue
->page_count
;
6381 job_info
->size
=queue
->size
;
6382 make_systemtime(&(job_info
->submitted
), t
);
6383 job_info
->timeelapsed
=0;
6384 job_info
->pagesprinted
=0;
6386 job_info
->devmode
= devmode
;
6391 /****************************************************************************
6392 Enumjobs at level 1.
6393 ****************************************************************************/
6395 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
6396 NEW_BUFFER
*buffer
, uint32 offered
,
6397 uint32
*needed
, uint32
*returned
)
6402 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
6409 for (i
=0; i
<*returned
; i
++)
6410 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
6414 /* check the required size. */
6415 for (i
=0; i
<*returned
; i
++)
6416 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6418 if (!alloc_buffer_size(buffer
, *needed
)) {
6420 return WERR_INSUFFICIENT_BUFFER
;
6423 /* fill the buffer with the structures */
6424 for (i
=0; i
<*returned
; i
++)
6425 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6430 if (*needed
> offered
) {
6432 return WERR_INSUFFICIENT_BUFFER
;
6438 /****************************************************************************
6439 Enumjobs at level 2.
6440 ****************************************************************************/
6442 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
6443 NEW_BUFFER
*buffer
, uint32 offered
,
6444 uint32
*needed
, uint32
*returned
)
6446 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6447 JOB_INFO_2
*info
= NULL
;
6450 DEVICEMODE
*devmode
= NULL
;
6452 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
6455 result
= WERR_NOMEM
;
6459 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6460 if (!W_ERROR_IS_OK(result
)) {
6465 /* this should not be a failure condition if the devmode is NULL */
6467 devmode
= construct_dev_mode(snum
);
6469 for (i
=0; i
<*returned
; i
++)
6470 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
,
6473 free_a_printer(&ntprinter
, 2);
6476 /* check the required size. */
6477 for (i
=0; i
<*returned
; i
++)
6478 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6480 if (*needed
> offered
) {
6482 result
= WERR_INSUFFICIENT_BUFFER
;
6486 if (!alloc_buffer_size(buffer
, *needed
)) {
6488 result
= WERR_INSUFFICIENT_BUFFER
;
6492 /* fill the buffer with the structures */
6493 for (i
=0; i
<*returned
; i
++)
6494 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6499 free_a_printer(&ntprinter
, 2);
6500 free_devmode(devmode
);
6508 /****************************************************************************
6510 ****************************************************************************/
6512 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6514 POLICY_HND
*handle
= &q_u
->handle
;
6515 uint32 level
= q_u
->level
;
6516 NEW_BUFFER
*buffer
= NULL
;
6517 uint32 offered
= q_u
->offered
;
6518 uint32
*needed
= &r_u
->needed
;
6519 uint32
*returned
= &r_u
->returned
;
6523 print_status_struct prt_status
;
6524 print_queue_struct
*queue
=NULL
;
6526 /* that's an [in out] buffer */
6527 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6528 buffer
= r_u
->buffer
;
6530 DEBUG(4,("_spoolss_enumjobs\n"));
6535 if (!get_printer_snum(p
, handle
, &snum
))
6538 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6539 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6541 if (*returned
== 0) {
6548 wret
= enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
6551 wret
= enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
6556 return WERR_UNKNOWN_LEVEL
;
6560 /****************************************************************************
6561 ****************************************************************************/
6563 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6568 /****************************************************************************
6569 ****************************************************************************/
6571 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6573 POLICY_HND
*handle
= &q_u
->handle
;
6574 uint32 jobid
= q_u
->jobid
;
6575 uint32 command
= q_u
->command
;
6577 struct current_user user
;
6579 WERROR errcode
= WERR_BADFUNC
;
6581 if (!get_printer_snum(p
, handle
, &snum
)) {
6585 if (!print_job_exists(snum
, jobid
)) {
6586 return WERR_INVALID_PRINTER_NAME
;
6589 get_current_user(&user
, p
);
6592 case JOB_CONTROL_CANCEL
:
6593 case JOB_CONTROL_DELETE
:
6594 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
6598 case JOB_CONTROL_PAUSE
:
6599 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
6603 case JOB_CONTROL_RESTART
:
6604 case JOB_CONTROL_RESUME
:
6605 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
6610 return WERR_UNKNOWN_LEVEL
;
6616 /****************************************************************************
6617 Enumerates all printer drivers at level 1.
6618 ****************************************************************************/
6620 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6625 fstring
*list
= NULL
;
6627 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6628 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
6632 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6634 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6635 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6641 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
6642 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6643 SAFE_FREE(driver_info_1
);
6647 else driver_info_1
= tdi1
;
6650 for (i
=0; i
<ndrivers
; i
++) {
6652 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6653 ZERO_STRUCT(driver
);
6654 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6655 architecture
, version
);
6656 if (!W_ERROR_IS_OK(status
)) {
6660 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6661 free_a_printer_driver(driver
, 3);
6664 *returned
+=ndrivers
;
6668 /* check the required size. */
6669 for (i
=0; i
<*returned
; i
++) {
6670 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6671 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6674 if (!alloc_buffer_size(buffer
, *needed
)) {
6675 SAFE_FREE(driver_info_1
);
6676 return WERR_INSUFFICIENT_BUFFER
;
6679 /* fill the buffer with the driver structures */
6680 for (i
=0; i
<*returned
; i
++) {
6681 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6682 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6685 SAFE_FREE(driver_info_1
);
6687 if (*needed
> offered
) {
6689 return WERR_INSUFFICIENT_BUFFER
;
6695 /****************************************************************************
6696 Enumerates all printer drivers at level 2.
6697 ****************************************************************************/
6699 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6704 fstring
*list
= NULL
;
6706 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6707 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
6711 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6713 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6714 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6720 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
6721 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6722 SAFE_FREE(driver_info_2
);
6726 else driver_info_2
= tdi2
;
6729 for (i
=0; i
<ndrivers
; i
++) {
6732 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6733 ZERO_STRUCT(driver
);
6734 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6735 architecture
, version
);
6736 if (!W_ERROR_IS_OK(status
)) {
6740 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6741 free_a_printer_driver(driver
, 3);
6744 *returned
+=ndrivers
;
6748 /* check the required size. */
6749 for (i
=0; i
<*returned
; i
++) {
6750 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6751 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6754 if (!alloc_buffer_size(buffer
, *needed
)) {
6755 SAFE_FREE(driver_info_2
);
6756 return WERR_INSUFFICIENT_BUFFER
;
6759 /* fill the buffer with the form structures */
6760 for (i
=0; i
<*returned
; i
++) {
6761 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6762 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6765 SAFE_FREE(driver_info_2
);
6767 if (*needed
> offered
) {
6769 return WERR_INSUFFICIENT_BUFFER
;
6775 /****************************************************************************
6776 Enumerates all printer drivers at level 3.
6777 ****************************************************************************/
6779 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6784 fstring
*list
= NULL
;
6786 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6787 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
6791 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6793 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6794 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6800 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
6801 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6802 SAFE_FREE(driver_info_3
);
6806 else driver_info_3
= tdi3
;
6809 for (i
=0; i
<ndrivers
; i
++) {
6812 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6813 ZERO_STRUCT(driver
);
6814 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6815 architecture
, version
);
6816 if (!W_ERROR_IS_OK(status
)) {
6820 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6821 free_a_printer_driver(driver
, 3);
6824 *returned
+=ndrivers
;
6828 /* check the required size. */
6829 for (i
=0; i
<*returned
; i
++) {
6830 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6831 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6834 if (!alloc_buffer_size(buffer
, *needed
)) {
6835 SAFE_FREE(driver_info_3
);
6836 return WERR_INSUFFICIENT_BUFFER
;
6839 /* fill the buffer with the driver structures */
6840 for (i
=0; i
<*returned
; i
++) {
6841 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6842 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6845 for (i
=0; i
<*returned
; i
++)
6846 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6848 SAFE_FREE(driver_info_3
);
6850 if (*needed
> offered
) {
6852 return WERR_INSUFFICIENT_BUFFER
;
6858 /****************************************************************************
6859 Enumerates all printer drivers.
6860 ****************************************************************************/
6862 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6864 UNISTR2
*environment
= &q_u
->environment
;
6865 uint32 level
= q_u
->level
;
6866 NEW_BUFFER
*buffer
= NULL
;
6867 uint32 offered
= q_u
->offered
;
6868 uint32
*needed
= &r_u
->needed
;
6869 uint32
*returned
= &r_u
->returned
;
6871 fstring
*list
= NULL
;
6873 fstring architecture
;
6875 /* that's an [in out] buffer */
6876 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6877 buffer
= r_u
->buffer
;
6879 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6880 fstrcpy(servername
, get_called_name());
6884 unistr2_to_ascii(architecture
, environment
, sizeof(architecture
)-1);
6888 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
6890 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
6892 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
6896 return WERR_UNKNOWN_LEVEL
;
6900 /****************************************************************************
6901 ****************************************************************************/
6903 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
6905 form
->flag
=list
->flag
;
6906 init_unistr(&form
->name
, list
->name
);
6907 form
->width
=list
->width
;
6908 form
->length
=list
->length
;
6909 form
->left
=list
->left
;
6910 form
->top
=list
->top
;
6911 form
->right
=list
->right
;
6912 form
->bottom
=list
->bottom
;
6915 /****************************************************************************
6916 ****************************************************************************/
6918 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
6920 uint32 level
= q_u
->level
;
6921 NEW_BUFFER
*buffer
= NULL
;
6922 uint32 offered
= q_u
->offered
;
6923 uint32
*needed
= &r_u
->needed
;
6924 uint32
*numofforms
= &r_u
->numofforms
;
6925 uint32 numbuiltinforms
;
6927 nt_forms_struct
*list
=NULL
;
6928 nt_forms_struct
*builtinlist
=NULL
;
6933 /* that's an [in out] buffer */
6934 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6935 buffer
= r_u
->buffer
;
6937 DEBUG(4,("_spoolss_enumforms\n"));
6938 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6939 DEBUGADD(5,("Info level [%d]\n", level
));
6941 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
6942 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
6943 *numofforms
= get_ntforms(&list
);
6944 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
6945 *numofforms
+= numbuiltinforms
;
6947 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
6951 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
6956 /* construct the list of form structures */
6957 for (i
=0; i
<numbuiltinforms
; i
++) {
6958 DEBUGADD(6,("Filling form number [%d]\n",i
));
6959 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
6962 SAFE_FREE(builtinlist
);
6964 for (; i
<*numofforms
; i
++) {
6965 DEBUGADD(6,("Filling form number [%d]\n",i
));
6966 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
6971 /* check the required size. */
6972 for (i
=0; i
<numbuiltinforms
; i
++) {
6973 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6974 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6976 for (; i
<*numofforms
; i
++) {
6977 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6978 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6981 *needed
=buffer_size
;
6983 if (!alloc_buffer_size(buffer
, buffer_size
)){
6985 return WERR_INSUFFICIENT_BUFFER
;
6988 /* fill the buffer with the form structures */
6989 for (i
=0; i
<numbuiltinforms
; i
++) {
6990 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6991 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6993 for (; i
<*numofforms
; i
++) {
6994 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6995 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7000 if (*needed
> offered
) {
7002 return WERR_INSUFFICIENT_BUFFER
;
7009 SAFE_FREE(builtinlist
);
7010 return WERR_UNKNOWN_LEVEL
;
7015 /****************************************************************************
7016 ****************************************************************************/
7018 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
7020 uint32 level
= q_u
->level
;
7021 UNISTR2
*uni_formname
= &q_u
->formname
;
7022 NEW_BUFFER
*buffer
= NULL
;
7023 uint32 offered
= q_u
->offered
;
7024 uint32
*needed
= &r_u
->needed
;
7026 nt_forms_struct
*list
=NULL
;
7027 nt_forms_struct builtin_form
;
7032 int numofforms
=0, i
=0;
7034 /* that's an [in out] buffer */
7035 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7036 buffer
= r_u
->buffer
;
7038 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
7040 DEBUG(4,("_spoolss_getform\n"));
7041 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7042 DEBUGADD(5,("Info level [%d]\n", level
));
7044 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
7045 if (!foundBuiltin
) {
7046 numofforms
= get_ntforms(&list
);
7047 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
7049 if (numofforms
== 0)
7056 fill_form_1(&form_1
, &builtin_form
);
7059 /* Check if the requested name is in the list of form structures */
7060 for (i
=0; i
<numofforms
; i
++) {
7062 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
7064 if (strequal(form_name
, list
[i
].name
)) {
7065 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
7066 fill_form_1(&form_1
, &list
[i
]);
7072 if (i
== numofforms
) {
7076 /* check the required size. */
7078 *needed
=spoolss_size_form_1(&form_1
);
7080 if (!alloc_buffer_size(buffer
, buffer_size
)){
7081 return WERR_INSUFFICIENT_BUFFER
;
7084 if (*needed
> offered
) {
7085 return WERR_INSUFFICIENT_BUFFER
;
7088 /* fill the buffer with the form structures */
7089 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
7090 smb_io_form_1("", buffer
, &form_1
, 0);
7096 return WERR_UNKNOWN_LEVEL
;
7100 /****************************************************************************
7101 ****************************************************************************/
7103 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
7105 init_unistr(&port
->port_name
, name
);
7108 /****************************************************************************
7109 ****************************************************************************/
7111 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
7113 init_unistr(&port
->port_name
, name
);
7114 init_unistr(&port
->monitor_name
, "Local Monitor");
7115 init_unistr(&port
->description
, "Local Port");
7116 port
->port_type
=PORT_TYPE_WRITE
;
7120 /****************************************************************************
7122 ****************************************************************************/
7124 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7126 PORT_INFO_1
*ports
=NULL
;
7129 if (*lp_enumports_cmd()) {
7130 char *cmd
= lp_enumports_cmd();
7137 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
7139 DEBUG(10,("Running [%s]\n", command
));
7140 ret
= smbrun(command
, &fd
);
7141 DEBUG(10,("Returned [%d]\n", ret
));
7145 /* Is this the best error to return here? */
7146 return WERR_ACCESS_DENIED
;
7150 qlines
= fd_lines_load(fd
, &numlines
);
7151 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7155 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
7156 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7157 dos_errstr(WERR_NOMEM
)));
7158 file_lines_free(qlines
);
7162 for (i
=0; i
<numlines
; i
++) {
7163 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7164 fill_port_1(&ports
[i
], qlines
[i
]);
7167 file_lines_free(qlines
);
7170 *returned
= numlines
;
7173 *returned
= 1; /* Sole Samba port returned. */
7175 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
7178 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7180 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7183 /* check the required size. */
7184 for (i
=0; i
<*returned
; i
++) {
7185 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7186 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
7189 if (!alloc_buffer_size(buffer
, *needed
)) {
7191 return WERR_INSUFFICIENT_BUFFER
;
7194 /* fill the buffer with the ports structures */
7195 for (i
=0; i
<*returned
; i
++) {
7196 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7197 smb_io_port_1("", buffer
, &ports
[i
], 0);
7202 if (*needed
> offered
) {
7204 return WERR_INSUFFICIENT_BUFFER
;
7210 /****************************************************************************
7212 ****************************************************************************/
7214 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7216 PORT_INFO_2
*ports
=NULL
;
7219 if (*lp_enumports_cmd()) {
7220 char *cmd
= lp_enumports_cmd();
7229 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
7230 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
7232 path
= lp_lockdir();
7234 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
7235 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
7238 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
7239 ret
= smbrun(command
, &fd
);
7240 DEBUGADD(10,("returned [%d]\n", ret
));
7244 /* Is this the best error to return here? */
7245 return WERR_ACCESS_DENIED
;
7249 qlines
= fd_lines_load(fd
, &numlines
);
7250 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7254 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
7255 file_lines_free(qlines
);
7259 for (i
=0; i
<numlines
; i
++) {
7260 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7261 fill_port_2(&(ports
[i
]), qlines
[i
]);
7264 file_lines_free(qlines
);
7267 *returned
= numlines
;
7273 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
7276 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7278 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7281 /* check the required size. */
7282 for (i
=0; i
<*returned
; i
++) {
7283 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7284 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7287 if (!alloc_buffer_size(buffer
, *needed
)) {
7289 return WERR_INSUFFICIENT_BUFFER
;
7292 /* fill the buffer with the ports structures */
7293 for (i
=0; i
<*returned
; i
++) {
7294 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7295 smb_io_port_2("", buffer
, &ports
[i
], 0);
7300 if (*needed
> offered
) {
7302 return WERR_INSUFFICIENT_BUFFER
;
7308 /****************************************************************************
7310 ****************************************************************************/
7312 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7314 uint32 level
= q_u
->level
;
7315 NEW_BUFFER
*buffer
= NULL
;
7316 uint32 offered
= q_u
->offered
;
7317 uint32
*needed
= &r_u
->needed
;
7318 uint32
*returned
= &r_u
->returned
;
7320 /* that's an [in out] buffer */
7321 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7322 buffer
= r_u
->buffer
;
7324 DEBUG(4,("_spoolss_enumports\n"));
7331 return enumports_level_1(buffer
, offered
, needed
, returned
);
7333 return enumports_level_2(buffer
, offered
, needed
, returned
);
7335 return WERR_UNKNOWN_LEVEL
;
7339 /****************************************************************************
7340 ****************************************************************************/
7342 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7343 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7344 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7345 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7348 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7351 WERROR err
= WERR_OK
;
7353 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
7354 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7358 ZERO_STRUCTP(printer
);
7360 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7361 if (!convert_printer_info(info
, printer
, 2)) {
7362 free_a_printer(&printer
, 2);
7366 /* check to see if the printer already exists */
7368 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7369 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7370 printer
->info_2
->sharename
));
7371 free_a_printer(&printer
, 2);
7372 return WERR_PRINTER_ALREADY_EXISTS
;
7375 /* FIXME!!! smbd should check to see if the driver is installed before
7376 trying to add a printer like this --jerry */
7378 if (*lp_addprinter_cmd() ) {
7379 if ( !add_printer_hook(printer
) ) {
7380 free_a_printer(&printer
,2);
7381 return WERR_ACCESS_DENIED
;
7385 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", get_called_name(),
7386 printer
->info_2
->sharename
);
7389 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7390 free_a_printer(&printer
,2);
7391 return WERR_ACCESS_DENIED
;
7394 /* you must be a printer admin to add a new printer */
7395 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7396 free_a_printer(&printer
,2);
7397 return WERR_ACCESS_DENIED
;
7401 * Do sanity check on the requested changes for Samba.
7404 if (!check_printer_ok(printer
->info_2
, snum
)) {
7405 free_a_printer(&printer
,2);
7406 return WERR_INVALID_PARAM
;
7410 * When a printer is created, the drivername bound to the printer is used
7411 * to lookup previously saved driver initialization info, which is then
7412 * bound to the new printer, simulating what happens in the Windows arch.
7417 set_driver_init(printer
, 2);
7421 /* A valid devmode was included, convert and link it
7423 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7425 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7426 &printer
->info_2
->devmode
))
7430 /* write the ASCII on disk */
7431 err
= mod_a_printer(*printer
, 2);
7432 if (!W_ERROR_IS_OK(err
)) {
7433 free_a_printer(&printer
,2);
7437 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7438 /* Handle open failed - remove addition. */
7439 del_a_printer(printer
->info_2
->sharename
);
7440 free_a_printer(&printer
,2);
7441 return WERR_ACCESS_DENIED
;
7444 update_c_setprinter(False
);
7445 free_a_printer(&printer
,2);
7450 /****************************************************************************
7451 ****************************************************************************/
7453 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7455 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
7456 uint32 level
= q_u
->level
;
7457 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7458 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7459 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7460 uint32 user_switch
= q_u
->user_switch
;
7461 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7462 POLICY_HND
*handle
= &r_u
->handle
;
7466 /* we don't handle yet */
7467 /* but I know what to do ... */
7468 return WERR_UNKNOWN_LEVEL
;
7470 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7472 user_switch
, user
, handle
);
7474 return WERR_UNKNOWN_LEVEL
;
7478 /****************************************************************************
7479 ****************************************************************************/
7481 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7483 uint32 level
= q_u
->level
;
7484 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7485 WERROR err
= WERR_OK
;
7486 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7487 struct current_user user
;
7488 fstring driver_name
;
7491 ZERO_STRUCT(driver
);
7493 get_current_user(&user
, p
);
7495 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7500 DEBUG(5,("Cleaning driver's information\n"));
7501 err
= clean_up_driver_struct(driver
, level
, &user
);
7502 if (!W_ERROR_IS_OK(err
))
7505 DEBUG(5,("Moving driver to final destination\n"));
7506 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
7507 if (W_ERROR_IS_OK(err
))
7508 err
= WERR_ACCESS_DENIED
;
7512 if (add_a_printer_driver(driver
, level
)!=0) {
7513 err
= WERR_ACCESS_DENIED
;
7517 /* BEGIN_ADMIN_LOG */
7520 fstrcpy(driver_name
, driver
.info_3
->name
? driver
.info_3
->name
: "");
7521 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7522 driver_name
, get_drv_ver_to_os(driver
.info_3
->cversion
),uidtoname(user
.uid
));
7525 fstrcpy(driver_name
, driver
.info_6
->name
? driver
.info_6
->name
: "");
7526 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7527 driver_name
, get_drv_ver_to_os(driver
.info_6
->version
),uidtoname(user
.uid
));
7533 * I think this is where he DrvUpgradePrinter() hook would be
7534 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7535 * server. Right now, we just need to send ourselves a message
7536 * to update each printer bound to this driver. --jerry
7539 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7540 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7545 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7546 * decide if the driver init data should be deleted. The rules are:
7547 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7548 * 2) delete init data only if there is no 2k/Xp driver
7549 * 3) always delete init data
7550 * The generalized rule is always use init data from the highest order driver.
7551 * It is necessary to follow the driver install by an initialization step to
7552 * finish off this process.
7555 version
= driver
.info_3
->cversion
;
7556 else if (level
== 6)
7557 version
= driver
.info_6
->version
;
7562 * 9x printer driver - never delete init data
7565 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7570 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7571 * there is no 2k/Xp driver init data for this driver name.
7575 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7577 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7579 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7581 if (!del_driver_init(driver_name
))
7582 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7585 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7587 free_a_printer_driver(driver1
,3);
7588 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7595 * 2k or Xp printer driver - always delete init data
7598 if (!del_driver_init(driver_name
))
7599 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7603 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7609 free_a_printer_driver(driver
, level
);
7613 /********************************************************************
7614 * spoolss_addprinterdriverex
7615 ********************************************************************/
7617 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7619 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7620 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7623 * we only support the semantics of AddPrinterDriver()
7624 * i.e. only copy files that are newer than existing ones
7627 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7628 return WERR_ACCESS_DENIED
;
7630 ZERO_STRUCT(q_u_local
);
7631 ZERO_STRUCT(r_u_local
);
7633 /* just pass the information off to _spoolss_addprinterdriver() */
7634 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7635 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7636 q_u_local
.level
= q_u
->level
;
7637 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7639 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7642 /****************************************************************************
7643 ****************************************************************************/
7645 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7647 init_unistr(&info
->name
, name
);
7650 /****************************************************************************
7651 ****************************************************************************/
7653 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7657 const char *short_archi
;
7658 DRIVER_DIRECTORY_1
*info
=NULL
;
7660 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7662 if (!(short_archi
= get_short_archi(long_archi
)))
7663 return WERR_INVALID_ENVIRONMENT
;
7665 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
7668 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi
);
7670 DEBUG(4,("printer driver directory: [%s]\n", path
));
7672 fill_driverdir_1(info
, path
);
7674 *needed
+= spoolss_size_driverdir_info_1(info
);
7676 if (!alloc_buffer_size(buffer
, *needed
)) {
7678 return WERR_INSUFFICIENT_BUFFER
;
7681 smb_io_driverdir_1("", buffer
, info
, 0);
7685 if (*needed
> offered
)
7686 return WERR_INSUFFICIENT_BUFFER
;
7691 /****************************************************************************
7692 ****************************************************************************/
7694 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7696 UNISTR2
*name
= &q_u
->name
;
7697 UNISTR2
*uni_environment
= &q_u
->environment
;
7698 uint32 level
= q_u
->level
;
7699 NEW_BUFFER
*buffer
= NULL
;
7700 uint32 offered
= q_u
->offered
;
7701 uint32
*needed
= &r_u
->needed
;
7703 /* that's an [in out] buffer */
7704 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7705 buffer
= r_u
->buffer
;
7707 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7713 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7715 return WERR_UNKNOWN_LEVEL
;
7719 /****************************************************************************
7720 ****************************************************************************/
7722 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7724 POLICY_HND
*handle
= &q_u
->handle
;
7725 uint32 idx
= q_u
->index
;
7726 uint32 in_value_len
= q_u
->valuesize
;
7727 uint32 in_data_len
= q_u
->datasize
;
7728 uint32
*out_max_value_len
= &r_u
->valuesize
;
7729 uint16
**out_value
= &r_u
->value
;
7730 uint32
*out_value_len
= &r_u
->realvaluesize
;
7731 uint32
*out_type
= &r_u
->type
;
7732 uint32
*out_max_data_len
= &r_u
->datasize
;
7733 uint8
**data_out
= &r_u
->data
;
7734 uint32
*out_data_len
= &r_u
->realdatasize
;
7736 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7738 uint32 biggest_valuesize
;
7739 uint32 biggest_datasize
;
7741 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7744 REGISTRY_VALUE
*val
= NULL
;
7745 NT_PRINTER_DATA
*p_data
;
7746 int i
, key_index
, num_values
;
7749 ZERO_STRUCT( printer
);
7753 *out_max_data_len
= 0;
7757 DEBUG(5,("spoolss_enumprinterdata\n"));
7760 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7764 if (!get_printer_snum(p
,handle
, &snum
))
7767 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7768 if (!W_ERROR_IS_OK(result
))
7771 p_data
= &printer
->info_2
->data
;
7772 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7777 * The NT machine wants to know the biggest size of value and data
7779 * cf: MSDN EnumPrinterData remark section
7782 if ( !in_value_len
&& !in_data_len
&& (key_index
!= -1) )
7784 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7786 biggest_valuesize
= 0;
7787 biggest_datasize
= 0;
7789 num_values
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
7791 for ( i
=0; i
<num_values
; i
++ )
7793 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
7795 name_length
= strlen(val
->valuename
);
7796 if ( strlen(val
->valuename
) > biggest_valuesize
)
7797 biggest_valuesize
= name_length
;
7799 if ( val
->size
> biggest_datasize
)
7800 biggest_datasize
= val
->size
;
7802 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7806 /* the value is an UNICODE string but real_value_size is the length
7807 in bytes including the trailing 0 */
7809 *out_value_len
= 2 * (1+biggest_valuesize
);
7810 *out_data_len
= biggest_datasize
;
7812 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7818 * the value len is wrong in NT sp3
7819 * that's the number of bytes not the number of unicode chars
7822 if ( key_index
!= -1 )
7823 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, idx
);
7828 /* out_value should default to "" or else NT4 has
7829 problems unmarshalling the response */
7831 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7833 if((*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7835 result
= WERR_NOMEM
;
7839 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
7841 /* the data is counted in bytes */
7843 *out_max_data_len
= in_data_len
;
7844 *out_data_len
= in_data_len
;
7846 /* only allocate when given a non-zero data_len */
7848 if ( in_data_len
&& ((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
7850 result
= WERR_NOMEM
;
7854 result
= WERR_NO_MORE_ITEMS
;
7860 * - counted in bytes in the request
7861 * - counted in UNICODE chars in the max reply
7862 * - counted in bytes in the real size
7864 * take a pause *before* coding not *during* coding
7868 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7869 if ( (*out_value
= (uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7871 result
= WERR_NOMEM
;
7875 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), in_value_len
, 0);
7879 *out_type
= regval_type( val
);
7881 /* data - counted in bytes */
7883 *out_max_data_len
= in_data_len
;
7884 if ( (*data_out
= (uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
7886 result
= WERR_NOMEM
;
7889 data_len
= (size_t)regval_size(val
);
7890 memcpy( *data_out
, regval_data_p(val
), data_len
);
7891 *out_data_len
= data_len
;
7895 free_a_printer(&printer
, 2);
7899 /****************************************************************************
7900 ****************************************************************************/
7902 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
7904 POLICY_HND
*handle
= &q_u
->handle
;
7905 UNISTR2
*value
= &q_u
->value
;
7906 uint32 type
= q_u
->type
;
7907 uint8
*data
= q_u
->data
;
7908 uint32 real_len
= q_u
->real_len
;
7910 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7912 WERROR status
= WERR_OK
;
7913 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7916 DEBUG(5,("spoolss_setprinterdata\n"));
7919 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7923 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
7924 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7925 return WERR_INVALID_PARAM
;
7928 if (!get_printer_snum(p
,handle
, &snum
))
7932 * Access check : NT returns "access denied" if you make a
7933 * SetPrinterData call without the necessary privildge.
7934 * we were originally returning OK if nothing changed
7935 * which made Win2k issue **a lot** of SetPrinterData
7936 * when connecting to a printer --jerry
7939 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
7941 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7942 status
= WERR_ACCESS_DENIED
;
7946 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7947 if (!W_ERROR_IS_OK(status
))
7950 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
7953 * When client side code sets a magic printer data key, detect it and save
7954 * the current printer data and the magic key's data (its the DEVMODE) for
7955 * future printer/driver initializations.
7957 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
7959 /* Set devmode and printer initialization info */
7960 status
= save_driver_init( printer
, 2, data
, real_len
);
7962 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
7966 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
7967 type
, data
, real_len
);
7968 if ( W_ERROR_IS_OK(status
) )
7969 status
= mod_a_printer(*printer
, 2);
7973 free_a_printer(&printer
, 2);
7978 /****************************************************************************
7979 ****************************************************************************/
7981 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
7983 POLICY_HND
*handle
= &q_u
->handle
;
7984 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7987 DEBUG(5,("_spoolss_resetprinter\n"));
7990 * All we do is to check to see if the handle and queue is valid.
7991 * This call really doesn't mean anything to us because we only
7992 * support RAW printing. --jerry
7996 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8000 if (!get_printer_snum(p
,handle
, &snum
))
8004 /* blindly return success */
8009 /****************************************************************************
8010 ****************************************************************************/
8012 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
8014 POLICY_HND
*handle
= &q_u
->handle
;
8015 UNISTR2
*value
= &q_u
->valuename
;
8017 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8019 WERROR status
= WERR_OK
;
8020 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8023 DEBUG(5,("spoolss_deleteprinterdata\n"));
8026 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8030 if (!get_printer_snum(p
, handle
, &snum
))
8033 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8034 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8035 return WERR_ACCESS_DENIED
;
8038 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8039 if (!W_ERROR_IS_OK(status
))
8042 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8044 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
8046 if ( W_ERROR_IS_OK(status
) )
8047 mod_a_printer( *printer
, 2 );
8049 free_a_printer(&printer
, 2);
8054 /****************************************************************************
8055 ****************************************************************************/
8057 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
8059 POLICY_HND
*handle
= &q_u
->handle
;
8060 FORM
*form
= &q_u
->form
;
8061 nt_forms_struct tmpForm
;
8063 WERROR status
= WERR_OK
;
8064 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8067 nt_forms_struct
*list
=NULL
;
8068 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8070 DEBUG(5,("spoolss_addform\n"));
8073 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8078 /* forms can be added on printer of on the print server handle */
8080 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8082 if (!get_printer_snum(p
,handle
, &snum
))
8085 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8086 if (!W_ERROR_IS_OK(status
))
8090 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8091 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8092 status
= WERR_ACCESS_DENIED
;
8096 /* can't add if builtin */
8098 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8099 status
= WERR_ALREADY_EXISTS
;
8103 count
= get_ntforms(&list
);
8105 if(!add_a_form(&list
, form
, &count
)) {
8106 status
= WERR_NOMEM
;
8110 write_ntforms(&list
, count
);
8113 * ChangeID must always be set if this is a printer
8116 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8117 status
= mod_a_printer(*printer
, 2);
8121 free_a_printer(&printer
, 2);
8127 /****************************************************************************
8128 ****************************************************************************/
8130 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
8132 POLICY_HND
*handle
= &q_u
->handle
;
8133 UNISTR2
*form_name
= &q_u
->name
;
8134 nt_forms_struct tmpForm
;
8136 nt_forms_struct
*list
=NULL
;
8137 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8139 WERROR status
= WERR_OK
;
8140 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8142 DEBUG(5,("spoolss_deleteform\n"));
8145 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8149 /* forms can be deleted on printer of on the print server handle */
8151 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8153 if (!get_printer_snum(p
,handle
, &snum
))
8156 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8157 if (!W_ERROR_IS_OK(status
))
8161 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8162 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8163 status
= WERR_ACCESS_DENIED
;
8167 /* can't delete if builtin */
8169 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
8170 status
= WERR_INVALID_PARAM
;
8174 count
= get_ntforms(&list
);
8176 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
8180 * ChangeID must always be set if this is a printer
8183 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8184 status
= mod_a_printer(*printer
, 2);
8188 free_a_printer(&printer
, 2);
8194 /****************************************************************************
8195 ****************************************************************************/
8197 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
8199 POLICY_HND
*handle
= &q_u
->handle
;
8200 FORM
*form
= &q_u
->form
;
8201 nt_forms_struct tmpForm
;
8203 WERROR status
= WERR_OK
;
8204 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8207 nt_forms_struct
*list
=NULL
;
8208 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8210 DEBUG(5,("spoolss_setform\n"));
8213 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8217 /* forms can be modified on printer of on the print server handle */
8219 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8221 if (!get_printer_snum(p
,handle
, &snum
))
8224 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8225 if (!W_ERROR_IS_OK(status
))
8229 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8230 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8231 status
= WERR_ACCESS_DENIED
;
8235 /* can't set if builtin */
8236 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8237 status
= WERR_INVALID_PARAM
;
8241 count
= get_ntforms(&list
);
8242 update_a_form(&list
, form
, count
);
8243 write_ntforms(&list
, count
);
8246 * ChangeID must always be set if this is a printer
8249 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8250 status
= mod_a_printer(*printer
, 2);
8255 free_a_printer(&printer
, 2);
8261 /****************************************************************************
8262 enumprintprocessors level 1.
8263 ****************************************************************************/
8265 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8267 PRINTPROCESSOR_1
*info_1
=NULL
;
8269 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
8274 init_unistr(&info_1
->name
, "winprint");
8276 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8278 if (!alloc_buffer_size(buffer
, *needed
))
8279 return WERR_INSUFFICIENT_BUFFER
;
8281 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8285 if (*needed
> offered
) {
8287 return WERR_INSUFFICIENT_BUFFER
;
8293 /****************************************************************************
8294 ****************************************************************************/
8296 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8298 uint32 level
= q_u
->level
;
8299 NEW_BUFFER
*buffer
= NULL
;
8300 uint32 offered
= q_u
->offered
;
8301 uint32
*needed
= &r_u
->needed
;
8302 uint32
*returned
= &r_u
->returned
;
8304 /* that's an [in out] buffer */
8305 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8306 buffer
= r_u
->buffer
;
8308 DEBUG(5,("spoolss_enumprintprocessors\n"));
8311 * Enumerate the print processors ...
8313 * Just reply with "winprint", to keep NT happy
8314 * and I can use my nice printer checker.
8322 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8324 return WERR_UNKNOWN_LEVEL
;
8328 /****************************************************************************
8329 enumprintprocdatatypes level 1.
8330 ****************************************************************************/
8332 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8334 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8336 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
8341 init_unistr(&info_1
->name
, "RAW");
8343 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8345 if (!alloc_buffer_size(buffer
, *needed
))
8346 return WERR_INSUFFICIENT_BUFFER
;
8348 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8352 if (*needed
> offered
) {
8354 return WERR_INSUFFICIENT_BUFFER
;
8360 /****************************************************************************
8361 ****************************************************************************/
8363 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8365 uint32 level
= q_u
->level
;
8366 NEW_BUFFER
*buffer
= NULL
;
8367 uint32 offered
= q_u
->offered
;
8368 uint32
*needed
= &r_u
->needed
;
8369 uint32
*returned
= &r_u
->returned
;
8371 /* that's an [in out] buffer */
8372 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8373 buffer
= r_u
->buffer
;
8375 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8382 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8384 return WERR_UNKNOWN_LEVEL
;
8388 /****************************************************************************
8389 enumprintmonitors level 1.
8390 ****************************************************************************/
8392 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8394 PRINTMONITOR_1
*info_1
=NULL
;
8396 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
8401 init_unistr(&info_1
->name
, "Local Port");
8403 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
8405 if (!alloc_buffer_size(buffer
, *needed
))
8406 return WERR_INSUFFICIENT_BUFFER
;
8408 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
8412 if (*needed
> offered
) {
8414 return WERR_INSUFFICIENT_BUFFER
;
8420 /****************************************************************************
8421 enumprintmonitors level 2.
8422 ****************************************************************************/
8424 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8426 PRINTMONITOR_2
*info_2
=NULL
;
8428 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
8433 init_unistr(&info_2
->name
, "Local Port");
8434 init_unistr(&info_2
->environment
, "Windows NT X86");
8435 init_unistr(&info_2
->dll_name
, "localmon.dll");
8437 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
8439 if (!alloc_buffer_size(buffer
, *needed
))
8440 return WERR_INSUFFICIENT_BUFFER
;
8442 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
8446 if (*needed
> offered
) {
8448 return WERR_INSUFFICIENT_BUFFER
;
8454 /****************************************************************************
8455 ****************************************************************************/
8457 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8459 uint32 level
= q_u
->level
;
8460 NEW_BUFFER
*buffer
= NULL
;
8461 uint32 offered
= q_u
->offered
;
8462 uint32
*needed
= &r_u
->needed
;
8463 uint32
*returned
= &r_u
->returned
;
8465 /* that's an [in out] buffer */
8466 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8467 buffer
= r_u
->buffer
;
8469 DEBUG(5,("spoolss_enumprintmonitors\n"));
8472 * Enumerate the print monitors ...
8474 * Just reply with "Local Port", to keep NT happy
8475 * and I can use my nice printer checker.
8483 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8485 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8487 return WERR_UNKNOWN_LEVEL
;
8491 /****************************************************************************
8492 ****************************************************************************/
8494 static WERROR
getjob_level_1(print_queue_struct
**queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
8498 JOB_INFO_1
*info_1
=NULL
;
8500 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
8502 if (info_1
== NULL
) {
8506 for (i
=0; i
<count
&& found
==False
; i
++) {
8507 if ((*queue
)[i
].job
==(int)jobid
)
8513 /* NT treats not found as bad param... yet another bad choice */
8514 return WERR_INVALID_PARAM
;
8517 fill_job_info_1(info_1
, &((*queue
)[i
-1]), i
, snum
);
8519 *needed
+= spoolss_size_job_info_1(info_1
);
8521 if (!alloc_buffer_size(buffer
, *needed
)) {
8523 return WERR_INSUFFICIENT_BUFFER
;
8526 smb_io_job_info_1("", buffer
, info_1
, 0);
8530 if (*needed
> offered
)
8531 return WERR_INSUFFICIENT_BUFFER
;
8536 /****************************************************************************
8537 ****************************************************************************/
8539 static WERROR
getjob_level_2(print_queue_struct
**queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
8544 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8546 DEVICEMODE
*devmode
= NULL
;
8547 NT_DEVICEMODE
*nt_devmode
= NULL
;
8549 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
8551 ZERO_STRUCTP(info_2
);
8553 if (info_2
== NULL
) {
8558 for ( i
=0; i
<count
&& found
==False
; i
++ )
8560 if ((*queue
)[i
].job
== (int)jobid
)
8566 /* NT treats not found as bad param... yet another bad
8568 ret
= WERR_INVALID_PARAM
;
8572 ret
= get_a_printer(NULL
, &ntprinter
, 2, lp_const_servicename(snum
));
8573 if (!W_ERROR_IS_OK(ret
))
8577 * if the print job does not have a DEVMODE associated with it,
8578 * just use the one for the printer. A NULL devicemode is not
8579 * a failure condition
8582 if ( !(nt_devmode
=print_job_devmode( snum
, jobid
)) )
8583 devmode
= construct_dev_mode(snum
);
8585 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) != NULL
) {
8586 ZERO_STRUCTP( devmode
);
8587 convert_nt_devicemode( devmode
, nt_devmode
);
8591 fill_job_info_2(info_2
, &((*queue
)[i
-1]), i
, snum
, ntprinter
, devmode
);
8593 *needed
+= spoolss_size_job_info_2(info_2
);
8595 if (!alloc_buffer_size(buffer
, *needed
)) {
8596 ret
= WERR_INSUFFICIENT_BUFFER
;
8600 smb_io_job_info_2("", buffer
, info_2
, 0);
8602 if (*needed
> offered
) {
8603 ret
= WERR_INSUFFICIENT_BUFFER
;
8610 /* Cleanup allocated memory */
8612 free_job_info_2(info_2
); /* Also frees devmode */
8614 free_a_printer(&ntprinter
, 2);
8619 /****************************************************************************
8620 ****************************************************************************/
8622 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8624 POLICY_HND
*handle
= &q_u
->handle
;
8625 uint32 jobid
= q_u
->jobid
;
8626 uint32 level
= q_u
->level
;
8627 NEW_BUFFER
*buffer
= NULL
;
8628 uint32 offered
= q_u
->offered
;
8629 uint32
*needed
= &r_u
->needed
;
8630 WERROR wstatus
= WERR_OK
;
8634 print_queue_struct
*queue
= NULL
;
8635 print_status_struct prt_status
;
8637 /* that's an [in out] buffer */
8638 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8639 buffer
= r_u
->buffer
;
8641 DEBUG(5,("spoolss_getjob\n"));
8645 if (!get_printer_snum(p
, handle
, &snum
))
8648 count
= print_queue_status(snum
, &queue
, &prt_status
);
8650 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8651 count
, prt_status
.status
, prt_status
.message
));
8655 wstatus
= getjob_level_1(&queue
, count
, snum
, jobid
,
8656 buffer
, offered
, needed
);
8659 wstatus
= getjob_level_2(&queue
, count
, snum
, jobid
,
8660 buffer
, offered
, needed
);
8663 wstatus
= WERR_UNKNOWN_LEVEL
;
8671 /********************************************************************
8672 spoolss_getprinterdataex
8674 From MSDN documentation of GetPrinterDataEx: pass request
8675 to GetPrinterData if key is "PrinterDriverData".
8676 ********************************************************************/
8678 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8680 POLICY_HND
*handle
= &q_u
->handle
;
8681 uint32 in_size
= q_u
->size
;
8682 uint32
*type
= &r_u
->type
;
8683 uint32
*out_size
= &r_u
->size
;
8684 uint8
**data
= &r_u
->data
;
8685 uint32
*needed
= &r_u
->needed
;
8686 fstring keyname
, valuename
;
8688 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8690 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8692 WERROR status
= WERR_OK
;
8694 DEBUG(4,("_spoolss_getprinterdataex\n"));
8696 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8697 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
8699 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8700 keyname
, valuename
));
8702 /* in case of problem, return some default values */
8706 *out_size
= in_size
;
8709 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8710 status
= WERR_BADFID
;
8714 /* Is the handle to a printer or to the server? */
8716 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8717 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8718 status
= WERR_INVALID_PARAM
;
8722 if ( !get_printer_snum(p
,handle
, &snum
) )
8725 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8726 if ( !W_ERROR_IS_OK(status
) )
8729 /* check to see if the keyname is valid */
8730 if ( !strlen(keyname
) ) {
8731 status
= WERR_INVALID_PARAM
;
8735 if ( lookup_printerkey( &printer
->info_2
->data
, keyname
) == -1 ) {
8736 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
8737 free_a_printer( &printer
, 2 );
8738 status
= WERR_BADFILE
;
8742 /* When given a new keyname, we should just create it */
8744 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
8746 if (*needed
> *out_size
)
8747 status
= WERR_MORE_DATA
;
8750 if ( !W_ERROR_IS_OK(status
) )
8752 DEBUG(5, ("error: allocating %d\n", *out_size
));
8754 /* reply this param doesn't exist */
8758 if( (*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
8759 status
= WERR_NOMEM
;
8769 free_a_printer( &printer
, 2 );
8774 /********************************************************************
8775 * spoolss_setprinterdataex
8776 ********************************************************************/
8778 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
8780 POLICY_HND
*handle
= &q_u
->handle
;
8781 uint32 type
= q_u
->type
;
8782 uint8
*data
= q_u
->data
;
8783 uint32 real_len
= q_u
->real_len
;
8785 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8787 WERROR status
= WERR_OK
;
8788 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8793 DEBUG(4,("_spoolss_setprinterdataex\n"));
8795 /* From MSDN documentation of SetPrinterDataEx: pass request to
8796 SetPrinterData if key is "PrinterDriverData" */
8799 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8803 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8804 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8805 return WERR_INVALID_PARAM
;
8808 if ( !get_printer_snum(p
,handle
, &snum
) )
8812 * Access check : NT returns "access denied" if you make a
8813 * SetPrinterData call without the necessary privildge.
8814 * we were originally returning OK if nothing changed
8815 * which made Win2k issue **a lot** of SetPrinterData
8816 * when connecting to a printer --jerry
8819 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8821 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8822 return WERR_ACCESS_DENIED
;
8825 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8826 if (!W_ERROR_IS_OK(status
))
8829 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
8830 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
8832 /* check for OID in valuename */
8834 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
8840 /* save the registry data */
8842 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
8844 if ( W_ERROR_IS_OK(status
) )
8846 /* save the OID if one was specified */
8848 fstrcat( keyname
, "\\" );
8849 fstrcat( keyname
, SPOOL_OID_KEY
);
8852 * I'm not checking the status here on purpose. Don't know
8853 * if this is right, but I'm returning the status from the
8854 * previous set_printer_dataex() call. I have no idea if
8855 * this is right. --jerry
8858 set_printer_dataex( printer
, keyname
, valuename
,
8859 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
8862 status
= mod_a_printer(*printer
, 2);
8865 free_a_printer(&printer
, 2);
8871 /********************************************************************
8872 * spoolss_deleteprinterdataex
8873 ********************************************************************/
8875 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
8877 POLICY_HND
*handle
= &q_u
->handle
;
8878 UNISTR2
*value
= &q_u
->valuename
;
8879 UNISTR2
*key
= &q_u
->keyname
;
8881 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8883 WERROR status
= WERR_OK
;
8884 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8885 pstring valuename
, keyname
;
8887 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8890 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8894 if (!get_printer_snum(p
, handle
, &snum
))
8897 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8898 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8899 return WERR_ACCESS_DENIED
;
8902 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8903 if (!W_ERROR_IS_OK(status
))
8906 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8907 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
8909 status
= delete_printer_dataex( printer
, keyname
, valuename
);
8911 if ( W_ERROR_IS_OK(status
) )
8912 mod_a_printer( *printer
, 2 );
8914 free_a_printer(&printer
, 2);
8919 /********************************************************************
8920 * spoolss_enumprinterkey
8921 ********************************************************************/
8924 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
8927 fstring
*keynames
= NULL
;
8928 uint16
*enumkeys
= NULL
;
8931 POLICY_HND
*handle
= &q_u
->handle
;
8932 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8933 NT_PRINTER_DATA
*data
;
8934 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8936 WERROR status
= WERR_BADFILE
;
8939 DEBUG(4,("_spoolss_enumprinterkey\n"));
8942 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8946 if ( !get_printer_snum(p
,handle
, &snum
) )
8949 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8950 if (!W_ERROR_IS_OK(status
))
8953 /* get the list of subkey names */
8955 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
8956 data
= &printer
->info_2
->data
;
8958 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
8960 if ( num_keys
== -1 ) {
8961 status
= WERR_BADFILE
;
8965 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
8967 r_u
->needed
= printerkey_len
*2;
8969 if ( q_u
->size
< r_u
->needed
) {
8970 status
= WERR_MORE_DATA
;
8974 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
8975 status
= WERR_NOMEM
;
8981 if ( q_u
->size
< r_u
->needed
)
8982 status
= WERR_MORE_DATA
;
8985 free_a_printer( &printer
, 2 );
8986 SAFE_FREE( keynames
);
8991 /********************************************************************
8992 * spoolss_deleteprinterkey
8993 ********************************************************************/
8995 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
8997 POLICY_HND
*handle
= &q_u
->handle
;
8998 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9000 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9004 DEBUG(5,("spoolss_deleteprinterkey\n"));
9007 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9011 /* if keyname == NULL, return error */
9013 if ( !q_u
->keyname
.buffer
)
9014 return WERR_INVALID_PARAM
;
9016 if (!get_printer_snum(p
, handle
, &snum
))
9019 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9020 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9021 return WERR_ACCESS_DENIED
;
9024 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9025 if (!W_ERROR_IS_OK(status
))
9028 /* delete the key and all subneys */
9030 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
9032 status
= delete_all_printer_data( printer
->info_2
, key
);
9034 if ( W_ERROR_IS_OK(status
) )
9035 status
= mod_a_printer(*printer
, 2);
9037 free_a_printer( &printer
, 2 );
9043 /********************************************************************
9044 * spoolss_enumprinterdataex
9045 ********************************************************************/
9047 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
9049 POLICY_HND
*handle
= &q_u
->handle
;
9050 uint32 in_size
= q_u
->size
;
9053 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9054 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
9055 NT_PRINTER_DATA
*p_data
;
9057 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9062 REGISTRY_VALUE
*val
;
9067 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9070 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
9075 * first check for a keyname of NULL or "". Win2k seems to send
9076 * this a lot and we should send back WERR_INVALID_PARAM
9077 * no need to spend time looking up the printer in this case.
9081 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9082 if ( !strlen(key
) ) {
9083 result
= WERR_INVALID_PARAM
;
9087 /* get the printer off of disk */
9089 if (!get_printer_snum(p
,handle
, &snum
))
9092 ZERO_STRUCT(printer
);
9093 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9094 if (!W_ERROR_IS_OK(result
))
9097 /* now look for a match on the key name */
9099 p_data
= &printer
->info_2
->data
;
9101 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9102 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
9104 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
9105 result
= WERR_INVALID_PARAM
;
9112 /* allocate the memory for the array of pointers -- if necessary */
9114 num_entries
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
9117 if ( (enum_values
=talloc(p
->mem_ctx
, num_entries
*sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
9119 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9120 (unsigned long)num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
9121 result
= WERR_NOMEM
;
9125 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
9129 * loop through all params and build the array to pass
9130 * back to the client
9133 for ( i
=0; i
<num_entries
; i
++ )
9135 /* lookup the registry value */
9137 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
9138 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
9142 value_name
= regval_name( val
);
9143 init_unistr( &enum_values
[i
].valuename
, value_name
);
9144 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
9145 enum_values
[i
].type
= regval_type( val
);
9147 data_len
= regval_size( val
);
9149 if ( !(enum_values
[i
].data
= talloc_memdup(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
9151 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9153 result
= WERR_NOMEM
;
9157 enum_values
[i
].data_len
= data_len
;
9159 /* keep track of the size of the array in bytes */
9161 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
9164 /* housekeeping information in the reply */
9166 r_u
->needed
= needed
;
9167 r_u
->returned
= num_entries
;
9169 if (needed
> in_size
) {
9170 result
= WERR_MORE_DATA
;
9174 /* copy data into the reply */
9176 r_u
->ctr
.size
= r_u
->needed
;
9177 r_u
->ctr
.size_of_array
= r_u
->returned
;
9178 r_u
->ctr
.values
= enum_values
;
9184 free_a_printer(&printer
, 2);
9189 /****************************************************************************
9190 ****************************************************************************/
9192 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
9194 init_unistr(&info
->name
, name
);
9197 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
9198 UNISTR2
*environment
,
9205 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
9207 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
9209 if (!get_short_archi(long_archi
))
9210 return WERR_INVALID_ENVIRONMENT
;
9212 if((info
=(PRINTPROCESSOR_DIRECTORY_1
*)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1
))) == NULL
)
9215 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9217 fill_printprocessordirectory_1(info
, path
);
9219 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
9221 if (!alloc_buffer_size(buffer
, *needed
)) {
9223 return WERR_INSUFFICIENT_BUFFER
;
9226 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
9230 if (*needed
> offered
)
9231 return WERR_INSUFFICIENT_BUFFER
;
9236 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
9238 uint32 level
= q_u
->level
;
9239 NEW_BUFFER
*buffer
= NULL
;
9240 uint32 offered
= q_u
->offered
;
9241 uint32
*needed
= &r_u
->needed
;
9244 /* that's an [in out] buffer */
9245 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
9246 buffer
= r_u
->buffer
;
9248 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9254 result
= getprintprocessordirectory_level_1
9255 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
9258 result
= WERR_UNKNOWN_LEVEL
;
9266 WERROR
_spoolss_replyopenprinter(pipes_struct
*p
, SPOOL_Q_REPLYOPENPRINTER
*q_u
,
9267 SPOOL_R_REPLYOPENPRINTER
*r_u
)
9269 DEBUG(5,("_spoolss_replyopenprinter\n"));
9271 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u
->printer
));
9276 WERROR
_spoolss_replycloseprinter(pipes_struct
*p
, SPOOL_Q_REPLYCLOSEPRINTER
*q_u
,
9277 SPOOL_R_REPLYCLOSEPRINTER
*r_u
)
9279 DEBUG(5,("_spoolss_replycloseprinter\n"));