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 [%x] field [%x] 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 },
1985 {"Windows IA64", "IA64", 3 },
1989 for (i=0; archi_table[i].long_archi != NULL; i++)
1991 if (strcmp(arch, archi_table[i].long_archi) == 0)
1992 return (archi_table[i].version);
1998 /********************************************************************
1999 * _spoolss_deleteprinterdriver
2000 ********************************************************************/
2002 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2006 NT_PRINTER_DRIVER_INFO_LEVEL info;
2007 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2009 struct current_user user;
2011 WERROR status_win2k = WERR_ACCESS_DENIED;
2013 get_current_user(&user, p);
2015 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2016 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2018 /* check that we have a valid driver name first */
2020 if ((version=get_version_id(arch)) == -1)
2021 return WERR_INVALID_ENVIRONMENT;
2024 ZERO_STRUCT(info_win2k);
2026 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2028 /* try for Win2k driver if "Windows NT x86" */
2030 if ( version == 2 ) {
2032 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2033 status = WERR_UNKNOWN_PRINTER_DRIVER;
2037 /* otherwise it was a failure */
2039 status = WERR_UNKNOWN_PRINTER_DRIVER;
2045 if (printer_driver_in_use(info.info_3)) {
2046 status = WERR_PRINTER_DRIVER_IN_USE;
2052 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2054 /* if we get to here, we now have 2 driver info structures to remove */
2055 /* remove the Win2k driver first*/
2057 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2058 free_a_printer_driver( info_win2k, 3 );
2060 /* this should not have failed---if it did, report to client */
2061 if ( !W_ERROR_IS_OK(status_win2k) )
2066 status = delete_printer_driver(info.info_3, &user, version, False);
2068 /* if at least one of the deletes succeeded return OK */
2070 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2074 free_a_printer_driver( info, 3 );
2079 /********************************************************************
2080 * spoolss_deleteprinterdriverex
2081 ********************************************************************/
2083 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2087 NT_PRINTER_DRIVER_INFO_LEVEL info;
2088 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2090 uint32 flags = q_u->delete_flags;
2092 struct current_user user;
2094 WERROR status_win2k = WERR_ACCESS_DENIED;
2096 get_current_user(&user, p);
2098 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2099 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2101 /* check that we have a valid driver name first */
2102 if ((version=get_version_id(arch)) == -1) {
2103 /* this is what NT returns */
2104 return WERR_INVALID_ENVIRONMENT;
2107 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2108 version = q_u->version;
2111 ZERO_STRUCT(info_win2k);
2113 status = get_a_printer_driver(&info, 3, driver, arch, version);
2115 if ( !W_ERROR_IS_OK(status) )
2118 * if the client asked for a specific version,
2119 * or this is something other than Windows NT x86,
2123 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2126 /* try for Win2k driver if "Windows NT x86" */
2129 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2130 status = WERR_UNKNOWN_PRINTER_DRIVER;
2135 if ( printer_driver_in_use(info.info_3) ) {
2136 status = WERR_PRINTER_DRIVER_IN_USE;
2141 * we have a couple of cases to consider.
2142 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2143 * then the delete should fail if **any** files overlap with
2145 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2146 * non-overlapping files
2147 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2148 * is set, the do not delete any files
2149 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2152 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2154 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2156 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2157 /* no idea of the correct error here */
2158 status = WERR_ACCESS_DENIED;
2163 /* also check for W32X86/3 if necessary; maybe we already have? */
2165 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2166 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2169 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2170 /* no idea of the correct error here */
2171 free_a_printer_driver( info_win2k, 3 );
2172 status = WERR_ACCESS_DENIED;
2176 /* if we get to here, we now have 2 driver info structures to remove */
2177 /* remove the Win2k driver first*/
2179 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2180 free_a_printer_driver( info_win2k, 3 );
2182 /* this should not have failed---if it did, report to client */
2184 if ( !W_ERROR_IS_OK(status_win2k) )
2189 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2191 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2194 free_a_printer_driver( info, 3 );
2200 /****************************************************************************
2201 Internal routine for retreiving printerdata
2202 ***************************************************************************/
2204 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2205 const char *key, const char *value, uint32 *type, uint8 **data,
2206 uint32 *needed, uint32 in_size )
2208 REGISTRY_VALUE *val;
2211 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2212 return WERR_BADFILE;
2214 *type = regval_type( val );
2216 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2218 size = regval_size( val );
2220 /* copy the min(in_size, len) */
2223 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2225 /* special case for 0 length values */
2227 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2231 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2240 DEBUG(5,("get_printer_dataex: copy done\n"));
2245 /****************************************************************************
2246 Internal routine for removing printerdata
2247 ***************************************************************************/
2249 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2251 return delete_printer_data( printer->info_2, key, value );
2254 /****************************************************************************
2255 Internal routine for storing printerdata
2256 ***************************************************************************/
2258 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2259 uint32 type, uint8 *data, int real_len )
2261 delete_printer_data( printer->info_2, key, value );
2263 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2266 /********************************************************************
2267 GetPrinterData on a printer server Handle.
2268 ********************************************************************/
2270 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2274 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2276 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2278 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2284 if (!StrCaseCmp(value, "BeepEnabled")) {
2286 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2288 SIVAL(*data, 0, 0x00);
2293 if (!StrCaseCmp(value, "EventLog")) {
2295 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2297 /* formally was 0x1b */
2298 SIVAL(*data, 0, 0x0);
2303 if (!StrCaseCmp(value, "NetPopup")) {
2305 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2307 SIVAL(*data, 0, 0x00);
2312 if (!StrCaseCmp(value, "MajorVersion")) {
2314 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2317 /* Windows NT 4.0 seems to not allow uploading of drivers
2318 to a server that reports 0x3 as the MajorVersion.
2319 need to investigate more how Win2k gets around this .
2322 if ( RA_WINNT == get_remote_arch() )
2331 if (!StrCaseCmp(value, "MinorVersion")) {
2333 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2341 * uint32 size = 0x114
2343 * uint32 minor = [0|1]
2344 * uint32 build = [2195|2600]
2345 * extra unicode string = e.g. "Service Pack 3"
2347 if (!StrCaseCmp(value, "OSVersion")) {
2351 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2353 ZERO_STRUCTP( *data );
2355 SIVAL(*data, 0, *needed); /* size */
2356 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2358 SIVAL(*data, 12, 2195); /* build */
2360 /* leave extra string empty */
2366 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2367 const char *string="C:\\PRINTERS";
2369 *needed = 2*(strlen(string)+1);
2370 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2372 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2374 /* it's done by hand ready to go on the wire */
2375 for (i=0; i<strlen(string); i++) {
2376 (*data)[2*i]=string[i];
2377 (*data)[2*i+1]='\0';
2382 if (!StrCaseCmp(value, "Architecture")) {
2383 const char *string="Windows NT x86";
2385 *needed = 2*(strlen(string)+1);
2386 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2388 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2389 for (i=0; i<strlen(string); i++) {
2390 (*data)[2*i]=string[i];
2391 (*data)[2*i+1]='\0';
2396 if (!StrCaseCmp(value, "DsPresent")) {
2398 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2400 SIVAL(*data, 0, 0x01);
2405 if (!StrCaseCmp(value, "DNSMachineName")) {
2408 if (!get_mydnsfullname(hostname))
2409 return WERR_BADFILE;
2411 *needed = 2*(strlen(hostname)+1);
2412 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2414 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2415 for (i=0; i<strlen(hostname); i++) {
2416 (*data)[2*i]=hostname[i];
2417 (*data)[2*i+1]='\0';
2423 return WERR_BADFILE;
2426 /********************************************************************
2427 * spoolss_getprinterdata
2428 ********************************************************************/
2430 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2432 POLICY_HND *handle = &q_u->handle;
2433 UNISTR2 *valuename = &q_u->valuename;
2434 uint32 in_size = q_u->size;
2435 uint32 *type = &r_u->type;
2436 uint32 *out_size = &r_u->size;
2437 uint8 **data = &r_u->data;
2438 uint32 *needed = &r_u->needed;
2441 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2442 NT_PRINTER_INFO_LEVEL *printer = NULL;
2446 * Reminder: when it's a string, the length is in BYTES
2447 * even if UNICODE is negociated.
2452 *out_size = in_size;
2454 /* in case of problem, return some default values */
2459 DEBUG(4,("_spoolss_getprinterdata\n"));
2462 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2463 status = WERR_BADFID;
2467 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2469 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2470 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2473 if ( !get_printer_snum(p,handle, &snum) ) {
2474 status = WERR_BADFID;
2478 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2479 if ( !W_ERROR_IS_OK(status) )
2482 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2484 if ( strequal(value, "ChangeId") ) {
2486 *needed = sizeof(uint32);
2487 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2488 status = WERR_NOMEM;
2491 SIVAL( *data, 0, printer->info_2->changeid );
2495 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2498 if (*needed > *out_size)
2499 status = WERR_MORE_DATA;
2502 if ( !W_ERROR_IS_OK(status) )
2504 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2506 /* reply this param doesn't exist */
2509 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2511 free_a_printer( &printer, 2 );
2520 /* cleanup & exit */
2523 free_a_printer( &printer, 2 );
2528 /*********************************************************
2529 Connect to the client machine.
2530 **********************************************************/
2532 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2533 struct in_addr *client_ip, const char *remote_machine)
2535 ZERO_STRUCTP(the_cli);
2537 if(cli_initialise(the_cli) == NULL) {
2538 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2542 if ( is_zero_ip(*client_ip) ) {
2543 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2544 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2545 cli_shutdown(the_cli);
2549 if (ismyip(the_cli->dest_ip)) {
2550 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2551 cli_shutdown(the_cli);
2556 the_cli->dest_ip.s_addr = client_ip->s_addr;
2557 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2558 inet_ntoa(*client_ip) ));
2561 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2562 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) ));
2563 cli_shutdown(the_cli);
2567 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2568 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2570 cli_shutdown(the_cli);
2574 the_cli->protocol = PROTOCOL_NT1;
2575 cli_setup_signing_state(the_cli, lp_client_signing());
2577 if (!cli_negprot(the_cli)) {
2578 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2579 cli_shutdown(the_cli);
2583 if (the_cli->protocol != PROTOCOL_NT1) {
2584 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2585 cli_shutdown(the_cli);
2590 * Do an anonymous session setup.
2593 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2594 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2595 cli_shutdown(the_cli);
2599 if (!(the_cli->sec_mode & 1)) {
2600 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2601 cli_shutdown(the_cli);
2605 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2606 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) ));
2607 cli_shutdown(the_cli);
2612 * Ok - we have an anonymous connection to the IPC$ share.
2613 * Now start the NT Domain stuff :-).
2616 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2617 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)));
2618 cli_nt_session_close(the_cli);
2619 cli_ulogoff(the_cli);
2620 cli_shutdown(the_cli);
2627 /***************************************************************************
2628 Connect to the client.
2629 ****************************************************************************/
2631 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2632 uint32 localprinter, uint32 type,
2633 POLICY_HND *handle, struct in_addr *client_ip)
2638 * If it's the first connection, contact the client
2639 * and connect to the IPC$ share anonymously
2641 if (smb_connections==0) {
2642 fstring unix_printer;
2644 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2646 ZERO_STRUCT(notify_cli);
2648 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2651 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2652 /* Tell the connections db we're now interested in printer
2653 * notify messages. */
2654 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2658 * Tell the specific printing tdb we want messages for this printer
2659 * by registering our PID.
2662 if (!print_notify_register_pid(snum))
2663 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2667 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2670 if (!W_ERROR_IS_OK(result))
2671 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2672 dos_errstr(result)));
2674 return (W_ERROR_IS_OK(result));
2677 /********************************************************************
2679 * ReplyFindFirstPrinterChangeNotifyEx
2681 * before replying OK: status=0 a rpc call is made to the workstation
2682 * asking ReplyOpenPrinter
2684 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2685 * called from api_spoolss_rffpcnex
2686 ********************************************************************/
2688 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2690 POLICY_HND *handle = &q_u->handle;
2691 uint32 flags = q_u->flags;
2692 uint32 options = q_u->options;
2693 UNISTR2 *localmachine = &q_u->localmachine;
2694 uint32 printerlocal = q_u->printerlocal;
2696 SPOOL_NOTIFY_OPTION *option = q_u->option;
2697 struct in_addr client_ip;
2699 /* store the notify value in the printer struct */
2701 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2704 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2708 Printer->notify.flags=flags;
2709 Printer->notify.options=options;
2710 Printer->notify.printerlocal=printerlocal;
2712 if (Printer->notify.option)
2713 free_spool_notify_option(&Printer->notify.option);
2715 Printer->notify.option=dup_spool_notify_option(option);
2717 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2718 sizeof(Printer->notify.localmachine)-1);
2720 /* Connect to the client machine and send a ReplyOpenPrinter */
2722 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2724 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2725 !get_printer_snum(p, handle, &snum) )
2728 client_ip.s_addr = inet_addr(p->conn->client_address);
2730 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2731 Printer->notify.printerlocal, 1,
2732 &Printer->notify.client_hnd, &client_ip))
2733 return WERR_SERVER_UNAVAILABLE;
2735 Printer->notify.client_connected=True;
2740 /*******************************************************************
2741 * fill a notify_info_data with the servername
2742 ********************************************************************/
2744 void spoolss_notify_server_name(int snum,
2745 SPOOL_NOTIFY_INFO_DATA *data,
2746 print_queue_struct *queue,
2747 NT_PRINTER_INFO_LEVEL *printer,
2748 TALLOC_CTX *mem_ctx)
2750 pstring temp_name, temp;
2753 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2755 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2757 data->notify_data.data.length = len;
2758 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2760 if (!data->notify_data.data.string) {
2761 data->notify_data.data.length = 0;
2765 memcpy(data->notify_data.data.string, temp, len);
2768 /*******************************************************************
2769 * fill a notify_info_data with the printername (not including the servername).
2770 ********************************************************************/
2772 void spoolss_notify_printer_name(int snum,
2773 SPOOL_NOTIFY_INFO_DATA *data,
2774 print_queue_struct *queue,
2775 NT_PRINTER_INFO_LEVEL *printer,
2776 TALLOC_CTX *mem_ctx)
2781 /* the notify name should not contain the \\server\ part */
2782 char *p = strrchr(printer->info_2->printername, '\\');
2785 p = printer->info_2->printername;
2790 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2792 data->notify_data.data.length = len;
2793 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2795 if (!data->notify_data.data.string) {
2796 data->notify_data.data.length = 0;
2800 memcpy(data->notify_data.data.string, temp, len);
2803 /*******************************************************************
2804 * fill a notify_info_data with the servicename
2805 ********************************************************************/
2807 void spoolss_notify_share_name(int snum,
2808 SPOOL_NOTIFY_INFO_DATA *data,
2809 print_queue_struct *queue,
2810 NT_PRINTER_INFO_LEVEL *printer,
2811 TALLOC_CTX *mem_ctx)
2816 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2818 data->notify_data.data.length = len;
2819 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2821 if (!data->notify_data.data.string) {
2822 data->notify_data.data.length = 0;
2826 memcpy(data->notify_data.data.string, temp, len);
2829 /*******************************************************************
2830 * fill a notify_info_data with the port name
2831 ********************************************************************/
2833 void spoolss_notify_port_name(int snum,
2834 SPOOL_NOTIFY_INFO_DATA *data,
2835 print_queue_struct *queue,
2836 NT_PRINTER_INFO_LEVEL *printer,
2837 TALLOC_CTX *mem_ctx)
2842 /* even if it's strange, that's consistant in all the code */
2844 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2846 data->notify_data.data.length = len;
2847 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2849 if (!data->notify_data.data.string) {
2850 data->notify_data.data.length = 0;
2854 memcpy(data->notify_data.data.string, temp, len);
2857 /*******************************************************************
2858 * fill a notify_info_data with the printername
2859 * but it doesn't exist, have to see what to do
2860 ********************************************************************/
2862 void spoolss_notify_driver_name(int snum,
2863 SPOOL_NOTIFY_INFO_DATA *data,
2864 print_queue_struct *queue,
2865 NT_PRINTER_INFO_LEVEL *printer,
2866 TALLOC_CTX *mem_ctx)
2871 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2873 data->notify_data.data.length = len;
2874 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2876 if (!data->notify_data.data.string) {
2877 data->notify_data.data.length = 0;
2881 memcpy(data->notify_data.data.string, temp, len);
2884 /*******************************************************************
2885 * fill a notify_info_data with the comment
2886 ********************************************************************/
2888 void spoolss_notify_comment(int snum,
2889 SPOOL_NOTIFY_INFO_DATA *data,
2890 print_queue_struct *queue,
2891 NT_PRINTER_INFO_LEVEL *printer,
2892 TALLOC_CTX *mem_ctx)
2897 if (*printer->info_2->comment == '\0')
2898 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2900 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2902 data->notify_data.data.length = len;
2903 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2905 if (!data->notify_data.data.string) {
2906 data->notify_data.data.length = 0;
2910 memcpy(data->notify_data.data.string, temp, len);
2913 /*******************************************************************
2914 * fill a notify_info_data with the comment
2915 * location = "Room 1, floor 2, building 3"
2916 ********************************************************************/
2918 void spoolss_notify_location(int snum,
2919 SPOOL_NOTIFY_INFO_DATA *data,
2920 print_queue_struct *queue,
2921 NT_PRINTER_INFO_LEVEL *printer,
2922 TALLOC_CTX *mem_ctx)
2927 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2929 data->notify_data.data.length = len;
2930 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2932 if (!data->notify_data.data.string) {
2933 data->notify_data.data.length = 0;
2937 memcpy(data->notify_data.data.string, temp, len);
2940 /*******************************************************************
2941 * fill a notify_info_data with the device mode
2942 * jfm:xxxx don't to it for know but that's a real problem !!!
2943 ********************************************************************/
2945 static void spoolss_notify_devmode(int snum,
2946 SPOOL_NOTIFY_INFO_DATA *data,
2947 print_queue_struct *queue,
2948 NT_PRINTER_INFO_LEVEL *printer,
2949 TALLOC_CTX *mem_ctx)
2953 /*******************************************************************
2954 * fill a notify_info_data with the separator file name
2955 ********************************************************************/
2957 void spoolss_notify_sepfile(int snum,
2958 SPOOL_NOTIFY_INFO_DATA *data,
2959 print_queue_struct *queue,
2960 NT_PRINTER_INFO_LEVEL *printer,
2961 TALLOC_CTX *mem_ctx)
2966 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2968 data->notify_data.data.length = len;
2969 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2971 if (!data->notify_data.data.string) {
2972 data->notify_data.data.length = 0;
2976 memcpy(data->notify_data.data.string, temp, len);
2979 /*******************************************************************
2980 * fill a notify_info_data with the print processor
2981 * jfm:xxxx return always winprint to indicate we don't do anything to it
2982 ********************************************************************/
2984 void spoolss_notify_print_processor(int snum,
2985 SPOOL_NOTIFY_INFO_DATA *data,
2986 print_queue_struct *queue,
2987 NT_PRINTER_INFO_LEVEL *printer,
2988 TALLOC_CTX *mem_ctx)
2993 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2995 data->notify_data.data.length = len;
2996 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2998 if (!data->notify_data.data.string) {
2999 data->notify_data.data.length = 0;
3003 memcpy(data->notify_data.data.string, temp, len);
3006 /*******************************************************************
3007 * fill a notify_info_data with the print processor options
3008 * jfm:xxxx send an empty string
3009 ********************************************************************/
3011 void spoolss_notify_parameters(int snum,
3012 SPOOL_NOTIFY_INFO_DATA *data,
3013 print_queue_struct *queue,
3014 NT_PRINTER_INFO_LEVEL *printer,
3015 TALLOC_CTX *mem_ctx)
3020 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3022 data->notify_data.data.length = len;
3023 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3025 if (!data->notify_data.data.string) {
3026 data->notify_data.data.length = 0;
3030 memcpy(data->notify_data.data.string, temp, len);
3033 /*******************************************************************
3034 * fill a notify_info_data with the data type
3035 * jfm:xxxx always send RAW as data type
3036 ********************************************************************/
3038 void spoolss_notify_datatype(int snum,
3039 SPOOL_NOTIFY_INFO_DATA *data,
3040 print_queue_struct *queue,
3041 NT_PRINTER_INFO_LEVEL *printer,
3042 TALLOC_CTX *mem_ctx)
3047 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3049 data->notify_data.data.length = len;
3050 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3052 if (!data->notify_data.data.string) {
3053 data->notify_data.data.length = 0;
3057 memcpy(data->notify_data.data.string, temp, len);
3060 /*******************************************************************
3061 * fill a notify_info_data with the security descriptor
3062 * jfm:xxxx send an null pointer to say no security desc
3063 * have to implement security before !
3064 ********************************************************************/
3066 static void spoolss_notify_security_desc(int snum,
3067 SPOOL_NOTIFY_INFO_DATA *data,
3068 print_queue_struct *queue,
3069 NT_PRINTER_INFO_LEVEL *printer,
3070 TALLOC_CTX *mem_ctx)
3072 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3073 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3076 /*******************************************************************
3077 * fill a notify_info_data with the attributes
3078 * jfm:xxxx a samba printer is always shared
3079 ********************************************************************/
3081 void spoolss_notify_attributes(int snum,
3082 SPOOL_NOTIFY_INFO_DATA *data,
3083 print_queue_struct *queue,
3084 NT_PRINTER_INFO_LEVEL *printer,
3085 TALLOC_CTX *mem_ctx)
3087 data->notify_data.value[0] = printer->info_2->attributes;
3088 data->notify_data.value[1] = 0;
3091 /*******************************************************************
3092 * fill a notify_info_data with the priority
3093 ********************************************************************/
3095 static void spoolss_notify_priority(int snum,
3096 SPOOL_NOTIFY_INFO_DATA *data,
3097 print_queue_struct *queue,
3098 NT_PRINTER_INFO_LEVEL *printer,
3099 TALLOC_CTX *mem_ctx)
3101 data->notify_data.value[0] = printer->info_2->priority;
3102 data->notify_data.value[1] = 0;
3105 /*******************************************************************
3106 * fill a notify_info_data with the default priority
3107 ********************************************************************/
3109 static void spoolss_notify_default_priority(int snum,
3110 SPOOL_NOTIFY_INFO_DATA *data,
3111 print_queue_struct *queue,
3112 NT_PRINTER_INFO_LEVEL *printer,
3113 TALLOC_CTX *mem_ctx)
3115 data->notify_data.value[0] = printer->info_2->default_priority;
3116 data->notify_data.value[1] = 0;
3119 /*******************************************************************
3120 * fill a notify_info_data with the start time
3121 ********************************************************************/
3123 static void spoolss_notify_start_time(int snum,
3124 SPOOL_NOTIFY_INFO_DATA *data,
3125 print_queue_struct *queue,
3126 NT_PRINTER_INFO_LEVEL *printer,
3127 TALLOC_CTX *mem_ctx)
3129 data->notify_data.value[0] = printer->info_2->starttime;
3130 data->notify_data.value[1] = 0;
3133 /*******************************************************************
3134 * fill a notify_info_data with the until time
3135 ********************************************************************/
3137 static void spoolss_notify_until_time(int snum,
3138 SPOOL_NOTIFY_INFO_DATA *data,
3139 print_queue_struct *queue,
3140 NT_PRINTER_INFO_LEVEL *printer,
3141 TALLOC_CTX *mem_ctx)
3143 data->notify_data.value[0] = printer->info_2->untiltime;
3144 data->notify_data.value[1] = 0;
3147 /*******************************************************************
3148 * fill a notify_info_data with the status
3149 ********************************************************************/
3151 static void spoolss_notify_status(int snum,
3152 SPOOL_NOTIFY_INFO_DATA *data,
3153 print_queue_struct *queue,
3154 NT_PRINTER_INFO_LEVEL *printer,
3155 TALLOC_CTX *mem_ctx)
3157 print_status_struct status;
3159 print_queue_length(snum, &status);
3160 data->notify_data.value[0]=(uint32) status.status;
3161 data->notify_data.value[1] = 0;
3164 /*******************************************************************
3165 * fill a notify_info_data with the number of jobs queued
3166 ********************************************************************/
3168 void spoolss_notify_cjobs(int snum,
3169 SPOOL_NOTIFY_INFO_DATA *data,
3170 print_queue_struct *queue,
3171 NT_PRINTER_INFO_LEVEL *printer,
3172 TALLOC_CTX *mem_ctx)
3174 data->notify_data.value[0] = print_queue_length(snum, NULL);
3175 data->notify_data.value[1] = 0;
3178 /*******************************************************************
3179 * fill a notify_info_data with the average ppm
3180 ********************************************************************/
3182 static void spoolss_notify_average_ppm(int snum,
3183 SPOOL_NOTIFY_INFO_DATA *data,
3184 print_queue_struct *queue,
3185 NT_PRINTER_INFO_LEVEL *printer,
3186 TALLOC_CTX *mem_ctx)
3188 /* always respond 8 pages per minutes */
3189 /* a little hard ! */
3190 data->notify_data.value[0] = printer->info_2->averageppm;
3191 data->notify_data.value[1] = 0;
3194 /*******************************************************************
3195 * fill a notify_info_data with username
3196 ********************************************************************/
3198 static void spoolss_notify_username(int snum,
3199 SPOOL_NOTIFY_INFO_DATA *data,
3200 print_queue_struct *queue,
3201 NT_PRINTER_INFO_LEVEL *printer,
3202 TALLOC_CTX *mem_ctx)
3207 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3209 data->notify_data.data.length = len;
3210 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3212 if (!data->notify_data.data.string) {
3213 data->notify_data.data.length = 0;
3217 memcpy(data->notify_data.data.string, temp, len);
3220 /*******************************************************************
3221 * fill a notify_info_data with job status
3222 ********************************************************************/
3224 static void spoolss_notify_job_status(int snum,
3225 SPOOL_NOTIFY_INFO_DATA *data,
3226 print_queue_struct *queue,
3227 NT_PRINTER_INFO_LEVEL *printer,
3228 TALLOC_CTX *mem_ctx)
3230 data->notify_data.value[0]=nt_printj_status(queue->status);
3231 data->notify_data.value[1] = 0;
3234 /*******************************************************************
3235 * fill a notify_info_data with job name
3236 ********************************************************************/
3238 static void spoolss_notify_job_name(int snum,
3239 SPOOL_NOTIFY_INFO_DATA *data,
3240 print_queue_struct *queue,
3241 NT_PRINTER_INFO_LEVEL *printer,
3242 TALLOC_CTX *mem_ctx)
3247 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3249 data->notify_data.data.length = len;
3250 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3252 if (!data->notify_data.data.string) {
3253 data->notify_data.data.length = 0;
3257 memcpy(data->notify_data.data.string, temp, len);
3260 /*******************************************************************
3261 * fill a notify_info_data with job status
3262 ********************************************************************/
3264 static void spoolss_notify_job_status_string(int snum,
3265 SPOOL_NOTIFY_INFO_DATA *data,
3266 print_queue_struct *queue,
3267 NT_PRINTER_INFO_LEVEL *printer,
3268 TALLOC_CTX *mem_ctx)
3271 * Now we're returning job status codes we just return a "" here. JRA.
3278 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3281 switch (queue->status) {
3286 p = ""; /* NT provides the paused string */
3295 #endif /* NO LONGER NEEDED. */
3297 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3299 data->notify_data.data.length = len;
3300 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3302 if (!data->notify_data.data.string) {
3303 data->notify_data.data.length = 0;
3307 memcpy(data->notify_data.data.string, temp, len);
3310 /*******************************************************************
3311 * fill a notify_info_data with job time
3312 ********************************************************************/
3314 static void spoolss_notify_job_time(int snum,
3315 SPOOL_NOTIFY_INFO_DATA *data,
3316 print_queue_struct *queue,
3317 NT_PRINTER_INFO_LEVEL *printer,
3318 TALLOC_CTX *mem_ctx)
3320 data->notify_data.value[0]=0x0;
3321 data->notify_data.value[1]=0;
3324 /*******************************************************************
3325 * fill a notify_info_data with job size
3326 ********************************************************************/
3328 static void spoolss_notify_job_size(int snum,
3329 SPOOL_NOTIFY_INFO_DATA *data,
3330 print_queue_struct *queue,
3331 NT_PRINTER_INFO_LEVEL *printer,
3332 TALLOC_CTX *mem_ctx)
3334 data->notify_data.value[0]=queue->size;
3335 data->notify_data.value[1]=0;
3338 /*******************************************************************
3339 * fill a notify_info_data with page info
3340 ********************************************************************/
3341 static void spoolss_notify_total_pages(int snum,
3342 SPOOL_NOTIFY_INFO_DATA *data,
3343 print_queue_struct *queue,
3344 NT_PRINTER_INFO_LEVEL *printer,
3345 TALLOC_CTX *mem_ctx)
3347 data->notify_data.value[0]=queue->page_count;
3348 data->notify_data.value[1]=0;
3351 /*******************************************************************
3352 * fill a notify_info_data with pages printed info.
3353 ********************************************************************/
3354 static void spoolss_notify_pages_printed(int snum,
3355 SPOOL_NOTIFY_INFO_DATA *data,
3356 print_queue_struct *queue,
3357 NT_PRINTER_INFO_LEVEL *printer,
3358 TALLOC_CTX *mem_ctx)
3360 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3361 data->notify_data.value[1]=0;
3364 /*******************************************************************
3365 Fill a notify_info_data with job position.
3366 ********************************************************************/
3368 static void spoolss_notify_job_position(int snum,
3369 SPOOL_NOTIFY_INFO_DATA *data,
3370 print_queue_struct *queue,
3371 NT_PRINTER_INFO_LEVEL *printer,
3372 TALLOC_CTX *mem_ctx)
3374 data->notify_data.value[0]=queue->job;
3375 data->notify_data.value[1]=0;
3378 /*******************************************************************
3379 Fill a notify_info_data with submitted time.
3380 ********************************************************************/
3382 static void spoolss_notify_submitted_time(int snum,
3383 SPOOL_NOTIFY_INFO_DATA *data,
3384 print_queue_struct *queue,
3385 NT_PRINTER_INFO_LEVEL *printer,
3386 TALLOC_CTX *mem_ctx)
3393 t=gmtime(&queue->time);
3395 len = sizeof(SYSTEMTIME);
3397 data->notify_data.data.length = len;
3398 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3400 if (!data->notify_data.data.string) {
3401 data->notify_data.data.length = 0;
3405 make_systemtime(&st, t);
3408 * Systemtime must be linearized as a set of UINT16's.
3409 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3412 p = (char *)data->notify_data.data.string;
3413 SSVAL(p, 0, st.year);
3414 SSVAL(p, 2, st.month);
3415 SSVAL(p, 4, st.dayofweek);
3416 SSVAL(p, 6, st.day);
3417 SSVAL(p, 8, st.hour);
3418 SSVAL(p, 10, st.minute);
3419 SSVAL(p, 12, st.second);
3420 SSVAL(p, 14, st.milliseconds);
3423 struct s_notify_info_data_table
3429 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3430 print_queue_struct *queue,
3431 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3434 /* A table describing the various print notification constants and
3435 whether the notification data is a pointer to a variable sized
3436 buffer, a one value uint32 or a two value uint32. */
3438 static const struct s_notify_info_data_table notify_info_data_table[] =
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3491 /*******************************************************************
3492 Return the size of info_data structure.
3493 ********************************************************************/
3495 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3499 for (i = 0; i < sizeof(notify_info_data_table); i++)
3501 if ( (notify_info_data_table[i].type == type)
3502 && (notify_info_data_table[i].field == field) )
3504 switch(notify_info_data_table[i].size)
3506 case NOTIFY_ONE_VALUE:
3507 case NOTIFY_TWO_VALUE:
3512 /* The only pointer notify data I have seen on
3513 the wire is the submitted time and this has
3514 the notify size set to 4. -tpot */
3516 case NOTIFY_POINTER:
3519 case NOTIFY_SECDESC:
3525 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3530 /*******************************************************************
3531 Return the type of notify_info_data.
3532 ********************************************************************/
3534 static int type_of_notify_info_data(uint16 type, uint16 field)
3538 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3539 if (notify_info_data_table[i].type == type &&
3540 notify_info_data_table[i].field == field)
3541 return notify_info_data_table[i].size;
3547 /****************************************************************************
3548 ****************************************************************************/
3550 static int search_notify(uint16 type, uint16 field, int *value)
3554 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3555 if (notify_info_data_table[i].type == type &&
3556 notify_info_data_table[i].field == field &&
3557 notify_info_data_table[i].fn != NULL) {
3566 /****************************************************************************
3567 ****************************************************************************/
3569 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3571 info_data->type = type;
3572 info_data->field = field;
3573 info_data->reserved = 0;
3575 info_data->size = size_of_notify_info_data(type, field);
3576 info_data->enc_type = type_of_notify_info_data(type, field);
3583 /*******************************************************************
3585 * fill a notify_info struct with info asked
3587 ********************************************************************/
3589 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3590 snum, SPOOL_NOTIFY_OPTION_TYPE
3591 *option_type, uint32 id,
3592 TALLOC_CTX *mem_ctx)
3598 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3599 NT_PRINTER_INFO_LEVEL *printer = NULL;
3600 print_queue_struct *queue=NULL;
3602 type=option_type->type;
3604 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3605 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3606 option_type->count, lp_servicename(snum)));
3608 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3611 for(field_num=0; field_num<option_type->count; field_num++) {
3612 field = option_type->fields[field_num];
3614 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3616 if (!search_notify(type, field, &j) )
3619 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3620 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3625 current_data = &info->data[info->count];
3627 construct_info_data(current_data, type, field, id);
3629 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3630 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3632 notify_info_data_table[j].fn(snum, current_data, queue,
3638 free_a_printer(&printer, 2);
3642 /*******************************************************************
3644 * fill a notify_info struct with info asked
3646 ********************************************************************/
3648 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3649 SPOOL_NOTIFY_INFO *info,
3650 NT_PRINTER_INFO_LEVEL *printer,
3651 int snum, SPOOL_NOTIFY_OPTION_TYPE
3652 *option_type, uint32 id,
3653 TALLOC_CTX *mem_ctx)
3659 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3661 DEBUG(4,("construct_notify_jobs_info\n"));
3663 type = option_type->type;
3665 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3666 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3667 option_type->count));
3669 for(field_num=0; field_num<option_type->count; field_num++) {
3670 field = option_type->fields[field_num];
3672 if (!search_notify(type, field, &j) )
3675 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3676 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3679 else info->data = tid;
3681 current_data=&(info->data[info->count]);
3683 construct_info_data(current_data, type, field, id);
3684 notify_info_data_table[j].fn(snum, current_data, queue,
3693 * JFM: The enumeration is not that simple, it's even non obvious.
3695 * let's take an example: I want to monitor the PRINTER SERVER for
3696 * the printer's name and the number of jobs currently queued.
3697 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3698 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3700 * I have 3 printers on the back of my server.
3702 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3705 * 1 printer 1 name 1
3706 * 2 printer 1 cjob 1
3707 * 3 printer 2 name 2
3708 * 4 printer 2 cjob 2
3709 * 5 printer 3 name 3
3710 * 6 printer 3 name 3
3712 * that's the print server case, the printer case is even worse.
3715 /*******************************************************************
3717 * enumerate all printers on the printserver
3718 * fill a notify_info struct with info asked
3720 ********************************************************************/
3722 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3723 SPOOL_NOTIFY_INFO *info,
3724 TALLOC_CTX *mem_ctx)
3727 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3728 int n_services=lp_numservices();
3730 SPOOL_NOTIFY_OPTION *option;
3731 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3733 DEBUG(4,("printserver_notify_info\n"));
3738 option=Printer->notify.option;
3743 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3744 sending a ffpcn() request first */
3749 for (i=0; i<option->count; i++) {
3750 option_type=&(option->ctr.type[i]);
3752 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3755 for (snum=0; snum<n_services; snum++)
3757 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3758 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3764 * Debugging information, don't delete.
3767 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3768 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3769 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3771 for (i=0; i<info->count; i++) {
3772 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3773 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3774 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3781 /*******************************************************************
3783 * fill a notify_info struct with info asked
3785 ********************************************************************/
3787 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3788 TALLOC_CTX *mem_ctx)
3791 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3794 SPOOL_NOTIFY_OPTION *option;
3795 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3797 print_queue_struct *queue=NULL;
3798 print_status_struct status;
3800 DEBUG(4,("printer_notify_info\n"));
3805 option=Printer->notify.option;
3811 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3812 sending a ffpcn() request first */
3817 get_printer_snum(p, hnd, &snum);
3819 for (i=0; i<option->count; i++) {
3820 option_type=&option->ctr.type[i];
3822 switch ( option_type->type ) {
3823 case PRINTER_NOTIFY_TYPE:
3824 if(construct_notify_printer_info(Printer, info, snum,
3830 case JOB_NOTIFY_TYPE: {
3831 NT_PRINTER_INFO_LEVEL *printer = NULL;
3833 count = print_queue_status(snum, &queue, &status);
3835 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3838 for (j=0; j<count; j++) {
3839 construct_notify_jobs_info(&queue[j], info,
3846 free_a_printer(&printer, 2);
3856 * Debugging information, don't delete.
3859 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3860 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3861 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3863 for (i=0; i<info->count; i++) {
3864 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3865 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3866 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3872 /********************************************************************
3874 ********************************************************************/
3876 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3878 POLICY_HND *handle = &q_u->handle;
3879 SPOOL_NOTIFY_INFO *info = &r_u->info;
3881 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3882 WERROR result = WERR_BADFID;
3884 /* we always have a NOTIFY_INFO struct */
3888 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3889 OUR_HANDLE(handle)));
3893 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3896 * We are now using the change value, and
3897 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3898 * I don't have a global notification system, I'm sending back all the
3899 * informations even when _NOTHING_ has changed.
3902 /* We need to keep track of the change value to send back in
3903 RRPCN replies otherwise our updates are ignored. */
3905 Printer->notify.fnpcn = True;
3907 if (Printer->notify.client_connected) {
3908 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3909 Printer->notify.change = q_u->change;
3912 /* just ignore the SPOOL_NOTIFY_OPTION */
3914 switch (Printer->printer_type) {
3915 case PRINTER_HANDLE_IS_PRINTSERVER:
3916 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3919 case PRINTER_HANDLE_IS_PRINTER:
3920 result = printer_notify_info(p, handle, info, p->mem_ctx);
3924 Printer->notify.fnpcn = False;
3930 /********************************************************************
3931 * construct_printer_info_0
3932 * fill a printer_info_0 struct
3933 ********************************************************************/
3935 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3939 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3940 counter_printer_0 *session_counter;
3941 uint32 global_counter;
3944 print_status_struct status;
3946 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3949 count = print_queue_length(snum, &status);
3951 /* check if we already have a counter for this printer */
3952 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3954 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3955 if (session_counter->snum == snum)
3959 /* it's the first time, add it to the list */
3960 if (session_counter==NULL) {
3961 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3962 free_a_printer(&ntprinter, 2);
3965 ZERO_STRUCTP(session_counter);
3966 session_counter->snum=snum;
3967 session_counter->counter=0;
3968 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3972 session_counter->counter++;
3975 * the global_counter should be stored in a TDB as it's common to all the clients
3976 * and should be zeroed on samba startup
3978 global_counter=session_counter->counter;
3980 pstrcpy(chaine,ntprinter->info_2->printername);
3982 init_unistr(&printer->printername, chaine);
3984 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3985 init_unistr(&printer->servername, chaine);
3987 printer->cjobs = count;
3988 printer->total_jobs = 0;
3989 printer->total_bytes = 0;
3991 setuptime = (time_t)ntprinter->info_2->setuptime;
3992 t=gmtime(&setuptime);
3994 printer->year = t->tm_year+1900;
3995 printer->month = t->tm_mon+1;
3996 printer->dayofweek = t->tm_wday;
3997 printer->day = t->tm_mday;
3998 printer->hour = t->tm_hour;
3999 printer->minute = t->tm_min;
4000 printer->second = t->tm_sec;
4001 printer->milliseconds = 0;
4003 printer->global_counter = global_counter;
4004 printer->total_pages = 0;
4006 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4007 printer->major_version = 0x0005; /* NT 5 */
4008 printer->build_version = 0x0893; /* build 2195 */
4010 printer->unknown7 = 0x1;
4011 printer->unknown8 = 0x0;
4012 printer->unknown9 = 0x0;
4013 printer->session_counter = session_counter->counter;
4014 printer->unknown11 = 0x0;
4015 printer->printer_errors = 0x0; /* number of print failure */
4016 printer->unknown13 = 0x0;
4017 printer->unknown14 = 0x1;
4018 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4019 printer->unknown16 = 0x0;
4020 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4021 printer->unknown18 = 0x0;
4022 printer->status = nt_printq_status(status.status);
4023 printer->unknown20 = 0x0;
4024 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4025 printer->unknown22 = 0x0;
4026 printer->unknown23 = 0x6; /* 6 ???*/
4027 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4028 printer->unknown25 = 0;
4029 printer->unknown26 = 0;
4030 printer->unknown27 = 0;
4031 printer->unknown28 = 0;
4032 printer->unknown29 = 0;
4034 free_a_printer(&ntprinter,2);
4038 /********************************************************************
4039 * construct_printer_info_1
4040 * fill a printer_info_1 struct
4041 ********************************************************************/
4042 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4046 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4048 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4051 printer->flags=flags;
4053 if (*ntprinter->info_2->comment == '\0') {
4054 init_unistr(&printer->comment, lp_comment(snum));
4055 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4056 ntprinter->info_2->drivername, lp_comment(snum));
4059 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4060 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4061 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4064 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4066 init_unistr(&printer->description, chaine);
4067 init_unistr(&printer->name, chaine2);
4069 free_a_printer(&ntprinter,2);
4074 /****************************************************************************
4075 Free a DEVMODE struct.
4076 ****************************************************************************/
4078 static void free_dev_mode(DEVICEMODE *dev)
4083 SAFE_FREE(dev->private);
4088 /****************************************************************************
4089 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4090 should be valid upon entry
4091 ****************************************************************************/
4093 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4095 if ( !devmode || !ntdevmode )
4098 init_unistr(&devmode->devicename, ntdevmode->devicename);
4100 init_unistr(&devmode->formname, ntdevmode->formname);
4102 devmode->specversion = ntdevmode->specversion;
4103 devmode->driverversion = ntdevmode->driverversion;
4104 devmode->size = ntdevmode->size;
4105 devmode->driverextra = ntdevmode->driverextra;
4106 devmode->fields = ntdevmode->fields;
4108 devmode->orientation = ntdevmode->orientation;
4109 devmode->papersize = ntdevmode->papersize;
4110 devmode->paperlength = ntdevmode->paperlength;
4111 devmode->paperwidth = ntdevmode->paperwidth;
4112 devmode->scale = ntdevmode->scale;
4113 devmode->copies = ntdevmode->copies;
4114 devmode->defaultsource = ntdevmode->defaultsource;
4115 devmode->printquality = ntdevmode->printquality;
4116 devmode->color = ntdevmode->color;
4117 devmode->duplex = ntdevmode->duplex;
4118 devmode->yresolution = ntdevmode->yresolution;
4119 devmode->ttoption = ntdevmode->ttoption;
4120 devmode->collate = ntdevmode->collate;
4121 devmode->icmmethod = ntdevmode->icmmethod;
4122 devmode->icmintent = ntdevmode->icmintent;
4123 devmode->mediatype = ntdevmode->mediatype;
4124 devmode->dithertype = ntdevmode->dithertype;
4126 if (ntdevmode->private != NULL) {
4127 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4134 /****************************************************************************
4135 Create a DEVMODE struct. Returns malloced memory.
4136 ****************************************************************************/
4138 DEVICEMODE *construct_dev_mode(int snum)
4140 NT_PRINTER_INFO_LEVEL *printer = NULL;
4141 DEVICEMODE *devmode = NULL;
4143 DEBUG(7,("construct_dev_mode\n"));
4145 DEBUGADD(8,("getting printer characteristics\n"));
4147 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4150 if ( !printer->info_2->devmode ) {
4151 DEBUG(5, ("BONG! There was no device mode!\n"));
4155 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4156 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4160 ZERO_STRUCTP(devmode);
4162 DEBUGADD(8,("loading DEVICEMODE\n"));
4164 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4165 free_dev_mode( devmode );
4170 free_a_printer(&printer,2);
4175 /********************************************************************
4176 * construct_printer_info_2
4177 * fill a printer_info_2 struct
4178 ********************************************************************/
4180 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4183 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4185 print_status_struct status;
4187 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4190 count = print_queue_length(snum, &status);
4192 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4193 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4194 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4195 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4196 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4198 if (*ntprinter->info_2->comment == '\0')
4199 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4201 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4203 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4204 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4205 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4206 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4207 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4209 printer->attributes = ntprinter->info_2->attributes;
4211 printer->priority = ntprinter->info_2->priority; /* priority */
4212 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4213 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4214 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4215 printer->status = nt_printq_status(status.status); /* status */
4216 printer->cjobs = count; /* jobs */
4217 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4219 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4220 DEBUG(8, ("Returning NULL Devicemode!\n"));
4223 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4224 /* steal the printer info sec_desc structure. [badly done]. */
4225 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4226 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4227 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4228 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4231 printer->secdesc = NULL;
4234 free_a_printer(&ntprinter, 2);
4238 /********************************************************************
4239 * construct_printer_info_3
4240 * fill a printer_info_3 struct
4241 ********************************************************************/
4243 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4245 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4246 PRINTER_INFO_3 *printer = NULL;
4248 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4252 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4253 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4257 ZERO_STRUCTP(printer);
4259 printer->flags = 4; /* These are the components of the SD we are returning. */
4260 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4261 /* steal the printer info sec_desc structure. [badly done]. */
4262 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4266 * Set the flags for the components we are returning.
4269 if (printer->secdesc->owner_sid)
4270 printer->flags |= OWNER_SECURITY_INFORMATION;
4272 if (printer->secdesc->grp_sid)
4273 printer->flags |= GROUP_SECURITY_INFORMATION;
4275 if (printer->secdesc->dacl)
4276 printer->flags |= DACL_SECURITY_INFORMATION;
4278 if (printer->secdesc->sacl)
4279 printer->flags |= SACL_SECURITY_INFORMATION;
4282 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4283 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4284 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4287 free_a_printer(&ntprinter, 2);
4289 *pp_printer = printer;
4293 /********************************************************************
4294 * construct_printer_info_4
4295 * fill a printer_info_4 struct
4296 ********************************************************************/
4298 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4300 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4302 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4305 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4306 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4307 printer->attributes = ntprinter->info_2->attributes;
4309 free_a_printer(&ntprinter, 2);
4313 /********************************************************************
4314 * construct_printer_info_5
4315 * fill a printer_info_5 struct
4316 ********************************************************************/
4318 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4320 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4322 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4325 init_unistr(&printer->printername, ntprinter->info_2->printername);
4326 init_unistr(&printer->portname, ntprinter->info_2->portname);
4327 printer->attributes = ntprinter->info_2->attributes;
4329 /* these two are not used by NT+ according to MSDN */
4331 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4332 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4334 free_a_printer(&ntprinter, 2);
4339 /********************************************************************
4340 * construct_printer_info_7
4341 * fill a printer_info_7 struct
4342 ********************************************************************/
4344 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4346 char *guid_str = NULL;
4349 if (is_printer_published(print_hnd, snum, &guid)) {
4350 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4351 strupper_m(guid_str);
4352 init_unistr(&printer->guid, guid_str);
4353 printer->action = SPOOL_DS_PUBLISH;
4355 init_unistr(&printer->guid, "");
4356 printer->action = SPOOL_DS_UNPUBLISH;
4362 /********************************************************************
4363 Spoolss_enumprinters.
4364 ********************************************************************/
4366 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4370 int n_services=lp_numservices();
4371 PRINTER_INFO_1 *tp, *printers=NULL;
4372 PRINTER_INFO_1 current_prt;
4374 DEBUG(4,("enum_all_printers_info_1\n"));
4376 for (snum=0; snum<n_services; snum++) {
4377 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4378 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4380 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4381 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4382 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4383 SAFE_FREE(printers);
4388 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4390 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4396 /* check the required size. */
4397 for (i=0; i<*returned; i++)
4398 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4400 if (!alloc_buffer_size(buffer, *needed))
4401 return WERR_INSUFFICIENT_BUFFER;
4403 /* fill the buffer with the structures */
4404 for (i=0; i<*returned; i++)
4405 smb_io_printer_info_1("", buffer, &printers[i], 0);
4408 SAFE_FREE(printers);
4410 if (*needed > offered) {
4412 return WERR_INSUFFICIENT_BUFFER;
4418 /********************************************************************
4419 enum_all_printers_info_1_local.
4420 *********************************************************************/
4422 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4424 DEBUG(4,("enum_all_printers_info_1_local\n"));
4426 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4429 /********************************************************************
4430 enum_all_printers_info_1_name.
4431 *********************************************************************/
4433 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4437 DEBUG(4,("enum_all_printers_info_1_name\n"));
4439 if ((name[0] == '\\') && (name[1] == '\\'))
4442 if (is_myname_or_ipaddr(s)) {
4443 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4446 return WERR_INVALID_NAME;
4449 /********************************************************************
4450 enum_all_printers_info_1_remote.
4451 *********************************************************************/
4453 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4455 PRINTER_INFO_1 *printer;
4456 fstring printername;
4459 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4461 /* JFM: currently it's more a place holder than anything else.
4462 * In the spooler world there is a notion of server registration.
4463 * the print servers are registring (sp ?) on the PDC (in the same domain)
4465 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4468 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4473 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4474 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4475 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4477 init_unistr(&printer->description, desc);
4478 init_unistr(&printer->name, printername);
4479 init_unistr(&printer->comment, comment);
4480 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4482 /* check the required size. */
4483 *needed += spoolss_size_printer_info_1(printer);
4485 if (!alloc_buffer_size(buffer, *needed)) {
4487 return WERR_INSUFFICIENT_BUFFER;
4490 /* fill the buffer with the structures */
4491 smb_io_printer_info_1("", buffer, printer, 0);
4496 if (*needed > offered) {
4498 return WERR_INSUFFICIENT_BUFFER;
4504 /********************************************************************
4505 enum_all_printers_info_1_network.
4506 *********************************************************************/
4508 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4512 DEBUG(4,("enum_all_printers_info_1_network\n"));
4514 /* If we respond to a enum_printers level 1 on our name with flags
4515 set to PRINTER_ENUM_REMOTE with a list of printers then these
4516 printers incorrectly appear in the APW browse list.
4517 Specifically the printers for the server appear at the workgroup
4518 level where all the other servers in the domain are
4519 listed. Windows responds to this call with a
4520 WERR_CAN_NOT_COMPLETE so we should do the same. */
4522 if (name[0] == '\\' && name[1] == '\\')
4525 if (is_myname_or_ipaddr(s))
4526 return WERR_CAN_NOT_COMPLETE;
4528 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4531 /********************************************************************
4532 * api_spoolss_enumprinters
4534 * called from api_spoolss_enumprinters (see this to understand)
4535 ********************************************************************/
4537 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4541 int n_services=lp_numservices();
4542 PRINTER_INFO_2 *tp, *printers=NULL;
4543 PRINTER_INFO_2 current_prt;
4545 for (snum=0; snum<n_services; snum++) {
4546 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4547 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4549 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4550 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4551 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4552 SAFE_FREE(printers);
4557 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4558 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4564 /* check the required size. */
4565 for (i=0; i<*returned; i++)
4566 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4568 if (!alloc_buffer_size(buffer, *needed)) {
4569 for (i=0; i<*returned; i++) {
4570 free_devmode(printers[i].devmode);
4572 SAFE_FREE(printers);
4573 return WERR_INSUFFICIENT_BUFFER;
4576 /* fill the buffer with the structures */
4577 for (i=0; i<*returned; i++)
4578 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4581 for (i=0; i<*returned; i++) {
4582 free_devmode(printers[i].devmode);
4584 SAFE_FREE(printers);
4586 if (*needed > offered) {
4588 return WERR_INSUFFICIENT_BUFFER;
4594 /********************************************************************
4595 * handle enumeration of printers at level 1
4596 ********************************************************************/
4598 static WERROR enumprinters_level1( uint32 flags, fstring name,
4599 NEW_BUFFER *buffer, uint32 offered,
4600 uint32 *needed, uint32 *returned)
4602 /* Not all the flags are equals */
4604 if (flags & PRINTER_ENUM_LOCAL)
4605 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4607 if (flags & PRINTER_ENUM_NAME)
4608 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4610 if (flags & PRINTER_ENUM_REMOTE)
4611 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4613 if (flags & PRINTER_ENUM_NETWORK)
4614 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4616 return WERR_OK; /* NT4sp5 does that */
4619 /********************************************************************
4620 * handle enumeration of printers at level 2
4621 ********************************************************************/
4623 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4624 NEW_BUFFER *buffer, uint32 offered,
4625 uint32 *needed, uint32 *returned)
4627 char *s = servername;
4629 if (flags & PRINTER_ENUM_LOCAL) {
4630 return enum_all_printers_info_2(buffer, offered, needed, returned);
4633 if (flags & PRINTER_ENUM_NAME) {
4634 if ((servername[0] == '\\') && (servername[1] == '\\'))
4636 if (is_myname_or_ipaddr(s))
4637 return enum_all_printers_info_2(buffer, offered, needed, returned);
4639 return WERR_INVALID_NAME;
4642 if (flags & PRINTER_ENUM_REMOTE)
4643 return WERR_UNKNOWN_LEVEL;
4648 /********************************************************************
4649 * handle enumeration of printers at level 5
4650 ********************************************************************/
4652 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4653 NEW_BUFFER *buffer, uint32 offered,
4654 uint32 *needed, uint32 *returned)
4656 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4660 /********************************************************************
4661 * api_spoolss_enumprinters
4663 * called from api_spoolss_enumprinters (see this to understand)
4664 ********************************************************************/
4666 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4668 uint32 flags = q_u->flags;
4669 UNISTR2 *servername = &q_u->servername;
4670 uint32 level = q_u->level;
4671 NEW_BUFFER *buffer = NULL;
4672 uint32 offered = q_u->offered;
4673 uint32 *needed = &r_u->needed;
4674 uint32 *returned = &r_u->returned;
4678 /* that's an [in out] buffer */
4679 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4680 buffer = r_u->buffer;
4682 DEBUG(4,("_spoolss_enumprinters\n"));
4689 * flags==PRINTER_ENUM_NAME
4690 * if name=="" then enumerates all printers
4691 * if name!="" then enumerate the printer
4692 * flags==PRINTER_ENUM_REMOTE
4693 * name is NULL, enumerate printers
4694 * Level 2: name!="" enumerates printers, name can't be NULL
4695 * Level 3: doesn't exist
4696 * Level 4: does a local registry lookup
4697 * Level 5: same as Level 2
4700 unistr2_to_ascii(name, servername, sizeof(name)-1);
4705 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4707 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4709 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4714 return WERR_UNKNOWN_LEVEL;
4717 /****************************************************************************
4718 ****************************************************************************/
4720 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4722 PRINTER_INFO_0 *printer=NULL;
4724 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4727 construct_printer_info_0(print_hnd, printer, snum);
4729 /* check the required size. */
4730 *needed += spoolss_size_printer_info_0(printer);
4732 if (!alloc_buffer_size(buffer, *needed)) {
4734 return WERR_INSUFFICIENT_BUFFER;
4737 /* fill the buffer with the structures */
4738 smb_io_printer_info_0("", buffer, printer, 0);
4743 if (*needed > offered) {
4744 return WERR_INSUFFICIENT_BUFFER;
4750 /****************************************************************************
4751 ****************************************************************************/
4753 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4755 PRINTER_INFO_1 *printer=NULL;
4757 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4760 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4762 /* check the required size. */
4763 *needed += spoolss_size_printer_info_1(printer);
4765 if (!alloc_buffer_size(buffer, *needed)) {
4767 return WERR_INSUFFICIENT_BUFFER;
4770 /* fill the buffer with the structures */
4771 smb_io_printer_info_1("", buffer, printer, 0);
4776 if (*needed > offered) {
4777 return WERR_INSUFFICIENT_BUFFER;
4783 /****************************************************************************
4784 ****************************************************************************/
4786 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4788 PRINTER_INFO_2 *printer=NULL;
4790 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4793 construct_printer_info_2(print_hnd, printer, snum);
4795 /* check the required size. */
4796 *needed += spoolss_size_printer_info_2(printer);
4798 if (!alloc_buffer_size(buffer, *needed)) {
4799 free_printer_info_2(printer);
4800 return WERR_INSUFFICIENT_BUFFER;
4803 /* fill the buffer with the structures */
4804 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4805 free_printer_info_2(printer);
4810 free_printer_info_2(printer);
4812 if (*needed > offered) {
4813 return WERR_INSUFFICIENT_BUFFER;
4819 /****************************************************************************
4820 ****************************************************************************/
4822 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4824 PRINTER_INFO_3 *printer=NULL;
4826 if (!construct_printer_info_3(print_hnd, &printer, snum))
4829 /* check the required size. */
4830 *needed += spoolss_size_printer_info_3(printer);
4832 if (!alloc_buffer_size(buffer, *needed)) {
4833 free_printer_info_3(printer);
4834 return WERR_INSUFFICIENT_BUFFER;
4837 /* fill the buffer with the structures */
4838 smb_io_printer_info_3("", buffer, printer, 0);
4841 free_printer_info_3(printer);
4843 if (*needed > offered) {
4844 return WERR_INSUFFICIENT_BUFFER;
4850 /****************************************************************************
4851 ****************************************************************************/
4853 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4855 PRINTER_INFO_4 *printer=NULL;
4857 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4860 if (!construct_printer_info_4(print_hnd, printer, snum))
4863 /* check the required size. */
4864 *needed += spoolss_size_printer_info_4(printer);
4866 if (!alloc_buffer_size(buffer, *needed)) {
4867 free_printer_info_4(printer);
4868 return WERR_INSUFFICIENT_BUFFER;
4871 /* fill the buffer with the structures */
4872 smb_io_printer_info_4("", buffer, printer, 0);
4875 free_printer_info_4(printer);
4877 if (*needed > offered) {
4878 return WERR_INSUFFICIENT_BUFFER;
4884 /****************************************************************************
4885 ****************************************************************************/
4887 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4889 PRINTER_INFO_5 *printer=NULL;
4891 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4894 if (!construct_printer_info_5(print_hnd, printer, snum))
4897 /* check the required size. */
4898 *needed += spoolss_size_printer_info_5(printer);
4900 if (!alloc_buffer_size(buffer, *needed)) {
4901 free_printer_info_5(printer);
4902 return WERR_INSUFFICIENT_BUFFER;
4905 /* fill the buffer with the structures */
4906 smb_io_printer_info_5("", buffer, printer, 0);
4909 free_printer_info_5(printer);
4911 if (*needed > offered) {
4912 return WERR_INSUFFICIENT_BUFFER;
4918 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4920 PRINTER_INFO_7 *printer=NULL;
4922 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4925 if (!construct_printer_info_7(print_hnd, printer, snum))
4928 /* check the required size. */
4929 *needed += spoolss_size_printer_info_7(printer);
4931 if (!alloc_buffer_size(buffer, *needed)) {
4932 free_printer_info_7(printer);
4933 return WERR_INSUFFICIENT_BUFFER;
4936 /* fill the buffer with the structures */
4937 smb_io_printer_info_7("", buffer, printer, 0);
4940 free_printer_info_7(printer);
4942 if (*needed > offered) {
4943 return WERR_INSUFFICIENT_BUFFER;
4949 /****************************************************************************
4950 ****************************************************************************/
4952 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4954 POLICY_HND *handle = &q_u->handle;
4955 uint32 level = q_u->level;
4956 NEW_BUFFER *buffer = NULL;
4957 uint32 offered = q_u->offered;
4958 uint32 *needed = &r_u->needed;
4959 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4963 /* that's an [in out] buffer */
4964 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4965 buffer = r_u->buffer;
4969 if (!get_printer_snum(p, handle, &snum))
4974 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4976 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4978 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4980 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4982 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4984 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4986 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4988 return WERR_UNKNOWN_LEVEL;
4991 /********************************************************************
4992 * fill a DRIVER_INFO_1 struct
4993 ********************************************************************/
4995 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4997 init_unistr( &info->name, driver.info_3->name);
5000 /********************************************************************
5001 * construct_printer_driver_info_1
5002 ********************************************************************/
5004 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5006 NT_PRINTER_INFO_LEVEL *printer = NULL;
5007 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5009 ZERO_STRUCT(driver);
5011 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5012 return WERR_INVALID_PRINTER_NAME;
5014 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5015 return WERR_UNKNOWN_PRINTER_DRIVER;
5017 fill_printer_driver_info_1(info, driver, servername, architecture);
5019 free_a_printer(&printer,2);
5024 /********************************************************************
5025 * construct_printer_driver_info_2
5026 * fill a printer_info_2 struct
5027 ********************************************************************/
5029 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5033 info->version=driver.info_3->cversion;
5035 init_unistr( &info->name, driver.info_3->name );
5036 init_unistr( &info->architecture, driver.info_3->environment );
5039 if (strlen(driver.info_3->driverpath)) {
5040 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5041 init_unistr( &info->driverpath, temp );
5043 init_unistr( &info->driverpath, "" );
5045 if (strlen(driver.info_3->datafile)) {
5046 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5047 init_unistr( &info->datafile, temp );
5049 init_unistr( &info->datafile, "" );
5051 if (strlen(driver.info_3->configfile)) {
5052 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5053 init_unistr( &info->configfile, temp );
5055 init_unistr( &info->configfile, "" );
5058 /********************************************************************
5059 * construct_printer_driver_info_2
5060 * fill a printer_info_2 struct
5061 ********************************************************************/
5063 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5065 NT_PRINTER_INFO_LEVEL *printer = NULL;
5066 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5068 ZERO_STRUCT(printer);
5069 ZERO_STRUCT(driver);
5071 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5072 return WERR_INVALID_PRINTER_NAME;
5074 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5075 return WERR_UNKNOWN_PRINTER_DRIVER;
5077 fill_printer_driver_info_2(info, driver, servername);
5079 free_a_printer(&printer,2);
5084 /********************************************************************
5085 * copy a strings array and convert to UNICODE
5087 * convert an array of ascii string to a UNICODE string
5088 ********************************************************************/
5090 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5098 DEBUG(6,("init_unistr_array\n"));
5109 v = ""; /* hack to handle null lists */
5112 /* hack to allow this to be used in places other than when generating
5113 the list of dependent files */
5116 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5120 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5122 /* add one extra unit16 for the second terminating NULL */
5124 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5125 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5133 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5138 /* special case for ""; we need to add both NULL's here */
5140 (*uni_array)[j++]=0x0000;
5141 (*uni_array)[j]=0x0000;
5144 DEBUGADD(6,("last one:done\n"));
5146 /* return size of array in uint16's */
5151 /********************************************************************
5152 * construct_printer_info_3
5153 * fill a printer_info_3 struct
5154 ********************************************************************/
5156 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5162 info->version=driver.info_3->cversion;
5164 init_unistr( &info->name, driver.info_3->name );
5165 init_unistr( &info->architecture, driver.info_3->environment );
5167 if (strlen(driver.info_3->driverpath)) {
5168 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5169 init_unistr( &info->driverpath, temp );
5171 init_unistr( &info->driverpath, "" );
5173 if (strlen(driver.info_3->datafile)) {
5174 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5175 init_unistr( &info->datafile, temp );
5177 init_unistr( &info->datafile, "" );
5179 if (strlen(driver.info_3->configfile)) {
5180 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5181 init_unistr( &info->configfile, temp );
5183 init_unistr( &info->configfile, "" );
5185 if (strlen(driver.info_3->helpfile)) {
5186 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5187 init_unistr( &info->helpfile, temp );
5189 init_unistr( &info->helpfile, "" );
5191 init_unistr( &info->monitorname, driver.info_3->monitorname );
5192 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5194 info->dependentfiles=NULL;
5195 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5198 /********************************************************************
5199 * construct_printer_info_3
5200 * fill a printer_info_3 struct
5201 ********************************************************************/
5203 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5205 NT_PRINTER_INFO_LEVEL *printer = NULL;
5206 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5208 ZERO_STRUCT(driver);
5210 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5211 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5212 if (!W_ERROR_IS_OK(status))
5213 return WERR_INVALID_PRINTER_NAME;
5215 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5216 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5221 * I put this code in during testing. Helpful when commenting out the
5222 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5223 * as win2k always queries the driver using an infor level of 6.
5224 * I've left it in (but ifdef'd out) because I'll probably
5225 * use it in experimentation again in the future. --jerry 22/01/2002
5228 if (!W_ERROR_IS_OK(status)) {
5230 * Is this a W2k client ?
5233 /* Yes - try again with a WinNT driver. */
5235 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5236 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5240 if (!W_ERROR_IS_OK(status)) {
5241 free_a_printer(&printer,2);
5242 return WERR_UNKNOWN_PRINTER_DRIVER;
5250 fill_printer_driver_info_3(info, driver, servername);
5252 free_a_printer(&printer,2);
5257 /********************************************************************
5258 * construct_printer_info_6
5259 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5260 ********************************************************************/
5262 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5268 memset(&nullstr, '\0', sizeof(fstring));
5270 info->version=driver.info_3->cversion;
5272 init_unistr( &info->name, driver.info_3->name );
5273 init_unistr( &info->architecture, driver.info_3->environment );
5275 if (strlen(driver.info_3->driverpath)) {
5276 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5277 init_unistr( &info->driverpath, temp );
5279 init_unistr( &info->driverpath, "" );
5281 if (strlen(driver.info_3->datafile)) {
5282 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5283 init_unistr( &info->datafile, temp );
5285 init_unistr( &info->datafile, "" );
5287 if (strlen(driver.info_3->configfile)) {
5288 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5289 init_unistr( &info->configfile, temp );
5291 init_unistr( &info->configfile, "" );
5293 if (strlen(driver.info_3->helpfile)) {
5294 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5295 init_unistr( &info->helpfile, temp );
5297 init_unistr( &info->helpfile, "" );
5299 init_unistr( &info->monitorname, driver.info_3->monitorname );
5300 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5302 info->dependentfiles = NULL;
5303 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5305 info->previousdrivernames=NULL;
5306 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5308 info->driver_date.low=0;
5309 info->driver_date.high=0;
5312 info->driver_version_low=0;
5313 info->driver_version_high=0;
5315 init_unistr( &info->mfgname, "");
5316 init_unistr( &info->oem_url, "");
5317 init_unistr( &info->hardware_id, "");
5318 init_unistr( &info->provider, "");
5321 /********************************************************************
5322 * construct_printer_info_6
5323 * fill a printer_info_6 struct
5324 ********************************************************************/
5326 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5327 fstring servername, fstring architecture, uint32 version)
5329 NT_PRINTER_INFO_LEVEL *printer = NULL;
5330 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5333 ZERO_STRUCT(driver);
5335 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5337 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5339 if (!W_ERROR_IS_OK(status))
5340 return WERR_INVALID_PRINTER_NAME;
5342 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5344 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5346 if (!W_ERROR_IS_OK(status))
5349 * Is this a W2k client ?
5353 free_a_printer(&printer,2);
5354 return WERR_UNKNOWN_PRINTER_DRIVER;
5357 /* Yes - try again with a WinNT driver. */
5359 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5360 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5361 if (!W_ERROR_IS_OK(status)) {
5362 free_a_printer(&printer,2);
5363 return WERR_UNKNOWN_PRINTER_DRIVER;
5367 fill_printer_driver_info_6(info, driver, servername);
5369 free_a_printer(&printer,2);
5370 free_a_printer_driver(driver, 3);
5375 /****************************************************************************
5376 ****************************************************************************/
5378 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5380 SAFE_FREE(info->dependentfiles);
5383 /****************************************************************************
5384 ****************************************************************************/
5386 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5388 SAFE_FREE(info->dependentfiles);
5392 /****************************************************************************
5393 ****************************************************************************/
5395 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5397 DRIVER_INFO_1 *info=NULL;
5400 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5403 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5404 if (!W_ERROR_IS_OK(status)) {
5409 /* check the required size. */
5410 *needed += spoolss_size_printer_driver_info_1(info);
5412 if (!alloc_buffer_size(buffer, *needed)) {
5414 return WERR_INSUFFICIENT_BUFFER;
5417 /* fill the buffer with the structures */
5418 smb_io_printer_driver_info_1("", buffer, info, 0);
5423 if (*needed > offered)
5424 return WERR_INSUFFICIENT_BUFFER;
5429 /****************************************************************************
5430 ****************************************************************************/
5432 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5434 DRIVER_INFO_2 *info=NULL;
5437 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5440 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5441 if (!W_ERROR_IS_OK(status)) {
5446 /* check the required size. */
5447 *needed += spoolss_size_printer_driver_info_2(info);
5449 if (!alloc_buffer_size(buffer, *needed)) {
5451 return WERR_INSUFFICIENT_BUFFER;
5454 /* fill the buffer with the structures */
5455 smb_io_printer_driver_info_2("", buffer, info, 0);
5460 if (*needed > offered)
5461 return WERR_INSUFFICIENT_BUFFER;
5466 /****************************************************************************
5467 ****************************************************************************/
5469 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5476 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5477 if (!W_ERROR_IS_OK(status)) {
5481 /* check the required size. */
5482 *needed += spoolss_size_printer_driver_info_3(&info);
5484 if (!alloc_buffer_size(buffer, *needed)) {
5485 free_printer_driver_info_3(&info);
5486 return WERR_INSUFFICIENT_BUFFER;
5489 /* fill the buffer with the structures */
5490 smb_io_printer_driver_info_3("", buffer, &info, 0);
5492 free_printer_driver_info_3(&info);
5494 if (*needed > offered)
5495 return WERR_INSUFFICIENT_BUFFER;
5500 /****************************************************************************
5501 ****************************************************************************/
5503 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5510 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5511 if (!W_ERROR_IS_OK(status)) {
5515 /* check the required size. */
5516 *needed += spoolss_size_printer_driver_info_6(&info);
5518 if (!alloc_buffer_size(buffer, *needed)) {
5519 free_printer_driver_info_6(&info);
5520 return WERR_INSUFFICIENT_BUFFER;
5523 /* fill the buffer with the structures */
5524 smb_io_printer_driver_info_6("", buffer, &info, 0);
5526 free_printer_driver_info_6(&info);
5528 if (*needed > offered)
5529 return WERR_INSUFFICIENT_BUFFER;
5534 /****************************************************************************
5535 ****************************************************************************/
5537 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5539 POLICY_HND *handle = &q_u->handle;
5540 UNISTR2 *uni_arch = &q_u->architecture;
5541 uint32 level = q_u->level;
5542 uint32 clientmajorversion = q_u->clientmajorversion;
5543 NEW_BUFFER *buffer = NULL;
5544 uint32 offered = q_u->offered;
5545 uint32 *needed = &r_u->needed;
5546 uint32 *servermajorversion = &r_u->servermajorversion;
5547 uint32 *serverminorversion = &r_u->serverminorversion;
5550 fstring architecture;
5553 /* that's an [in out] buffer */
5554 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5555 buffer = r_u->buffer;
5557 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5560 *servermajorversion = 0;
5561 *serverminorversion = 0;
5563 fstrcpy(servername, get_called_name());
5564 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5566 if (!get_printer_snum(p, handle, &snum))
5571 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5573 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5575 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5577 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5580 return WERR_UNKNOWN_LEVEL;
5583 /****************************************************************************
5584 ****************************************************************************/
5586 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5588 POLICY_HND *handle = &q_u->handle;
5590 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5593 DEBUG(3,("Error in startpageprinter printer handle\n"));
5597 Printer->page_started=True;
5601 /****************************************************************************
5602 ****************************************************************************/
5604 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5606 POLICY_HND *handle = &q_u->handle;
5609 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5612 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5616 if (!get_printer_snum(p, handle, &snum))
5619 Printer->page_started=False;
5620 print_job_endpage(snum, Printer->jobid);
5625 /********************************************************************
5626 * api_spoolss_getprinter
5627 * called from the spoolss dispatcher
5629 ********************************************************************/
5631 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5633 POLICY_HND *handle = &q_u->handle;
5634 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5635 uint32 *jobid = &r_u->jobid;
5637 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5641 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5642 struct current_user user;
5645 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5649 get_current_user(&user, p);
5652 * a nice thing with NT is it doesn't listen to what you tell it.
5653 * when asked to send _only_ RAW datas, it tries to send datas
5656 * So I add checks like in NT Server ...
5659 if (info_1->p_datatype != 0) {
5660 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5661 if (strcmp(datatype, "RAW") != 0) {
5663 return WERR_INVALID_DATATYPE;
5667 /* get the share number of the printer */
5668 if (!get_printer_snum(p, handle, &snum)) {
5672 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5674 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5676 /* An error occured in print_job_start() so return an appropriate
5679 if (Printer->jobid == -1) {
5680 return map_werror_from_unix(errno);
5683 Printer->document_started=True;
5684 (*jobid) = Printer->jobid;
5689 /********************************************************************
5690 * api_spoolss_getprinter
5691 * called from the spoolss dispatcher
5693 ********************************************************************/
5695 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5697 POLICY_HND *handle = &q_u->handle;
5699 return _spoolss_enddocprinter_internal(p, handle);
5702 /****************************************************************************
5703 ****************************************************************************/
5705 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5707 POLICY_HND *handle = &q_u->handle;
5708 uint32 buffer_size = q_u->buffer_size;
5709 uint8 *buffer = q_u->buffer;
5710 uint32 *buffer_written = &q_u->buffer_size2;
5712 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5715 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5716 r_u->buffer_written = q_u->buffer_size2;
5720 if (!get_printer_snum(p, handle, &snum))
5723 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5724 if (*buffer_written == -1) {
5725 r_u->buffer_written = 0;
5726 if (errno == ENOSPC)
5727 return WERR_NO_SPOOL_SPACE;
5729 return WERR_ACCESS_DENIED;
5732 r_u->buffer_written = q_u->buffer_size2;
5737 /********************************************************************
5738 * api_spoolss_getprinter
5739 * called from the spoolss dispatcher
5741 ********************************************************************/
5743 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5746 struct current_user user;
5748 WERROR errcode = WERR_BADFUNC;
5749 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5751 get_current_user(&user, p);
5754 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5758 if (!get_printer_snum(p, handle, &snum))
5762 case PRINTER_CONTROL_PAUSE:
5763 if (print_queue_pause(&user, snum, &errcode)) {
5767 case PRINTER_CONTROL_RESUME:
5768 case PRINTER_CONTROL_UNPAUSE:
5769 if (print_queue_resume(&user, snum, &errcode)) {
5773 case PRINTER_CONTROL_PURGE:
5774 if (print_queue_purge(&user, snum, &errcode)) {
5779 return WERR_UNKNOWN_LEVEL;
5785 /********************************************************************
5786 * api_spoolss_abortprinter
5787 * From MSDN: "Deletes printer's spool file if printer is configured
5789 ********************************************************************/
5791 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5793 POLICY_HND *handle = &q_u->handle;
5794 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5796 struct current_user user;
5797 WERROR errcode = WERR_OK;
5800 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5804 if (!get_printer_snum(p, handle, &snum))
5807 get_current_user( &user, p );
5809 print_job_delete( &user, snum, Printer->jobid, &errcode );
5814 /********************************************************************
5815 * called by spoolss_api_setprinter
5816 * when updating a printer description
5817 ********************************************************************/
5819 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5820 const SPOOL_PRINTER_INFO_LEVEL *info,
5821 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5823 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5824 struct current_user user;
5828 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5830 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5831 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5832 OUR_HANDLE(handle)));
5834 result = WERR_BADFID;
5838 /* NT seems to like setting the security descriptor even though
5839 nothing may have actually changed. This causes annoying
5840 dialog boxes when the user doesn't have permission to change
5841 the security descriptor. */
5843 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5845 if (DEBUGLEVEL >= 10) {
5849 the_acl = old_secdesc_ctr->sec->dacl;
5850 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5851 PRINTERNAME(snum), the_acl->num_aces));
5853 for (i = 0; i < the_acl->num_aces; i++) {
5856 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5858 DEBUG(10, ("%s 0x%08x\n", sid_str,
5859 the_acl->ace[i].info.mask));
5862 the_acl = secdesc_ctr->sec->dacl;
5865 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5866 PRINTERNAME(snum), the_acl->num_aces));
5868 for (i = 0; i < the_acl->num_aces; i++) {
5871 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5873 DEBUG(10, ("%s 0x%08x\n", sid_str,
5874 the_acl->ace[i].info.mask));
5877 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5881 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5883 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5888 /* Work out which user is performing the operation */
5890 get_current_user(&user, p);
5892 /* Check the user has permissions to change the security
5893 descriptor. By experimentation with two NT machines, the user
5894 requires Full Access to the printer to change security
5897 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5898 result = WERR_ACCESS_DENIED;
5902 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5909 /********************************************************************
5910 Do Samba sanity checks on a printer info struct.
5911 this has changed purpose: it now "canonicalises" printer
5912 info from a client rather than just checking it is correct
5913 ********************************************************************/
5915 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5917 fstring printername;
5920 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5921 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5923 /* we force some elements to "correct" values */
5924 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5925 fstrcpy(info->sharename, lp_servicename(snum));
5927 /* make sure printername is in \\server\printername format */
5929 fstrcpy( printername, info->printername );
5931 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5932 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5936 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5937 get_called_name(), p );
5939 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5945 /****************************************************************************
5946 ****************************************************************************/
5948 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5950 extern userdom_struct current_user_info;
5951 char *cmd = lp_addprinter_cmd();
5957 fstring remote_machine = "%m";
5959 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5961 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5962 cmd, printer->info_2->printername, printer->info_2->sharename,
5963 printer->info_2->portname, printer->info_2->drivername,
5964 printer->info_2->location, printer->info_2->comment, remote_machine);
5966 DEBUG(10,("Running [%s]\n", command));
5967 ret = smbrun(command, &fd);
5968 DEBUGADD(10,("returned [%d]\n", ret));
5977 /* Get lines and convert them back to dos-codepage */
5978 qlines = fd_lines_load(fd, &numlines);
5979 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5983 /* Set the portname to what the script says the portname should be. */
5984 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5985 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5987 /* Send SIGHUP to process group... is there a better way? */
5990 /* reload our services immediately */
5991 reload_services( False );
5994 file_lines_free(qlines);
5998 /********************************************************************
5999 * Called by spoolss_api_setprinter
6000 * when updating a printer description.
6001 ********************************************************************/
6003 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6004 const SPOOL_PRINTER_INFO_LEVEL *info,
6005 DEVICEMODE *devmode)
6008 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6009 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6014 DEBUG(8,("update_printer\n"));
6019 result = WERR_BADFID;
6023 if (!get_printer_snum(p, handle, &snum)) {
6024 result = WERR_BADFID;
6028 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6029 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6030 result = WERR_BADFID;
6034 DEBUGADD(8,("Converting info_2 struct\n"));
6037 * convert_printer_info converts the incoming
6038 * info from the client and overwrites the info
6039 * just read from the tdb in the pointer 'printer'.
6042 if (!convert_printer_info(info, printer, level)) {
6043 result = WERR_NOMEM;
6048 /* we have a valid devmode
6049 convert it and link it*/
6051 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6052 if (!convert_devicemode(printer->info_2->printername, devmode,
6053 &printer->info_2->devmode)) {
6054 result = WERR_NOMEM;
6059 /* Do sanity check on the requested changes for Samba */
6061 if (!check_printer_ok(printer->info_2, snum)) {
6062 result = WERR_INVALID_PARAM;
6066 /* FIXME!!! If the driver has changed we really should verify that
6067 it is installed before doing much else --jerry */
6069 /* Check calling user has permission to update printer description */
6071 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6072 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6073 result = WERR_ACCESS_DENIED;
6077 /* Call addprinter hook */
6078 /* Check changes to see if this is really needed */
6080 if ( *lp_addprinter_cmd()
6081 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6082 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6083 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6084 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6086 if ( !add_printer_hook(printer) ) {
6087 result = WERR_ACCESS_DENIED;
6092 * make sure we actually reload the services after
6093 * this as smb.conf could have a new section in it
6094 * .... shouldn't .... but could
6096 reload_services(False);
6100 * When a *new* driver is bound to a printer, the drivername is used to
6101 * lookup previously saved driver initialization info, which is then
6102 * bound to the printer, simulating what happens in the Windows arch.
6104 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6106 if (!set_driver_init(printer, 2))
6108 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6109 printer->info_2->drivername));
6112 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6113 printer->info_2->drivername));
6115 notify_printer_driver(snum, printer->info_2->drivername);
6119 * flag which changes actually occured. This is a small subset of
6120 * all the possible changes. We also have to update things in the
6124 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6125 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6126 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6127 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6129 notify_printer_comment(snum, printer->info_2->comment);
6132 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6133 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6134 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6135 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6137 notify_printer_sharename(snum, printer->info_2->sharename);
6140 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6143 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6146 pname = printer->info_2->printername;
6149 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6150 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6151 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6153 notify_printer_printername( snum, pname );
6156 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6157 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6158 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6159 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6161 notify_printer_port(snum, printer->info_2->portname);
6164 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6165 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6166 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6167 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6169 notify_printer_location(snum, printer->info_2->location);
6172 /* here we need to update some more DsSpooler keys */
6173 /* uNCName, serverName, shortServerName */
6175 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6176 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6177 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6178 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6179 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6181 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6182 global_myname(), printer->info_2->sharename );
6183 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6184 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6185 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6187 /* Update printer info */
6188 result = mod_a_printer(*printer, 2);
6191 free_a_printer(&printer, 2);
6192 free_a_printer(&old_printer, 2);
6198 /****************************************************************************
6199 ****************************************************************************/
6200 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6201 const SPOOL_PRINTER_INFO_LEVEL *info)
6204 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6206 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6208 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6213 if (!get_printer_snum(p, handle, &snum))
6216 nt_printer_publish(Printer, snum, info7->action);
6220 return WERR_UNKNOWN_LEVEL;
6223 /****************************************************************************
6224 ****************************************************************************/
6226 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6228 POLICY_HND *handle = &q_u->handle;
6229 uint32 level = q_u->level;
6230 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6231 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6232 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6233 uint32 command = q_u->command;
6236 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6239 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6243 /* check the level */
6246 return control_printer(handle, command, p);
6248 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6249 if (!W_ERROR_IS_OK(result))
6252 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6255 return update_printer_sec(handle, level, info, p,
6258 return publish_or_unpublish_printer(p, handle, info);
6260 return WERR_UNKNOWN_LEVEL;
6264 /****************************************************************************
6265 ****************************************************************************/
6267 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6269 POLICY_HND *handle = &q_u->handle;
6270 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6273 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6277 if (Printer->notify.client_connected==True) {
6280 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6282 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6283 !get_printer_snum(p, handle, &snum) )
6286 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6289 Printer->notify.flags=0;
6290 Printer->notify.options=0;
6291 Printer->notify.localmachine[0]='\0';
6292 Printer->notify.printerlocal=0;
6293 if (Printer->notify.option)
6294 free_spool_notify_option(&Printer->notify.option);
6295 Printer->notify.client_connected=False;
6300 /****************************************************************************
6301 ****************************************************************************/
6303 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6305 /* that's an [in out] buffer (despite appearences to the contrary) */
6306 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6309 return WERR_INVALID_PARAM; /* this is what a NT server
6310 returns for AddJob. AddJob
6311 must fail on non-local
6315 /****************************************************************************
6316 ****************************************************************************/
6318 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6319 int position, int snum)
6325 t=gmtime(&queue->time);
6326 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6328 job_info->jobid=queue->job;
6329 init_unistr(&job_info->printername, lp_servicename(snum));
6330 init_unistr(&job_info->machinename, temp_name);
6331 init_unistr(&job_info->username, queue->fs_user);
6332 init_unistr(&job_info->document, queue->fs_file);
6333 init_unistr(&job_info->datatype, "RAW");
6334 init_unistr(&job_info->text_status, "");
6335 job_info->status=nt_printj_status(queue->status);
6336 job_info->priority=queue->priority;
6337 job_info->position=position;
6338 job_info->totalpages=queue->page_count;
6339 job_info->pagesprinted=0;
6341 make_systemtime(&job_info->submitted, t);
6344 /****************************************************************************
6345 ****************************************************************************/
6347 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6348 int position, int snum,
6349 NT_PRINTER_INFO_LEVEL *ntprinter,
6350 DEVICEMODE *devmode)
6355 t=gmtime(&queue->time);
6356 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6358 job_info->jobid=queue->job;
6360 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6362 init_unistr(&job_info->machinename, temp_name);
6363 init_unistr(&job_info->username, queue->fs_user);
6364 init_unistr(&job_info->document, queue->fs_file);
6365 init_unistr(&job_info->notifyname, queue->fs_user);
6366 init_unistr(&job_info->datatype, "RAW");
6367 init_unistr(&job_info->printprocessor, "winprint");
6368 init_unistr(&job_info->parameters, "");
6369 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6370 init_unistr(&job_info->text_status, "");
6372 /* and here the security descriptor */
6374 job_info->status=nt_printj_status(queue->status);
6375 job_info->priority=queue->priority;
6376 job_info->position=position;
6377 job_info->starttime=0;
6378 job_info->untiltime=0;
6379 job_info->totalpages=queue->page_count;
6380 job_info->size=queue->size;
6381 make_systemtime(&(job_info->submitted), t);
6382 job_info->timeelapsed=0;
6383 job_info->pagesprinted=0;
6385 job_info->devmode = devmode;
6390 /****************************************************************************
6391 Enumjobs at level 1.
6392 ****************************************************************************/
6394 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6395 NEW_BUFFER *buffer, uint32 offered,
6396 uint32 *needed, uint32 *returned)
6401 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6408 for (i=0; i<*returned; i++)
6409 fill_job_info_1(&info[i], &queue[i], i, snum);
6413 /* check the required size. */
6414 for (i=0; i<*returned; i++)
6415 (*needed) += spoolss_size_job_info_1(&info[i]);
6417 if (!alloc_buffer_size(buffer, *needed)) {
6419 return WERR_INSUFFICIENT_BUFFER;
6422 /* fill the buffer with the structures */
6423 for (i=0; i<*returned; i++)
6424 smb_io_job_info_1("", buffer, &info[i], 0);
6429 if (*needed > offered) {
6431 return WERR_INSUFFICIENT_BUFFER;
6437 /****************************************************************************
6438 Enumjobs at level 2.
6439 ****************************************************************************/
6441 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6442 NEW_BUFFER *buffer, uint32 offered,
6443 uint32 *needed, uint32 *returned)
6445 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6446 JOB_INFO_2 *info = NULL;
6449 DEVICEMODE *devmode = NULL;
6451 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6454 result = WERR_NOMEM;
6458 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6459 if (!W_ERROR_IS_OK(result)) {
6464 /* this should not be a failure condition if the devmode is NULL */
6466 devmode = construct_dev_mode(snum);
6468 for (i=0; i<*returned; i++)
6469 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6472 free_a_printer(&ntprinter, 2);
6475 /* check the required size. */
6476 for (i=0; i<*returned; i++)
6477 (*needed) += spoolss_size_job_info_2(&info[i]);
6479 if (*needed > offered) {
6481 result = WERR_INSUFFICIENT_BUFFER;
6485 if (!alloc_buffer_size(buffer, *needed)) {
6487 result = WERR_INSUFFICIENT_BUFFER;
6491 /* fill the buffer with the structures */
6492 for (i=0; i<*returned; i++)
6493 smb_io_job_info_2("", buffer, &info[i], 0);
6498 free_a_printer(&ntprinter, 2);
6499 free_devmode(devmode);
6507 /****************************************************************************
6509 ****************************************************************************/
6511 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6513 POLICY_HND *handle = &q_u->handle;
6514 uint32 level = q_u->level;
6515 NEW_BUFFER *buffer = NULL;
6516 uint32 offered = q_u->offered;
6517 uint32 *needed = &r_u->needed;
6518 uint32 *returned = &r_u->returned;
6522 print_status_struct prt_status;
6523 print_queue_struct *queue=NULL;
6525 /* that's an [in out] buffer */
6526 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6527 buffer = r_u->buffer;
6529 DEBUG(4,("_spoolss_enumjobs\n"));
6534 if (!get_printer_snum(p, handle, &snum))
6537 *returned = print_queue_status(snum, &queue, &prt_status);
6538 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6540 if (*returned == 0) {
6547 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6550 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6555 return WERR_UNKNOWN_LEVEL;
6559 /****************************************************************************
6560 ****************************************************************************/
6562 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6567 /****************************************************************************
6568 ****************************************************************************/
6570 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6572 POLICY_HND *handle = &q_u->handle;
6573 uint32 jobid = q_u->jobid;
6574 uint32 command = q_u->command;
6576 struct current_user user;
6578 WERROR errcode = WERR_BADFUNC;
6580 if (!get_printer_snum(p, handle, &snum)) {
6584 if (!print_job_exists(snum, jobid)) {
6585 return WERR_INVALID_PRINTER_NAME;
6588 get_current_user(&user, p);
6591 case JOB_CONTROL_CANCEL:
6592 case JOB_CONTROL_DELETE:
6593 if (print_job_delete(&user, snum, jobid, &errcode)) {
6597 case JOB_CONTROL_PAUSE:
6598 if (print_job_pause(&user, snum, jobid, &errcode)) {
6602 case JOB_CONTROL_RESTART:
6603 case JOB_CONTROL_RESUME:
6604 if (print_job_resume(&user, snum, jobid, &errcode)) {
6609 return WERR_UNKNOWN_LEVEL;
6615 /****************************************************************************
6616 Enumerates all printer drivers at level 1.
6617 ****************************************************************************/
6619 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6624 fstring *list = NULL;
6626 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6627 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6631 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6633 ndrivers=get_ntdrivers(&list, architecture, version);
6634 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6640 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6641 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6642 SAFE_FREE(driver_info_1);
6646 else driver_info_1 = tdi1;
6649 for (i=0; i<ndrivers; i++) {
6651 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6652 ZERO_STRUCT(driver);
6653 status = get_a_printer_driver(&driver, 3, list[i],
6654 architecture, version);
6655 if (!W_ERROR_IS_OK(status)) {
6659 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6660 free_a_printer_driver(driver, 3);
6663 *returned+=ndrivers;
6667 /* check the required size. */
6668 for (i=0; i<*returned; i++) {
6669 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6670 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6673 if (!alloc_buffer_size(buffer, *needed)) {
6674 SAFE_FREE(driver_info_1);
6675 return WERR_INSUFFICIENT_BUFFER;
6678 /* fill the buffer with the driver structures */
6679 for (i=0; i<*returned; i++) {
6680 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6681 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6684 SAFE_FREE(driver_info_1);
6686 if (*needed > offered) {
6688 return WERR_INSUFFICIENT_BUFFER;
6694 /****************************************************************************
6695 Enumerates all printer drivers at level 2.
6696 ****************************************************************************/
6698 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6703 fstring *list = NULL;
6705 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6706 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6710 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6712 ndrivers=get_ntdrivers(&list, architecture, version);
6713 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6719 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6720 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6721 SAFE_FREE(driver_info_2);
6725 else driver_info_2 = tdi2;
6728 for (i=0; i<ndrivers; i++) {
6731 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6732 ZERO_STRUCT(driver);
6733 status = get_a_printer_driver(&driver, 3, list[i],
6734 architecture, version);
6735 if (!W_ERROR_IS_OK(status)) {
6739 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6740 free_a_printer_driver(driver, 3);
6743 *returned+=ndrivers;
6747 /* check the required size. */
6748 for (i=0; i<*returned; i++) {
6749 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6750 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6753 if (!alloc_buffer_size(buffer, *needed)) {
6754 SAFE_FREE(driver_info_2);
6755 return WERR_INSUFFICIENT_BUFFER;
6758 /* fill the buffer with the form structures */
6759 for (i=0; i<*returned; i++) {
6760 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6761 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6764 SAFE_FREE(driver_info_2);
6766 if (*needed > offered) {
6768 return WERR_INSUFFICIENT_BUFFER;
6774 /****************************************************************************
6775 Enumerates all printer drivers at level 3.
6776 ****************************************************************************/
6778 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6783 fstring *list = NULL;
6785 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6786 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6790 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6792 ndrivers=get_ntdrivers(&list, architecture, version);
6793 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6799 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6800 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6801 SAFE_FREE(driver_info_3);
6805 else driver_info_3 = tdi3;
6808 for (i=0; i<ndrivers; i++) {
6811 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6812 ZERO_STRUCT(driver);
6813 status = get_a_printer_driver(&driver, 3, list[i],
6814 architecture, version);
6815 if (!W_ERROR_IS_OK(status)) {
6819 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6820 free_a_printer_driver(driver, 3);
6823 *returned+=ndrivers;
6827 /* check the required size. */
6828 for (i=0; i<*returned; i++) {
6829 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6830 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6833 if (!alloc_buffer_size(buffer, *needed)) {
6834 SAFE_FREE(driver_info_3);
6835 return WERR_INSUFFICIENT_BUFFER;
6838 /* fill the buffer with the driver structures */
6839 for (i=0; i<*returned; i++) {
6840 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6841 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6844 for (i=0; i<*returned; i++)
6845 SAFE_FREE(driver_info_3[i].dependentfiles);
6847 SAFE_FREE(driver_info_3);
6849 if (*needed > offered) {
6851 return WERR_INSUFFICIENT_BUFFER;
6857 /****************************************************************************
6858 Enumerates all printer drivers.
6859 ****************************************************************************/
6861 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6863 UNISTR2 *environment = &q_u->environment;
6864 uint32 level = q_u->level;
6865 NEW_BUFFER *buffer = NULL;
6866 uint32 offered = q_u->offered;
6867 uint32 *needed = &r_u->needed;
6868 uint32 *returned = &r_u->returned;
6870 fstring *list = NULL;
6872 fstring architecture;
6874 /* that's an [in out] buffer */
6875 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6876 buffer = r_u->buffer;
6878 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6879 fstrcpy(servername, get_called_name());
6883 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6887 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6889 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6891 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6895 return WERR_UNKNOWN_LEVEL;
6899 /****************************************************************************
6900 ****************************************************************************/
6902 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6904 form->flag=list->flag;
6905 init_unistr(&form->name, list->name);
6906 form->width=list->width;
6907 form->length=list->length;
6908 form->left=list->left;
6909 form->top=list->top;
6910 form->right=list->right;
6911 form->bottom=list->bottom;
6914 /****************************************************************************
6915 ****************************************************************************/
6917 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6919 uint32 level = q_u->level;
6920 NEW_BUFFER *buffer = NULL;
6921 uint32 offered = q_u->offered;
6922 uint32 *needed = &r_u->needed;
6923 uint32 *numofforms = &r_u->numofforms;
6924 uint32 numbuiltinforms;
6926 nt_forms_struct *list=NULL;
6927 nt_forms_struct *builtinlist=NULL;
6932 /* that's an [in out] buffer */
6933 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6934 buffer = r_u->buffer;
6936 DEBUG(4,("_spoolss_enumforms\n"));
6937 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6938 DEBUGADD(5,("Info level [%d]\n", level));
6940 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6941 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6942 *numofforms = get_ntforms(&list);
6943 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6944 *numofforms += numbuiltinforms;
6946 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6950 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6955 /* construct the list of form structures */
6956 for (i=0; i<numbuiltinforms; i++) {
6957 DEBUGADD(6,("Filling form number [%d]\n",i));
6958 fill_form_1(&forms_1[i], &builtinlist[i]);
6961 SAFE_FREE(builtinlist);
6963 for (; i<*numofforms; i++) {
6964 DEBUGADD(6,("Filling form number [%d]\n",i));
6965 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6970 /* check the required size. */
6971 for (i=0; i<numbuiltinforms; i++) {
6972 DEBUGADD(6,("adding form [%d]'s size\n",i));
6973 buffer_size += spoolss_size_form_1(&forms_1[i]);
6975 for (; i<*numofforms; i++) {
6976 DEBUGADD(6,("adding form [%d]'s size\n",i));
6977 buffer_size += spoolss_size_form_1(&forms_1[i]);
6980 *needed=buffer_size;
6982 if (!alloc_buffer_size(buffer, buffer_size)){
6984 return WERR_INSUFFICIENT_BUFFER;
6987 /* fill the buffer with the form structures */
6988 for (i=0; i<numbuiltinforms; i++) {
6989 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6990 smb_io_form_1("", buffer, &forms_1[i], 0);
6992 for (; i<*numofforms; i++) {
6993 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6994 smb_io_form_1("", buffer, &forms_1[i], 0);
6999 if (*needed > offered) {
7001 return WERR_INSUFFICIENT_BUFFER;
7008 SAFE_FREE(builtinlist);
7009 return WERR_UNKNOWN_LEVEL;
7014 /****************************************************************************
7015 ****************************************************************************/
7017 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7019 uint32 level = q_u->level;
7020 UNISTR2 *uni_formname = &q_u->formname;
7021 NEW_BUFFER *buffer = NULL;
7022 uint32 offered = q_u->offered;
7023 uint32 *needed = &r_u->needed;
7025 nt_forms_struct *list=NULL;
7026 nt_forms_struct builtin_form;
7031 int numofforms=0, i=0;
7033 /* that's an [in out] buffer */
7034 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7035 buffer = r_u->buffer;
7037 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7039 DEBUG(4,("_spoolss_getform\n"));
7040 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7041 DEBUGADD(5,("Info level [%d]\n", level));
7043 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7044 if (!foundBuiltin) {
7045 numofforms = get_ntforms(&list);
7046 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7048 if (numofforms == 0)
7055 fill_form_1(&form_1, &builtin_form);
7058 /* Check if the requested name is in the list of form structures */
7059 for (i=0; i<numofforms; i++) {
7061 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7063 if (strequal(form_name, list[i].name)) {
7064 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7065 fill_form_1(&form_1, &list[i]);
7071 if (i == numofforms) {
7075 /* check the required size. */
7077 *needed=spoolss_size_form_1(&form_1);
7079 if (!alloc_buffer_size(buffer, buffer_size)){
7080 return WERR_INSUFFICIENT_BUFFER;
7083 if (*needed > offered) {
7084 return WERR_INSUFFICIENT_BUFFER;
7087 /* fill the buffer with the form structures */
7088 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7089 smb_io_form_1("", buffer, &form_1, 0);
7095 return WERR_UNKNOWN_LEVEL;
7099 /****************************************************************************
7100 ****************************************************************************/
7102 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7104 init_unistr(&port->port_name, name);
7107 /****************************************************************************
7108 ****************************************************************************/
7110 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7112 init_unistr(&port->port_name, name);
7113 init_unistr(&port->monitor_name, "Local Monitor");
7114 init_unistr(&port->description, "Local Port");
7115 port->port_type=PORT_TYPE_WRITE;
7119 /****************************************************************************
7121 ****************************************************************************/
7123 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7125 PORT_INFO_1 *ports=NULL;
7128 if (*lp_enumports_cmd()) {
7129 char *cmd = lp_enumports_cmd();
7136 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7138 DEBUG(10,("Running [%s]\n", command));
7139 ret = smbrun(command, &fd);
7140 DEBUG(10,("Returned [%d]\n", ret));
7144 /* Is this the best error to return here? */
7145 return WERR_ACCESS_DENIED;
7149 qlines = fd_lines_load(fd, &numlines);
7150 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7154 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7155 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7156 dos_errstr(WERR_NOMEM)));
7157 file_lines_free(qlines);
7161 for (i=0; i<numlines; i++) {
7162 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7163 fill_port_1(&ports[i], qlines[i]);
7166 file_lines_free(qlines);
7169 *returned = numlines;
7172 *returned = 1; /* Sole Samba port returned. */
7174 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7177 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7179 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7182 /* check the required size. */
7183 for (i=0; i<*returned; i++) {
7184 DEBUGADD(6,("adding port [%d]'s size\n", i));
7185 *needed += spoolss_size_port_info_1(&ports[i]);
7188 if (!alloc_buffer_size(buffer, *needed)) {
7190 return WERR_INSUFFICIENT_BUFFER;
7193 /* fill the buffer with the ports structures */
7194 for (i=0; i<*returned; i++) {
7195 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7196 smb_io_port_1("", buffer, &ports[i], 0);
7201 if (*needed > offered) {
7203 return WERR_INSUFFICIENT_BUFFER;
7209 /****************************************************************************
7211 ****************************************************************************/
7213 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7215 PORT_INFO_2 *ports=NULL;
7218 if (*lp_enumports_cmd()) {
7219 char *cmd = lp_enumports_cmd();
7228 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7229 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7231 path = lp_lockdir();
7233 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7234 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7237 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7238 ret = smbrun(command, &fd);
7239 DEBUGADD(10,("returned [%d]\n", ret));
7243 /* Is this the best error to return here? */
7244 return WERR_ACCESS_DENIED;
7248 qlines = fd_lines_load(fd, &numlines);
7249 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7253 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7254 file_lines_free(qlines);
7258 for (i=0; i<numlines; i++) {
7259 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7260 fill_port_2(&(ports[i]), qlines[i]);
7263 file_lines_free(qlines);
7266 *returned = numlines;
7272 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7275 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7277 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7280 /* check the required size. */
7281 for (i=0; i<*returned; i++) {
7282 DEBUGADD(6,("adding port [%d]'s size\n", i));
7283 *needed += spoolss_size_port_info_2(&ports[i]);
7286 if (!alloc_buffer_size(buffer, *needed)) {
7288 return WERR_INSUFFICIENT_BUFFER;
7291 /* fill the buffer with the ports structures */
7292 for (i=0; i<*returned; i++) {
7293 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7294 smb_io_port_2("", buffer, &ports[i], 0);
7299 if (*needed > offered) {
7301 return WERR_INSUFFICIENT_BUFFER;
7307 /****************************************************************************
7309 ****************************************************************************/
7311 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7313 uint32 level = q_u->level;
7314 NEW_BUFFER *buffer = NULL;
7315 uint32 offered = q_u->offered;
7316 uint32 *needed = &r_u->needed;
7317 uint32 *returned = &r_u->returned;
7319 /* that's an [in out] buffer */
7320 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7321 buffer = r_u->buffer;
7323 DEBUG(4,("_spoolss_enumports\n"));
7330 return enumports_level_1(buffer, offered, needed, returned);
7332 return enumports_level_2(buffer, offered, needed, returned);
7334 return WERR_UNKNOWN_LEVEL;
7338 /****************************************************************************
7339 ****************************************************************************/
7341 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7342 const SPOOL_PRINTER_INFO_LEVEL *info,
7343 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7344 uint32 user_switch, const SPOOL_USER_CTR *user,
7347 NT_PRINTER_INFO_LEVEL *printer = NULL;
7350 WERROR err = WERR_OK;
7352 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7353 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7357 ZERO_STRUCTP(printer);
7359 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7360 if (!convert_printer_info(info, printer, 2)) {
7361 free_a_printer(&printer, 2);
7365 /* check to see if the printer already exists */
7367 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7368 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7369 printer->info_2->sharename));
7370 free_a_printer(&printer, 2);
7371 return WERR_PRINTER_ALREADY_EXISTS;
7374 /* FIXME!!! smbd should check to see if the driver is installed before
7375 trying to add a printer like this --jerry */
7377 if (*lp_addprinter_cmd() ) {
7378 if ( !add_printer_hook(printer) ) {
7379 free_a_printer(&printer,2);
7380 return WERR_ACCESS_DENIED;
7384 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7385 printer->info_2->sharename);
7388 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7389 free_a_printer(&printer,2);
7390 return WERR_ACCESS_DENIED;
7393 /* you must be a printer admin to add a new printer */
7394 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7395 free_a_printer(&printer,2);
7396 return WERR_ACCESS_DENIED;
7400 * Do sanity check on the requested changes for Samba.
7403 if (!check_printer_ok(printer->info_2, snum)) {
7404 free_a_printer(&printer,2);
7405 return WERR_INVALID_PARAM;
7409 * When a printer is created, the drivername bound to the printer is used
7410 * to lookup previously saved driver initialization info, which is then
7411 * bound to the new printer, simulating what happens in the Windows arch.
7416 set_driver_init(printer, 2);
7420 /* A valid devmode was included, convert and link it
7422 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7424 if (!convert_devicemode(printer->info_2->printername, devmode,
7425 &printer->info_2->devmode))
7429 /* write the ASCII on disk */
7430 err = mod_a_printer(*printer, 2);
7431 if (!W_ERROR_IS_OK(err)) {
7432 free_a_printer(&printer,2);
7436 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7437 /* Handle open failed - remove addition. */
7438 del_a_printer(printer->info_2->sharename);
7439 free_a_printer(&printer,2);
7440 return WERR_ACCESS_DENIED;
7443 update_c_setprinter(False);
7444 free_a_printer(&printer,2);
7449 /****************************************************************************
7450 ****************************************************************************/
7452 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7454 UNISTR2 *uni_srv_name = &q_u->server_name;
7455 uint32 level = q_u->level;
7456 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7457 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7458 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7459 uint32 user_switch = q_u->user_switch;
7460 SPOOL_USER_CTR *user = &q_u->user_ctr;
7461 POLICY_HND *handle = &r_u->handle;
7465 /* we don't handle yet */
7466 /* but I know what to do ... */
7467 return WERR_UNKNOWN_LEVEL;
7469 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7471 user_switch, user, handle);
7473 return WERR_UNKNOWN_LEVEL;
7477 /****************************************************************************
7478 ****************************************************************************/
7480 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7482 uint32 level = q_u->level;
7483 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7484 WERROR err = WERR_OK;
7485 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7486 struct current_user user;
7487 fstring driver_name;
7490 ZERO_STRUCT(driver);
7492 get_current_user(&user, p);
7494 if (!convert_printer_driver_info(info, &driver, level)) {
7499 DEBUG(5,("Cleaning driver's information\n"));
7500 err = clean_up_driver_struct(driver, level, &user);
7501 if (!W_ERROR_IS_OK(err))
7504 DEBUG(5,("Moving driver to final destination\n"));
7505 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7506 if (W_ERROR_IS_OK(err))
7507 err = WERR_ACCESS_DENIED;
7511 if (add_a_printer_driver(driver, level)!=0) {
7512 err = WERR_ACCESS_DENIED;
7516 /* BEGIN_ADMIN_LOG */
7519 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7520 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7521 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7524 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7525 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7526 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7532 * I think this is where he DrvUpgradePrinter() hook would be
7533 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7534 * server. Right now, we just need to send ourselves a message
7535 * to update each printer bound to this driver. --jerry
7538 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7539 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7544 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7545 * decide if the driver init data should be deleted. The rules are:
7546 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7547 * 2) delete init data only if there is no 2k/Xp driver
7548 * 3) always delete init data
7549 * The generalized rule is always use init data from the highest order driver.
7550 * It is necessary to follow the driver install by an initialization step to
7551 * finish off this process.
7554 version = driver.info_3->cversion;
7555 else if (level == 6)
7556 version = driver.info_6->version;
7561 * 9x printer driver - never delete init data
7564 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7569 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7570 * there is no 2k/Xp driver init data for this driver name.
7574 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7576 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7578 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7580 if (!del_driver_init(driver_name))
7581 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7584 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7586 free_a_printer_driver(driver1,3);
7587 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7594 * 2k or Xp printer driver - always delete init data
7597 if (!del_driver_init(driver_name))
7598 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7602 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7608 free_a_printer_driver(driver, level);
7612 /********************************************************************
7613 * spoolss_addprinterdriverex
7614 ********************************************************************/
7616 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7618 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7619 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7622 * we only support the semantics of AddPrinterDriver()
7623 * i.e. only copy files that are newer than existing ones
7626 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7627 return WERR_ACCESS_DENIED;
7629 ZERO_STRUCT(q_u_local);
7630 ZERO_STRUCT(r_u_local);
7632 /* just pass the information off to _spoolss_addprinterdriver() */
7633 q_u_local.server_name_ptr = q_u->server_name_ptr;
7634 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7635 q_u_local.level = q_u->level;
7636 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7638 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7641 /****************************************************************************
7642 ****************************************************************************/
7644 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7646 init_unistr(&info->name, name);
7649 /****************************************************************************
7650 ****************************************************************************/
7652 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7656 const char *short_archi;
7657 DRIVER_DIRECTORY_1 *info=NULL;
7659 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7661 if (!(short_archi = get_short_archi(long_archi)))
7662 return WERR_INVALID_ENVIRONMENT;
7664 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7667 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7669 DEBUG(4,("printer driver directory: [%s]\n", path));
7671 fill_driverdir_1(info, path);
7673 *needed += spoolss_size_driverdir_info_1(info);
7675 if (!alloc_buffer_size(buffer, *needed)) {
7677 return WERR_INSUFFICIENT_BUFFER;
7680 smb_io_driverdir_1("", buffer, info, 0);
7684 if (*needed > offered)
7685 return WERR_INSUFFICIENT_BUFFER;
7690 /****************************************************************************
7691 ****************************************************************************/
7693 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7695 UNISTR2 *name = &q_u->name;
7696 UNISTR2 *uni_environment = &q_u->environment;
7697 uint32 level = q_u->level;
7698 NEW_BUFFER *buffer = NULL;
7699 uint32 offered = q_u->offered;
7700 uint32 *needed = &r_u->needed;
7702 /* that's an [in out] buffer */
7703 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7704 buffer = r_u->buffer;
7706 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7712 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7714 return WERR_UNKNOWN_LEVEL;
7718 /****************************************************************************
7719 ****************************************************************************/
7721 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7723 POLICY_HND *handle = &q_u->handle;
7724 uint32 idx = q_u->index;
7725 uint32 in_value_len = q_u->valuesize;
7726 uint32 in_data_len = q_u->datasize;
7727 uint32 *out_max_value_len = &r_u->valuesize;
7728 uint16 **out_value = &r_u->value;
7729 uint32 *out_value_len = &r_u->realvaluesize;
7730 uint32 *out_type = &r_u->type;
7731 uint32 *out_max_data_len = &r_u->datasize;
7732 uint8 **data_out = &r_u->data;
7733 uint32 *out_data_len = &r_u->realdatasize;
7735 NT_PRINTER_INFO_LEVEL *printer = NULL;
7737 uint32 biggest_valuesize;
7738 uint32 biggest_datasize;
7740 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7743 REGISTRY_VALUE *val = NULL;
7744 NT_PRINTER_DATA *p_data;
7745 int i, key_index, num_values;
7748 ZERO_STRUCT( printer );
7752 *out_max_data_len = 0;
7756 DEBUG(5,("spoolss_enumprinterdata\n"));
7759 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7763 if (!get_printer_snum(p,handle, &snum))
7766 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7767 if (!W_ERROR_IS_OK(result))
7770 p_data = &printer->info_2->data;
7771 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7776 * The NT machine wants to know the biggest size of value and data
7778 * cf: MSDN EnumPrinterData remark section
7781 if ( !in_value_len && !in_data_len && (key_index != -1) )
7783 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7785 biggest_valuesize = 0;
7786 biggest_datasize = 0;
7788 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7790 for ( i=0; i<num_values; i++ )
7792 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7794 name_length = strlen(val->valuename);
7795 if ( strlen(val->valuename) > biggest_valuesize )
7796 biggest_valuesize = name_length;
7798 if ( val->size > biggest_datasize )
7799 biggest_datasize = val->size;
7801 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7805 /* the value is an UNICODE string but real_value_size is the length
7806 in bytes including the trailing 0 */
7808 *out_value_len = 2 * (1+biggest_valuesize);
7809 *out_data_len = biggest_datasize;
7811 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7817 * the value len is wrong in NT sp3
7818 * that's the number of bytes not the number of unicode chars
7821 if ( key_index != -1 )
7822 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7827 /* out_value should default to "" or else NT4 has
7828 problems unmarshalling the response */
7830 *out_max_value_len=(in_value_len/sizeof(uint16));
7832 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7834 result = WERR_NOMEM;
7838 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7840 /* the data is counted in bytes */
7842 *out_max_data_len = in_data_len;
7843 *out_data_len = in_data_len;
7845 /* only allocate when given a non-zero data_len */
7847 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7849 result = WERR_NOMEM;
7853 result = WERR_NO_MORE_ITEMS;
7859 * - counted in bytes in the request
7860 * - counted in UNICODE chars in the max reply
7861 * - counted in bytes in the real size
7863 * take a pause *before* coding not *during* coding
7867 *out_max_value_len=(in_value_len/sizeof(uint16));
7868 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7870 result = WERR_NOMEM;
7874 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7878 *out_type = regval_type( val );
7880 /* data - counted in bytes */
7882 *out_max_data_len = in_data_len;
7883 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7885 result = WERR_NOMEM;
7888 data_len = (size_t)regval_size(val);
7889 memcpy( *data_out, regval_data_p(val), data_len );
7890 *out_data_len = data_len;
7894 free_a_printer(&printer, 2);
7898 /****************************************************************************
7899 ****************************************************************************/
7901 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7903 POLICY_HND *handle = &q_u->handle;
7904 UNISTR2 *value = &q_u->value;
7905 uint32 type = q_u->type;
7906 uint8 *data = q_u->data;
7907 uint32 real_len = q_u->real_len;
7909 NT_PRINTER_INFO_LEVEL *printer = NULL;
7911 WERROR status = WERR_OK;
7912 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7915 DEBUG(5,("spoolss_setprinterdata\n"));
7918 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7922 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7923 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7924 return WERR_INVALID_PARAM;
7927 if (!get_printer_snum(p,handle, &snum))
7931 * Access check : NT returns "access denied" if you make a
7932 * SetPrinterData call without the necessary privildge.
7933 * we were originally returning OK if nothing changed
7934 * which made Win2k issue **a lot** of SetPrinterData
7935 * when connecting to a printer --jerry
7938 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7940 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7941 status = WERR_ACCESS_DENIED;
7945 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7946 if (!W_ERROR_IS_OK(status))
7949 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7952 * When client side code sets a magic printer data key, detect it and save
7953 * the current printer data and the magic key's data (its the DEVMODE) for
7954 * future printer/driver initializations.
7956 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7958 /* Set devmode and printer initialization info */
7959 status = save_driver_init( printer, 2, data, real_len );
7961 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7965 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7966 type, data, real_len );
7967 if ( W_ERROR_IS_OK(status) )
7968 status = mod_a_printer(*printer, 2);
7972 free_a_printer(&printer, 2);
7977 /****************************************************************************
7978 ****************************************************************************/
7980 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7982 POLICY_HND *handle = &q_u->handle;
7983 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7986 DEBUG(5,("_spoolss_resetprinter\n"));
7989 * All we do is to check to see if the handle and queue is valid.
7990 * This call really doesn't mean anything to us because we only
7991 * support RAW printing. --jerry
7995 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7999 if (!get_printer_snum(p,handle, &snum))
8003 /* blindly return success */
8008 /****************************************************************************
8009 ****************************************************************************/
8011 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8013 POLICY_HND *handle = &q_u->handle;
8014 UNISTR2 *value = &q_u->valuename;
8016 NT_PRINTER_INFO_LEVEL *printer = NULL;
8018 WERROR status = WERR_OK;
8019 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8022 DEBUG(5,("spoolss_deleteprinterdata\n"));
8025 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8029 if (!get_printer_snum(p, handle, &snum))
8032 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8033 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8034 return WERR_ACCESS_DENIED;
8037 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8038 if (!W_ERROR_IS_OK(status))
8041 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8043 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8045 if ( W_ERROR_IS_OK(status) )
8046 mod_a_printer( *printer, 2 );
8048 free_a_printer(&printer, 2);
8053 /****************************************************************************
8054 ****************************************************************************/
8056 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8058 POLICY_HND *handle = &q_u->handle;
8059 FORM *form = &q_u->form;
8060 nt_forms_struct tmpForm;
8062 WERROR status = WERR_OK;
8063 NT_PRINTER_INFO_LEVEL *printer = NULL;
8066 nt_forms_struct *list=NULL;
8067 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8069 DEBUG(5,("spoolss_addform\n"));
8072 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8077 /* forms can be added on printer of on the print server handle */
8079 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8081 if (!get_printer_snum(p,handle, &snum))
8084 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8085 if (!W_ERROR_IS_OK(status))
8089 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8090 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8091 status = WERR_ACCESS_DENIED;
8095 /* can't add if builtin */
8097 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8098 status = WERR_ALREADY_EXISTS;
8102 count = get_ntforms(&list);
8104 if(!add_a_form(&list, form, &count)) {
8105 status = WERR_NOMEM;
8109 write_ntforms(&list, count);
8112 * ChangeID must always be set if this is a printer
8115 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8116 status = mod_a_printer(*printer, 2);
8120 free_a_printer(&printer, 2);
8126 /****************************************************************************
8127 ****************************************************************************/
8129 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8131 POLICY_HND *handle = &q_u->handle;
8132 UNISTR2 *form_name = &q_u->name;
8133 nt_forms_struct tmpForm;
8135 nt_forms_struct *list=NULL;
8136 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8138 WERROR status = WERR_OK;
8139 NT_PRINTER_INFO_LEVEL *printer = NULL;
8141 DEBUG(5,("spoolss_deleteform\n"));
8144 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8148 /* forms can be deleted on printer of on the print server handle */
8150 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8152 if (!get_printer_snum(p,handle, &snum))
8155 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8156 if (!W_ERROR_IS_OK(status))
8160 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8161 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8162 status = WERR_ACCESS_DENIED;
8166 /* can't delete if builtin */
8168 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8169 status = WERR_INVALID_PARAM;
8173 count = get_ntforms(&list);
8175 if ( !delete_a_form(&list, form_name, &count, &status ))
8179 * ChangeID must always be set if this is a printer
8182 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8183 status = mod_a_printer(*printer, 2);
8187 free_a_printer(&printer, 2);
8193 /****************************************************************************
8194 ****************************************************************************/
8196 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8198 POLICY_HND *handle = &q_u->handle;
8199 FORM *form = &q_u->form;
8200 nt_forms_struct tmpForm;
8202 WERROR status = WERR_OK;
8203 NT_PRINTER_INFO_LEVEL *printer = NULL;
8206 nt_forms_struct *list=NULL;
8207 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8209 DEBUG(5,("spoolss_setform\n"));
8212 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8216 /* forms can be modified on printer of on the print server handle */
8218 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8220 if (!get_printer_snum(p,handle, &snum))
8223 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8224 if (!W_ERROR_IS_OK(status))
8228 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8229 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8230 status = WERR_ACCESS_DENIED;
8234 /* can't set if builtin */
8235 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8236 status = WERR_INVALID_PARAM;
8240 count = get_ntforms(&list);
8241 update_a_form(&list, form, count);
8242 write_ntforms(&list, count);
8245 * ChangeID must always be set if this is a printer
8248 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8249 status = mod_a_printer(*printer, 2);
8254 free_a_printer(&printer, 2);
8260 /****************************************************************************
8261 enumprintprocessors level 1.
8262 ****************************************************************************/
8264 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8266 PRINTPROCESSOR_1 *info_1=NULL;
8268 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8273 init_unistr(&info_1->name, "winprint");
8275 *needed += spoolss_size_printprocessor_info_1(info_1);
8277 if (!alloc_buffer_size(buffer, *needed))
8278 return WERR_INSUFFICIENT_BUFFER;
8280 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8284 if (*needed > offered) {
8286 return WERR_INSUFFICIENT_BUFFER;
8292 /****************************************************************************
8293 ****************************************************************************/
8295 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8297 uint32 level = q_u->level;
8298 NEW_BUFFER *buffer = NULL;
8299 uint32 offered = q_u->offered;
8300 uint32 *needed = &r_u->needed;
8301 uint32 *returned = &r_u->returned;
8303 /* that's an [in out] buffer */
8304 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8305 buffer = r_u->buffer;
8307 DEBUG(5,("spoolss_enumprintprocessors\n"));
8310 * Enumerate the print processors ...
8312 * Just reply with "winprint", to keep NT happy
8313 * and I can use my nice printer checker.
8321 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8323 return WERR_UNKNOWN_LEVEL;
8327 /****************************************************************************
8328 enumprintprocdatatypes level 1.
8329 ****************************************************************************/
8331 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8333 PRINTPROCDATATYPE_1 *info_1=NULL;
8335 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8340 init_unistr(&info_1->name, "RAW");
8342 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8344 if (!alloc_buffer_size(buffer, *needed))
8345 return WERR_INSUFFICIENT_BUFFER;
8347 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8351 if (*needed > offered) {
8353 return WERR_INSUFFICIENT_BUFFER;
8359 /****************************************************************************
8360 ****************************************************************************/
8362 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8364 uint32 level = q_u->level;
8365 NEW_BUFFER *buffer = NULL;
8366 uint32 offered = q_u->offered;
8367 uint32 *needed = &r_u->needed;
8368 uint32 *returned = &r_u->returned;
8370 /* that's an [in out] buffer */
8371 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8372 buffer = r_u->buffer;
8374 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8381 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8383 return WERR_UNKNOWN_LEVEL;
8387 /****************************************************************************
8388 enumprintmonitors level 1.
8389 ****************************************************************************/
8391 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8393 PRINTMONITOR_1 *info_1=NULL;
8395 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8400 init_unistr(&info_1->name, "Local Port");
8402 *needed += spoolss_size_printmonitor_info_1(info_1);
8404 if (!alloc_buffer_size(buffer, *needed))
8405 return WERR_INSUFFICIENT_BUFFER;
8407 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8411 if (*needed > offered) {
8413 return WERR_INSUFFICIENT_BUFFER;
8419 /****************************************************************************
8420 enumprintmonitors level 2.
8421 ****************************************************************************/
8423 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8425 PRINTMONITOR_2 *info_2=NULL;
8427 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8432 init_unistr(&info_2->name, "Local Port");
8433 init_unistr(&info_2->environment, "Windows NT X86");
8434 init_unistr(&info_2->dll_name, "localmon.dll");
8436 *needed += spoolss_size_printmonitor_info_2(info_2);
8438 if (!alloc_buffer_size(buffer, *needed))
8439 return WERR_INSUFFICIENT_BUFFER;
8441 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8445 if (*needed > offered) {
8447 return WERR_INSUFFICIENT_BUFFER;
8453 /****************************************************************************
8454 ****************************************************************************/
8456 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8458 uint32 level = q_u->level;
8459 NEW_BUFFER *buffer = NULL;
8460 uint32 offered = q_u->offered;
8461 uint32 *needed = &r_u->needed;
8462 uint32 *returned = &r_u->returned;
8464 /* that's an [in out] buffer */
8465 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8466 buffer = r_u->buffer;
8468 DEBUG(5,("spoolss_enumprintmonitors\n"));
8471 * Enumerate the print monitors ...
8473 * Just reply with "Local Port", to keep NT happy
8474 * and I can use my nice printer checker.
8482 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8484 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8486 return WERR_UNKNOWN_LEVEL;
8490 /****************************************************************************
8491 ****************************************************************************/
8493 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8497 JOB_INFO_1 *info_1=NULL;
8499 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8501 if (info_1 == NULL) {
8505 for (i=0; i<count && found==False; i++) {
8506 if ((*queue)[i].job==(int)jobid)
8512 /* NT treats not found as bad param... yet another bad choice */
8513 return WERR_INVALID_PARAM;
8516 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8518 *needed += spoolss_size_job_info_1(info_1);
8520 if (!alloc_buffer_size(buffer, *needed)) {
8522 return WERR_INSUFFICIENT_BUFFER;
8525 smb_io_job_info_1("", buffer, info_1, 0);
8529 if (*needed > offered)
8530 return WERR_INSUFFICIENT_BUFFER;
8535 /****************************************************************************
8536 ****************************************************************************/
8538 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8543 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8545 DEVICEMODE *devmode = NULL;
8546 NT_DEVICEMODE *nt_devmode = NULL;
8548 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8550 ZERO_STRUCTP(info_2);
8552 if (info_2 == NULL) {
8557 for ( i=0; i<count && found==False; i++ )
8559 if ((*queue)[i].job == (int)jobid)
8565 /* NT treats not found as bad param... yet another bad
8567 ret = WERR_INVALID_PARAM;
8571 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8572 if (!W_ERROR_IS_OK(ret))
8576 * if the print job does not have a DEVMODE associated with it,
8577 * just use the one for the printer. A NULL devicemode is not
8578 * a failure condition
8581 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8582 devmode = construct_dev_mode(snum);
8584 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8585 ZERO_STRUCTP( devmode );
8586 convert_nt_devicemode( devmode, nt_devmode );
8590 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8592 *needed += spoolss_size_job_info_2(info_2);
8594 if (!alloc_buffer_size(buffer, *needed)) {
8595 ret = WERR_INSUFFICIENT_BUFFER;
8599 smb_io_job_info_2("", buffer, info_2, 0);
8601 if (*needed > offered) {
8602 ret = WERR_INSUFFICIENT_BUFFER;
8609 /* Cleanup allocated memory */
8611 free_job_info_2(info_2); /* Also frees devmode */
8613 free_a_printer(&ntprinter, 2);
8618 /****************************************************************************
8619 ****************************************************************************/
8621 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8623 POLICY_HND *handle = &q_u->handle;
8624 uint32 jobid = q_u->jobid;
8625 uint32 level = q_u->level;
8626 NEW_BUFFER *buffer = NULL;
8627 uint32 offered = q_u->offered;
8628 uint32 *needed = &r_u->needed;
8629 WERROR wstatus = WERR_OK;
8633 print_queue_struct *queue = NULL;
8634 print_status_struct prt_status;
8636 /* that's an [in out] buffer */
8637 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8638 buffer = r_u->buffer;
8640 DEBUG(5,("spoolss_getjob\n"));
8644 if (!get_printer_snum(p, handle, &snum))
8647 count = print_queue_status(snum, &queue, &prt_status);
8649 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8650 count, prt_status.status, prt_status.message));
8654 wstatus = getjob_level_1(&queue, count, snum, jobid,
8655 buffer, offered, needed);
8658 wstatus = getjob_level_2(&queue, count, snum, jobid,
8659 buffer, offered, needed);
8662 wstatus = WERR_UNKNOWN_LEVEL;
8670 /********************************************************************
8671 spoolss_getprinterdataex
8673 From MSDN documentation of GetPrinterDataEx: pass request
8674 to GetPrinterData if key is "PrinterDriverData".
8675 ********************************************************************/
8677 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8679 POLICY_HND *handle = &q_u->handle;
8680 uint32 in_size = q_u->size;
8681 uint32 *type = &r_u->type;
8682 uint32 *out_size = &r_u->size;
8683 uint8 **data = &r_u->data;
8684 uint32 *needed = &r_u->needed;
8685 fstring keyname, valuename;
8687 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8689 NT_PRINTER_INFO_LEVEL *printer = NULL;
8691 WERROR status = WERR_OK;
8693 DEBUG(4,("_spoolss_getprinterdataex\n"));
8695 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8696 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8698 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8699 keyname, valuename));
8701 /* in case of problem, return some default values */
8705 *out_size = in_size;
8708 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8709 status = WERR_BADFID;
8713 /* Is the handle to a printer or to the server? */
8715 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8716 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8717 status = WERR_INVALID_PARAM;
8721 if ( !get_printer_snum(p,handle, &snum) )
8724 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8725 if ( !W_ERROR_IS_OK(status) )
8728 /* check to see if the keyname is valid */
8729 if ( !strlen(keyname) ) {
8730 status = WERR_INVALID_PARAM;
8734 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8735 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8736 free_a_printer( &printer, 2 );
8737 status = WERR_BADFILE;
8741 /* When given a new keyname, we should just create it */
8743 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8745 if (*needed > *out_size)
8746 status = WERR_MORE_DATA;
8749 if ( !W_ERROR_IS_OK(status) )
8751 DEBUG(5, ("error: allocating %d\n", *out_size));
8753 /* reply this param doesn't exist */
8757 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8758 status = WERR_NOMEM;
8768 free_a_printer( &printer, 2 );
8773 /********************************************************************
8774 * spoolss_setprinterdataex
8775 ********************************************************************/
8777 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8779 POLICY_HND *handle = &q_u->handle;
8780 uint32 type = q_u->type;
8781 uint8 *data = q_u->data;
8782 uint32 real_len = q_u->real_len;
8784 NT_PRINTER_INFO_LEVEL *printer = NULL;
8786 WERROR status = WERR_OK;
8787 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8792 DEBUG(4,("_spoolss_setprinterdataex\n"));
8794 /* From MSDN documentation of SetPrinterDataEx: pass request to
8795 SetPrinterData if key is "PrinterDriverData" */
8798 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8802 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8803 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8804 return WERR_INVALID_PARAM;
8807 if ( !get_printer_snum(p,handle, &snum) )
8811 * Access check : NT returns "access denied" if you make a
8812 * SetPrinterData call without the necessary privildge.
8813 * we were originally returning OK if nothing changed
8814 * which made Win2k issue **a lot** of SetPrinterData
8815 * when connecting to a printer --jerry
8818 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8820 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8821 return WERR_ACCESS_DENIED;
8824 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8825 if (!W_ERROR_IS_OK(status))
8828 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8829 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8831 /* check for OID in valuename */
8833 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8839 /* save the registry data */
8841 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8843 if ( W_ERROR_IS_OK(status) )
8845 /* save the OID if one was specified */
8847 fstrcat( keyname, "\\" );
8848 fstrcat( keyname, SPOOL_OID_KEY );
8851 * I'm not checking the status here on purpose. Don't know
8852 * if this is right, but I'm returning the status from the
8853 * previous set_printer_dataex() call. I have no idea if
8854 * this is right. --jerry
8857 set_printer_dataex( printer, keyname, valuename,
8858 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8861 status = mod_a_printer(*printer, 2);
8864 free_a_printer(&printer, 2);
8870 /********************************************************************
8871 * spoolss_deleteprinterdataex
8872 ********************************************************************/
8874 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8876 POLICY_HND *handle = &q_u->handle;
8877 UNISTR2 *value = &q_u->valuename;
8878 UNISTR2 *key = &q_u->keyname;
8880 NT_PRINTER_INFO_LEVEL *printer = NULL;
8882 WERROR status = WERR_OK;
8883 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8884 pstring valuename, keyname;
8886 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8889 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8893 if (!get_printer_snum(p, handle, &snum))
8896 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8897 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8898 return WERR_ACCESS_DENIED;
8901 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8902 if (!W_ERROR_IS_OK(status))
8905 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8906 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8908 status = delete_printer_dataex( printer, keyname, valuename );
8910 if ( W_ERROR_IS_OK(status) )
8911 mod_a_printer( *printer, 2 );
8913 free_a_printer(&printer, 2);
8918 /********************************************************************
8919 * spoolss_enumprinterkey
8920 ********************************************************************/
8923 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8926 fstring *keynames = NULL;
8927 uint16 *enumkeys = NULL;
8930 POLICY_HND *handle = &q_u->handle;
8931 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8932 NT_PRINTER_DATA *data;
8933 NT_PRINTER_INFO_LEVEL *printer = NULL;
8935 WERROR status = WERR_BADFILE;
8938 DEBUG(4,("_spoolss_enumprinterkey\n"));
8941 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8945 if ( !get_printer_snum(p,handle, &snum) )
8948 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8949 if (!W_ERROR_IS_OK(status))
8952 /* get the list of subkey names */
8954 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8955 data = &printer->info_2->data;
8957 num_keys = get_printer_subkeys( data, key, &keynames );
8959 if ( num_keys == -1 ) {
8960 status = WERR_BADFILE;
8964 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8966 r_u->needed = printerkey_len*2;
8968 if ( q_u->size < r_u->needed ) {
8969 status = WERR_MORE_DATA;
8973 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8974 status = WERR_NOMEM;
8980 if ( q_u->size < r_u->needed )
8981 status = WERR_MORE_DATA;
8984 free_a_printer( &printer, 2 );
8985 SAFE_FREE( keynames );
8990 /********************************************************************
8991 * spoolss_deleteprinterkey
8992 ********************************************************************/
8994 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8996 POLICY_HND *handle = &q_u->handle;
8997 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8999 NT_PRINTER_INFO_LEVEL *printer = NULL;
9003 DEBUG(5,("spoolss_deleteprinterkey\n"));
9006 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9010 /* if keyname == NULL, return error */
9012 if ( !q_u->keyname.buffer )
9013 return WERR_INVALID_PARAM;
9015 if (!get_printer_snum(p, handle, &snum))
9018 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9019 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9020 return WERR_ACCESS_DENIED;
9023 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9024 if (!W_ERROR_IS_OK(status))
9027 /* delete the key and all subneys */
9029 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9031 status = delete_all_printer_data( printer->info_2, key );
9033 if ( W_ERROR_IS_OK(status) )
9034 status = mod_a_printer(*printer, 2);
9036 free_a_printer( &printer, 2 );
9042 /********************************************************************
9043 * spoolss_enumprinterdataex
9044 ********************************************************************/
9046 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9048 POLICY_HND *handle = &q_u->handle;
9049 uint32 in_size = q_u->size;
9052 NT_PRINTER_INFO_LEVEL *printer = NULL;
9053 PRINTER_ENUM_VALUES *enum_values = NULL;
9054 NT_PRINTER_DATA *p_data;
9056 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9061 REGISTRY_VALUE *val;
9066 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9069 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9074 * first check for a keyname of NULL or "". Win2k seems to send
9075 * this a lot and we should send back WERR_INVALID_PARAM
9076 * no need to spend time looking up the printer in this case.
9080 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9081 if ( !strlen(key) ) {
9082 result = WERR_INVALID_PARAM;
9086 /* get the printer off of disk */
9088 if (!get_printer_snum(p,handle, &snum))
9091 ZERO_STRUCT(printer);
9092 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9093 if (!W_ERROR_IS_OK(result))
9096 /* now look for a match on the key name */
9098 p_data = &printer->info_2->data;
9100 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9101 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9103 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9104 result = WERR_INVALID_PARAM;
9111 /* allocate the memory for the array of pointers -- if necessary */
9113 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9116 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9118 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9119 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9120 result = WERR_NOMEM;
9124 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9128 * loop through all params and build the array to pass
9129 * back to the client
9132 for ( i=0; i<num_entries; i++ )
9134 /* lookup the registry value */
9136 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9137 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9141 value_name = regval_name( val );
9142 init_unistr( &enum_values[i].valuename, value_name );
9143 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9144 enum_values[i].type = regval_type( val );
9146 data_len = regval_size( val );
9148 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9150 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9152 result = WERR_NOMEM;
9156 enum_values[i].data_len = data_len;
9158 /* keep track of the size of the array in bytes */
9160 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9163 /* housekeeping information in the reply */
9165 r_u->needed = needed;
9166 r_u->returned = num_entries;
9168 if (needed > in_size) {
9169 result = WERR_MORE_DATA;
9173 /* copy data into the reply */
9175 r_u->ctr.size = r_u->needed;
9176 r_u->ctr.size_of_array = r_u->returned;
9177 r_u->ctr.values = enum_values;
9183 free_a_printer(&printer, 2);
9188 /****************************************************************************
9189 ****************************************************************************/
9191 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9193 init_unistr(&info->name, name);
9196 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9197 UNISTR2 *environment,
9204 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9206 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9208 if (!get_short_archi(long_archi))
9209 return WERR_INVALID_ENVIRONMENT;
9211 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9214 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9216 fill_printprocessordirectory_1(info, path);
9218 *needed += spoolss_size_printprocessordirectory_info_1(info);
9220 if (!alloc_buffer_size(buffer, *needed)) {
9222 return WERR_INSUFFICIENT_BUFFER;
9225 smb_io_printprocessordirectory_1("", buffer, info, 0);
9229 if (*needed > offered)
9230 return WERR_INSUFFICIENT_BUFFER;
9235 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9237 uint32 level = q_u->level;
9238 NEW_BUFFER *buffer = NULL;
9239 uint32 offered = q_u->offered;
9240 uint32 *needed = &r_u->needed;
9243 /* that's an [in out] buffer */
9244 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9245 buffer = r_u->buffer;
9247 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9253 result = getprintprocessordirectory_level_1
9254 (&q_u->name, &q_u->environment, buffer, offered, needed);
9257 result = WERR_UNKNOWN_LEVEL;
9265 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9266 SPOOL_R_REPLYOPENPRINTER *r_u)
9268 DEBUG(5,("_spoolss_replyopenprinter\n"));
9270 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9275 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9276 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9278 DEBUG(5,("_spoolss_replycloseprinter\n"));