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-2002,
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_"
40 #define PRINTER_HANDLE_IS_PRINTER 0
41 #define PRINTER_HANDLE_IS_PRINTSERVER 1
43 /* Table to map the driver version */
45 static const char * drv_ver_to_os
[] = {
46 "WIN9X", /* driver version/cversion 0 */
48 "WINNT", /* driver version/cversion 2 */
49 "WIN2K", /* driver version/cversion 3 */
53 const char *long_archi
;
54 const char *short_archi
;
59 /* structure to store the printer handles */
60 /* and a reference to what it's pointing to */
61 /* and the notify info asked about */
62 /* that's the central struct */
63 typedef struct _Printer
{
64 struct _Printer
*prev
, *next
;
65 BOOL document_started
;
67 uint32 jobid
; /* jobid in printing backend */
71 fstring printerservername
;
74 uint32 access_granted
;
80 SPOOL_NOTIFY_OPTION
*option
;
81 POLICY_HND client_hnd
;
82 BOOL client_connected
;
84 /* are we in a FindNextPrinterChangeNotify() call? */
92 /* devmode sent in the OpenPrinter() call */
93 NT_DEVICEMODE
*nt_devmode
;
98 static Printer_entry
*printers_list
;
100 typedef struct _counter_printer_0
{
108 static ubi_dlList counter_list
;
110 static struct cli_state notify_cli
; /* print notify back-channel */
111 static uint32 smb_connections
=0;
114 /* in printing/nt_printing.c */
116 extern STANDARD_MAPPING printer_std_mapping
, printserver_std_mapping
;
118 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
119 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
121 /* translate between internal status numbers and NT status numbers */
122 static int nt_printj_status(int v
)
128 return JOB_STATUS_PAUSED
;
130 return JOB_STATUS_SPOOLING
;
132 return JOB_STATUS_PRINTING
;
134 return JOB_STATUS_ERROR
;
136 return JOB_STATUS_DELETING
;
138 return JOB_STATUS_OFFLINE
;
140 return JOB_STATUS_PAPEROUT
;
142 return JOB_STATUS_PRINTED
;
144 return JOB_STATUS_DELETED
;
146 return JOB_STATUS_BLOCKED
;
147 case LPQ_USER_INTERVENTION
:
148 return JOB_STATUS_USER_INTERVENTION
;
153 static int nt_printq_status(int v
)
157 return PRINTER_STATUS_PAUSED
;
166 /****************************************************************************
167 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
168 ****************************************************************************/
170 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
175 SAFE_FREE((*pp
)->ctr
.type
);
179 /***************************************************************************
180 Disconnect from the client
181 ****************************************************************************/
183 static void srv_spoolss_replycloseprinter(int snum
, POLICY_HND
*handle
)
188 * Tell the specific printing tdb we no longer want messages for this printer
189 * by deregistering our PID.
192 if (!print_notify_deregister_pid(snum
))
193 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
195 /* weird if the test succeds !!! */
196 if (smb_connections
==0) {
197 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
201 result
= cli_spoolss_reply_close_printer(¬ify_cli
, notify_cli
.mem_ctx
, handle
);
203 if (!W_ERROR_IS_OK(result
))
204 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
205 dos_errstr(result
)));
207 /* if it's the last connection, deconnect the IPC$ share */
208 if (smb_connections
==1) {
209 cli_nt_session_close(¬ify_cli
);
210 cli_ulogoff(¬ify_cli
);
211 cli_shutdown(¬ify_cli
);
212 message_deregister(MSG_PRINTER_NOTIFY2
);
214 /* Tell the connections db we're no longer interested in
215 * printer notify messages. */
217 register_message_flags( False
, FLAG_MSG_PRINTING
);
223 /****************************************************************************
224 Functions to free a printer entry datastruct.
225 ****************************************************************************/
227 static void free_printer_entry(void *ptr
)
229 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
231 if (Printer
->notify
.client_connected
==True
) {
234 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
236 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
237 } else if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) {
238 snum
= print_queue_snum(Printer
->dev
.handlename
);
240 srv_spoolss_replycloseprinter(snum
,
241 &Printer
->notify
.client_hnd
);
245 Printer
->notify
.flags
=0;
246 Printer
->notify
.options
=0;
247 Printer
->notify
.localmachine
[0]='\0';
248 Printer
->notify
.printerlocal
=0;
249 free_spool_notify_option(&Printer
->notify
.option
);
250 Printer
->notify
.option
=NULL
;
251 Printer
->notify
.client_connected
=False
;
253 free_nt_devicemode( &Printer
->nt_devmode
);
255 /* Remove from the internal list. */
256 DLIST_REMOVE(printers_list
, Printer
);
261 /****************************************************************************
262 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
263 ****************************************************************************/
265 static SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
267 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
272 new_sp
= (SPOOL_NOTIFY_OPTION
*)malloc(sizeof(SPOOL_NOTIFY_OPTION
));
279 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
281 if (!new_sp
->ctr
.type
) {
290 /****************************************************************************
291 find printer index by handle
292 ****************************************************************************/
294 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
296 Printer_entry
*find_printer
= NULL
;
298 if(!find_policy_by_hnd(p
,hnd
,(void **)&find_printer
)) {
299 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
306 /****************************************************************************
307 Close printer index by handle.
308 ****************************************************************************/
310 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
312 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
315 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
319 close_policy_hnd(p
, hnd
);
324 /****************************************************************************
325 Delete a printer given a handle.
326 ****************************************************************************/
328 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
330 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
333 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
338 * It turns out that Windows allows delete printer on a handle
339 * opened by an admin user, then used on a pipe handle created
340 * by an anonymous user..... but they're working on security.... riiight !
344 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
345 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
346 return WERR_ACCESS_DENIED
;
350 /* Check calling user has permission to delete printer. Note that
351 since we set the snum parameter to -1 only administrators can
352 delete the printer. This stops people with the Full Control
353 permission from deleting the printer. */
355 if (!print_access_check(NULL
, -1, PRINTER_ACCESS_ADMINISTER
)) {
356 DEBUG(3, ("printer delete denied by security descriptor\n"));
357 return WERR_ACCESS_DENIED
;
361 if (del_a_printer(Printer
->dev
.handlename
) != 0) {
362 DEBUG(3,("Error deleting printer %s\n", Printer
->dev
.handlename
));
366 if (*lp_deleteprinter_cmd()) {
368 char *cmd
= lp_deleteprinter_cmd();
373 /* Printer->dev.handlename equals portname equals sharename */
374 slprintf(command
, sizeof(command
)-1, "%s \"%s\"", cmd
,
375 Printer
->dev
.handlename
);
377 DEBUG(10,("Running [%s]\n", command
));
378 ret
= smbrun(command
, NULL
);
380 return WERR_BADFID
; /* What to return here? */
382 DEBUGADD(10,("returned [%d]\n", ret
));
384 /* Send SIGHUP to process group... is there a better way? */
387 /* go ahead and re-read the services immediately */
388 reload_services( False
);
390 if ( ( i
= lp_servicenumber( Printer
->dev
.handlename
) ) < 0 )
391 return WERR_ACCESS_DENIED
;
397 /****************************************************************************
398 Return the snum of a printer corresponding to an handle.
399 ****************************************************************************/
401 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
403 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
406 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
410 switch (Printer
->printer_type
) {
411 case PRINTER_HANDLE_IS_PRINTER
:
412 DEBUG(4,("short name:%s\n", Printer
->dev
.handlename
));
413 *number
= print_queue_snum(Printer
->dev
.handlename
);
414 return (*number
!= -1);
415 case PRINTER_HANDLE_IS_PRINTSERVER
:
422 /****************************************************************************
423 Set printer handle type.
424 Check if it's \\server or \\server\printer
425 ****************************************************************************/
427 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
429 DEBUG(3,("Setting printer type=%s\n", handlename
));
431 if ( strlen(handlename
) < 3 ) {
432 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
436 /* it's a print server */
437 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
438 DEBUGADD(4,("Printer is a print server\n"));
439 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTSERVER
;
443 DEBUGADD(4,("Printer is a printer\n"));
444 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTER
;
450 /****************************************************************************
451 Set printer handle name.
452 ****************************************************************************/
454 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
457 int n_services
=lp_numservices();
462 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename
, strlen(handlename
)));
464 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTSERVER
) {
465 ZERO_STRUCT(Printer
->dev
.printerservername
);
466 strncpy(Printer
->dev
.printerservername
, handlename
, strlen(handlename
));
470 if (Printer
->printer_type
!=PRINTER_HANDLE_IS_PRINTER
)
473 if (*handlename
=='\\') {
474 aprinter
=strchr_m(handlename
+2, '\\');
481 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter
, strlen(aprinter
)));
484 * The original code allowed smbd to store a printer name that
485 * was different from the share name. This is not possible
486 * anymore, so I've simplified this loop greatly. Here
487 * we are just verifying that the printer name is a valid
488 * printer service defined in smb.conf
489 * --jerry [Fri Feb 15 11:17:46 CST 2002]
492 for (snum
=0; snum
<n_services
; snum
++) {
494 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
497 fstrcpy(sname
, lp_servicename(snum
));
499 DEBUGADD(5,("share:%s\n",sname
));
501 if (! StrCaseCmp(sname
, aprinter
)) {
510 DEBUGADD(4,("Printer not found\n"));
514 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
516 ZERO_STRUCT(Printer
->dev
.handlename
);
517 fstrcpy(Printer
->dev
.handlename
, sname
);
522 /****************************************************************************
523 Find first available printer slot. creates a printer handle for you.
524 ****************************************************************************/
526 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
528 Printer_entry
*new_printer
;
530 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
532 if((new_printer
=(Printer_entry
*)malloc(sizeof(Printer_entry
))) == NULL
)
535 ZERO_STRUCTP(new_printer
);
537 new_printer
->notify
.option
=NULL
;
539 /* Add to the internal list. */
540 DLIST_ADD(printers_list
, new_printer
);
542 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
543 SAFE_FREE(new_printer
);
547 if (!set_printer_hnd_printertype(new_printer
, name
)) {
548 close_printer_handle(p
, hnd
);
552 if (!set_printer_hnd_name(new_printer
, name
)) {
553 close_printer_handle(p
, hnd
);
557 new_printer
->access_granted
= access_granted
;
559 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
564 /****************************************************************************
565 Allocate more memory for a BUFFER.
566 ****************************************************************************/
568 static BOOL
alloc_buffer_size(NEW_BUFFER
*buffer
, uint32 buffer_size
)
576 /* damn, I'm doing the reverse operation of prs_grow() :) */
577 if (buffer_size
< prs_data_size(ps
))
580 extra_space
= buffer_size
- prs_data_size(ps
);
583 * save the offset and move to the end of the buffer
584 * prs_grow() checks the extra_space against the offset
586 old_offset
=prs_offset(ps
);
587 prs_set_offset(ps
, prs_data_size(ps
));
589 if (!prs_grow(ps
, extra_space
))
592 prs_set_offset(ps
, old_offset
);
594 buffer
->string_at_end
=prs_data_size(ps
);
599 /***************************************************************************
600 check to see if the client motify handle is monitoring the notification
601 given by (notify_type, notify_field).
602 **************************************************************************/
604 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
610 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
613 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
617 * Flags should always be zero when the change notify
618 * is registered by the cliebnt's spooler. A user Win32 app
619 * might use the flags though instead of the NOTIFY_OPTION_INFO
624 return is_monitoring_event_flags(
625 p
->notify
.flags
, notify_type
, notify_field
);
627 for (i
= 0; i
< option
->count
; i
++) {
629 /* Check match for notify_type */
631 if (option
->ctr
.type
[i
].type
!= notify_type
)
634 /* Check match for field */
636 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
637 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
643 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
644 (p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) ?
645 p
->dev
.handlename
: p
->dev
.printerservername
,
646 notify_type
, notify_field
));
651 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
653 static void notify_one_value(struct spoolss_notify_msg
*msg
,
654 SPOOL_NOTIFY_INFO_DATA
*data
,
657 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
658 data
->notify_data
.value
[1] = 0;
661 static void notify_string(struct spoolss_notify_msg
*msg
,
662 SPOOL_NOTIFY_INFO_DATA
*data
,
667 /* The length of the message includes the trailing \0 */
669 init_unistr2(&unistr
, msg
->notify
.data
, msg
->len
);
671 data
->notify_data
.data
.length
= msg
->len
* 2;
672 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, msg
->len
* 2);
674 if (!data
->notify_data
.data
.string
) {
675 data
->notify_data
.data
.length
= 0;
679 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
682 static void notify_system_time(struct spoolss_notify_msg
*msg
,
683 SPOOL_NOTIFY_INFO_DATA
*data
,
689 if (msg
->len
!= sizeof(time_t)) {
690 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
695 if (!prs_init(&ps
, MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
696 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
700 if (!make_systemtime(&systime
, gmtime((time_t *)msg
->notify
.data
))) {
701 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
705 if (!spoolss_io_system_time("", &ps
, 0, &systime
))
708 data
->notify_data
.data
.length
= prs_offset(&ps
);
709 data
->notify_data
.data
.string
=
710 talloc(mem_ctx
, prs_offset(&ps
));
712 memcpy(data
->notify_data
.data
.string
, prs_data_p(&ps
), prs_offset(&ps
));
717 struct notify2_message_table
{
719 void (*fn
)(struct spoolss_notify_msg
*msg
,
720 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
723 static struct notify2_message_table printer_notify_table
[] = {
724 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
725 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
726 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
727 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
728 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
729 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
730 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
731 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
732 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
733 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
734 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
735 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
736 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
737 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
738 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
739 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
740 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
741 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
742 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
745 static struct notify2_message_table job_notify_table
[] = {
746 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
747 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
748 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
749 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
750 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
751 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
752 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
753 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
754 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
755 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
756 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
757 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
758 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
759 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
760 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
761 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
762 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
763 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
764 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
765 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
766 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
767 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
768 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
769 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
773 /***********************************************************************
774 Allocate talloc context for container object
775 **********************************************************************/
777 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
782 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
787 /***********************************************************************
788 release all allocated memory and zero out structure
789 **********************************************************************/
791 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
797 talloc_destroy(ctr
->ctx
);
804 /***********************************************************************
805 **********************************************************************/
807 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
815 /***********************************************************************
816 **********************************************************************/
818 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
820 if ( !ctr
|| !ctr
->msg_groups
)
823 if ( idx
>= ctr
->num_groups
)
826 return &ctr
->msg_groups
[idx
];
830 /***********************************************************************
831 How many groups of change messages do we have ?
832 **********************************************************************/
834 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
839 return ctr
->num_groups
;
842 /***********************************************************************
843 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
844 **********************************************************************/
846 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
848 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
849 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
850 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
856 /* loop over all groups looking for a matching printer name */
858 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
859 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
863 /* add a new group? */
865 if ( i
== ctr
->num_groups
)
869 if ( !(groups
= talloc_realloc( ctr
->ctx
, ctr
->msg_groups
, sizeof(SPOOLSS_NOTIFY_MSG_GROUP
)*ctr
->num_groups
)) ) {
870 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
873 ctr
->msg_groups
= groups
;
875 /* clear the new entry and set the printer name */
877 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
878 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
881 /* add the change messages; 'i' is the correct index now regardless */
883 msg_grp
= &ctr
->msg_groups
[i
];
887 if ( !(msg_list
= talloc_realloc( ctr
->ctx
, msg_grp
->msgs
, sizeof(SPOOLSS_NOTIFY_MSG
)*msg_grp
->num_msgs
)) ) {
888 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
891 msg_grp
->msgs
= msg_list
;
893 new_slot
= msg_grp
->num_msgs
-1;
894 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
896 /* need to allocate own copy of data */
899 msg_grp
->msgs
[new_slot
].notify
.data
= talloc_memdup( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
901 return ctr
->num_groups
;
904 /***********************************************************************
905 Send a change notication message on all handles which have a call
907 **********************************************************************/
909 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
912 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
913 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
914 SPOOLSS_NOTIFY_MSG
*messages
;
918 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
922 messages
= msg_group
->msgs
;
925 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
929 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
931 /* loop over all printers */
933 for (p
= printers_list
; p
; p
= p
->next
)
935 SPOOL_NOTIFY_INFO_DATA
*data
;
940 /* Is there notification on this handle? */
942 if ( !p
->notify
.client_connected
)
945 DEBUG(10,("Client connected! [%s]\n", p
->dev
.handlename
));
947 /* For this printer? Print servers always receive
950 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
951 ( !strequal(msg_group
->printername
, p
->dev
.handlename
) ) )
954 DEBUG(10,("Our printer\n"));
956 /* allocate the max entries possible */
958 data
= talloc( mem_ctx
, msg_group
->num_msgs
*sizeof(SPOOL_NOTIFY_INFO_DATA
) );
963 /* build the array of change notifications */
965 for ( i
=0; i
<msg_group
->num_msgs
; i
++ )
967 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
969 /* Are we monitoring this event? */
971 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
975 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
976 msg
->type
, msg
->field
, p
->dev
.handlename
));
979 * if the is a printer notification handle and not a job notification
980 * type, then set the id to 0. Other wise just use what was specified
983 * When registering change notification on a print server handle
984 * we always need to send back the id (snum) matching the printer
985 * for which the change took place. For change notify registered
986 * on a printer handle, this does not matter and the id should be 0.
991 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
997 /* Convert unix jobid to smb jobid */
999 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
)
1001 id
= sysjob_to_jobid(msg
->id
);
1004 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1009 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1012 case PRINTER_NOTIFY_TYPE
:
1013 if ( printer_notify_table
[msg
->field
].fn
)
1014 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1017 case JOB_NOTIFY_TYPE
:
1018 if ( job_notify_table
[msg
->field
].fn
)
1019 job_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1023 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1030 cli_spoolss_rrpcn( ¬ify_cli
, mem_ctx
, &p
->notify
.client_hnd
,
1031 data_len
, data
, p
->notify
.change
, 0 );
1035 DEBUG(8,("send_notify2_changes: Exit...\n"));
1039 /***********************************************************************
1040 **********************************************************************/
1042 static BOOL
notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, void *buf
, size_t len
)
1047 /* Unpack message */
1049 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
1052 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddd",
1053 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1056 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
1057 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1059 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
1060 &msg
->len
, &msg
->notify
.data
);
1062 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1063 msg
->type
, msg
->field
, msg
->flags
));
1066 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1067 msg
->notify
.value
[1]));
1069 dump_data(3, msg
->notify
.data
, msg
->len
);
1074 /********************************************************************
1075 Receive a notify2 message list
1076 ********************************************************************/
1078 static void receive_notify2_message_list(int msg_type
, pid_t src
, void *msg
, size_t len
)
1080 size_t msg_count
, i
;
1081 char *buf
= (char *)msg
;
1084 SPOOLSS_NOTIFY_MSG notify
;
1085 SPOOLSS_NOTIFY_MSG_CTR messages
;
1089 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1093 msg_count
= IVAL(buf
, 0);
1096 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count
));
1098 if (msg_count
== 0) {
1099 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1103 /* initialize the container */
1105 ZERO_STRUCT( messages
);
1106 notify_msg_ctr_init( &messages
);
1109 * build message groups for each printer identified
1110 * in a change_notify msg. Remember that a PCN message
1111 * includes the handle returned for the srv_spoolss_replyopenprinter()
1112 * call. Therefore messages are grouped according to printer handle.
1115 for ( i
=0; i
<msg_count
; i
++ )
1117 if (msg_ptr
+ 4 - buf
> len
) {
1118 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1122 msg_len
= IVAL(msg_ptr
,0);
1125 if (msg_ptr
+ msg_len
- buf
> len
) {
1126 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1130 /* unpack messages */
1132 ZERO_STRUCT( notify
);
1133 notify2_unpack_msg( ¬ify
, msg_ptr
, msg_len
);
1136 /* add to correct list in container */
1138 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1140 /* free memory that might have been allocated by notify2_unpack_msg() */
1142 if ( notify
.len
!= 0 )
1143 SAFE_FREE( notify
.notify
.data
);
1146 /* process each group of messages */
1148 num_groups
= notify_msg_ctr_numgroups( &messages
);
1149 for ( i
=0; i
<num_groups
; i
++ )
1150 send_notify2_changes( &messages
, i
);
1155 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1157 notify_msg_ctr_destroy( &messages
);
1162 /********************************************************************
1163 Send a message to ourself about new driver being installed
1164 so we can upgrade the information for each printer bound to this
1166 ********************************************************************/
1168 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
1170 int len
= strlen(drivername
);
1175 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1178 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
1183 /**********************************************************************
1184 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1185 over all printers, upgrading ones as neessary
1186 **********************************************************************/
1188 void do_drv_upgrade_printer(int msg_type
, pid_t src
, void *buf
, size_t len
)
1192 int n_services
= lp_numservices();
1194 len
= MIN(len
,sizeof(drivername
)-1);
1195 strncpy(drivername
, buf
, len
);
1197 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1199 /* Iterate the printer list */
1201 for (snum
=0; snum
<n_services
; snum
++)
1203 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1206 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1208 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
1209 if (!W_ERROR_IS_OK(result
))
1212 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1214 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1216 /* all we care about currently is the change_id */
1218 result
= mod_a_printer(*printer
, 2);
1219 if (!W_ERROR_IS_OK(result
)) {
1220 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1221 dos_errstr(result
)));
1225 free_a_printer(&printer
, 2);
1232 /********************************************************************
1233 Update the cahce for all printq's with a registered client
1235 ********************************************************************/
1237 void update_monitored_printq_cache( void )
1239 Printer_entry
*printer
= printers_list
;
1242 /* loop through all printers and update the cache where
1243 client_connected == True */
1246 if ( (printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
1247 && printer
->notify
.client_connected
)
1249 snum
= print_queue_snum(printer
->dev
.handlename
);
1250 print_queue_status( snum
, NULL
, NULL
);
1253 printer
= printer
->next
;
1258 /********************************************************************
1259 Send a message to ourself about new driver being installed
1260 so we can upgrade the information for each printer bound to this
1262 ********************************************************************/
1264 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1266 int len
= strlen(drivername
);
1271 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1274 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1279 /**********************************************************************
1280 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1281 over all printers, resetting printer data as neessary
1282 **********************************************************************/
1284 void reset_all_printerdata(int msg_type
, pid_t src
, void *buf
, size_t len
)
1288 int n_services
= lp_numservices();
1290 len
= MIN( len
, sizeof(drivername
)-1 );
1291 strncpy( drivername
, buf
, len
);
1293 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1295 /* Iterate the printer list */
1297 for ( snum
=0; snum
<n_services
; snum
++ )
1299 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1302 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1304 result
= get_a_printer( &printer
, 2, lp_servicename(snum
) );
1305 if ( !W_ERROR_IS_OK(result
) )
1309 * if the printer is bound to the driver,
1310 * then reset to the new driver initdata
1313 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1315 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1317 if ( !set_driver_init(printer
, 2) ) {
1318 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1319 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1322 result
= mod_a_printer( *printer
, 2 );
1323 if ( !W_ERROR_IS_OK(result
) ) {
1324 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1325 get_dos_error_msg(result
)));
1329 free_a_printer( &printer
, 2 );
1338 /********************************************************************
1339 Copy routines used by convert_to_openprinterex()
1340 *******************************************************************/
1342 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1350 DEBUG (8,("dup_devmode\n"));
1352 /* bulk copy first */
1354 d
= talloc_memdup(ctx
, devmode
, sizeof(DEVICEMODE
));
1358 /* dup the pointer members separately */
1360 len
= unistrlen(devmode
->devicename
.buffer
);
1362 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1363 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1368 len
= unistrlen(devmode
->formname
.buffer
);
1370 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1371 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1375 d
->private = talloc_memdup(ctx
, devmode
->private, devmode
->driverextra
);
1380 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1382 if (!new_ctr
|| !ctr
)
1385 DEBUG(8,("copy_devmode_ctr\n"));
1387 new_ctr
->size
= ctr
->size
;
1388 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1390 if(ctr
->devmode_ptr
)
1391 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1394 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1396 if (!new_def
|| !def
)
1399 DEBUG(8,("copy_printer_defaults\n"));
1401 new_def
->datatype_ptr
= def
->datatype_ptr
;
1403 if (def
->datatype_ptr
)
1404 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1406 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1408 new_def
->access_required
= def
->access_required
;
1411 /********************************************************************
1412 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1413 * SPOOL_Q_OPEN_PRINTER_EX structure
1414 ********************************************************************/
1416 static void convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1418 if (!q_u_ex
|| !q_u
)
1421 DEBUG(8,("convert_to_openprinterex\n"));
1423 q_u_ex
->printername_ptr
= q_u
->printername_ptr
;
1425 if (q_u
->printername_ptr
)
1426 copy_unistr2(&q_u_ex
->printername
, &q_u
->printername
);
1428 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1431 /********************************************************************
1432 * spoolss_open_printer
1434 * called from the spoolss dispatcher
1435 ********************************************************************/
1437 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1439 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1440 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1445 ZERO_STRUCT(q_u_ex
);
1446 ZERO_STRUCT(r_u_ex
);
1448 /* convert the OpenPrinter() call to OpenPrinterEx() */
1450 convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1452 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1454 /* convert back to OpenPrinter() */
1456 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1461 /********************************************************************
1462 * spoolss_open_printer
1464 * If the openprinterex rpc call contains a devmode,
1465 * it's a per-user one. This per-user devmode is derivated
1466 * from the global devmode. Openprinterex() contains a per-user
1467 * devmode for when you do EMF printing and spooling.
1468 * In the EMF case, the NT workstation is only doing half the job
1469 * of rendering the page. The other half is done by running the printer
1470 * driver on the server.
1471 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1472 * The EMF file only contains what is to be printed on the page.
1473 * So in order for the server to know how to print, the NT client sends
1474 * a devicemode attached to the openprinterex call.
1475 * But this devicemode is short lived, it's only valid for the current print job.
1477 * If Samba would have supported EMF spooling, this devicemode would
1478 * have been attached to the handle, to sent it to the driver to correctly
1479 * rasterize the EMF file.
1481 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1482 * we just act as a pass-thru between windows and the printer.
1484 * In order to know that Samba supports only RAW spooling, NT has to call
1485 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1486 * and until NT sends a RAW job, we refuse it.
1488 * But to call getprinter() or startdoc(), you first need a valid handle,
1489 * and to get an handle you have to call openprintex(). Hence why you have
1490 * a devicemode in the openprinterex() call.
1493 * Differences between NT4 and NT 2000.
1496 * On NT4, you only have a global devicemode. This global devicemode can be changed
1497 * by the administrator (or by a user with enough privs). Everytime a user
1498 * wants to print, the devicemode is resetted to the default. In Word, everytime
1499 * you print, the printer's characteristics are always reset to the global devicemode.
1503 * In W2K, there is the notion of per-user devicemode. The first time you use
1504 * a printer, a per-user devicemode is build from the global devicemode.
1505 * If you change your per-user devicemode, it is saved in the registry, under the
1506 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1507 * printer preferences available.
1509 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1510 * on the General Tab of the printer properties windows.
1512 * To change the global devicemode: it's the "Printing Defaults..." button
1513 * on the Advanced Tab of the printer properties window.
1516 ********************************************************************/
1518 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1520 UNISTR2
*printername
= NULL
;
1521 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1522 POLICY_HND
*handle
= &r_u
->handle
;
1526 struct current_user user
;
1527 Printer_entry
*Printer
=NULL
;
1529 if (q_u
->printername_ptr
!= 0)
1530 printername
= &q_u
->printername
;
1532 if (printername
== NULL
)
1533 return WERR_INVALID_PRINTER_NAME
;
1535 /* some sanity check because you can open a printer or a print server */
1536 /* aka: \\server\printer or \\server */
1537 unistr2_to_ascii(name
, printername
, sizeof(name
)-1);
1539 DEBUGADD(3,("checking name: %s\n",name
));
1541 if (!open_printer_hnd(p
, handle
, name
, 0))
1542 return WERR_INVALID_PRINTER_NAME
;
1544 Printer
=find_printer_index_by_hnd(p
, handle
);
1546 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1547 Can't find printer handle we created for printer %s\n", name
));
1548 close_printer_handle(p
,handle
);
1549 return WERR_INVALID_PRINTER_NAME
;
1552 get_current_user(&user
, p
);
1555 * First case: the user is opening the print server:
1557 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1558 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1560 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1561 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1562 * or if the user is listed in the smb.conf printer admin parameter.
1564 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1565 * client view printer folder, but does not show the MSAPW.
1567 * Note: this test needs code to check access rights here too. Jeremy
1568 * could you look at this?
1570 * Second case: the user is opening a printer:
1571 * NT doesn't let us connect to a printer if the connecting user
1572 * doesn't have print permission.
1575 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1577 /* Printserver handles use global struct... */
1581 /* Map standard access rights to object specific access rights */
1583 se_map_standard(&printer_default
->access_required
,
1584 &printserver_std_mapping
);
1586 /* Deny any object specific bits that don't apply to print
1587 servers (i.e printer and job specific bits) */
1589 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1591 if (printer_default
->access_required
&
1592 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1593 DEBUG(3, ("access DENIED for non-printserver bits"));
1594 close_printer_handle(p
, handle
);
1595 return WERR_ACCESS_DENIED
;
1598 /* Allow admin access */
1600 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1602 if (!lp_ms_add_printer_wizard()) {
1603 close_printer_handle(p
, handle
);
1604 return WERR_ACCESS_DENIED
;
1607 /* if the user is not root and not a printer admin, then fail */
1610 && !user_in_list(uidtoname(user
.uid
), lp_printer_admin(snum
)) )
1612 close_printer_handle(p
, handle
);
1613 return WERR_ACCESS_DENIED
;
1616 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1620 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1623 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1624 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1626 /* We fall through to return WERR_OK */
1631 /* NT doesn't let us connect to a printer if the connecting user
1632 doesn't have print permission. */
1634 if (!get_printer_snum(p
, handle
, &snum
))
1637 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1639 /* map an empty access mask to the minimum access mask */
1640 if (printer_default
->access_required
== 0x0)
1641 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1644 * If we are not serving the printer driver for this printer,
1645 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1646 * will keep NT clients happy --jerry
1649 if (lp_use_client_driver(snum
)
1650 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1652 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1655 /* check smb.conf parameters and the the sec_desc */
1657 if (!user_ok(uidtoname(user
.uid
), snum
) || !print_access_check(&user
, snum
, printer_default
->access_required
)) {
1658 DEBUG(3, ("access DENIED for printer open\n"));
1659 close_printer_handle(p
, handle
);
1660 return WERR_ACCESS_DENIED
;
1663 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1664 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1665 close_printer_handle(p
, handle
);
1666 return WERR_ACCESS_DENIED
;
1669 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1670 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1672 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1674 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1675 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1679 Printer
->access_granted
= printer_default
->access_required
;
1682 * If the client sent a devmode in the OpenPrinter() call, then
1683 * save it here in case we get a job submission on this handle
1686 if ( (Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTSERVER
)
1687 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1689 convert_devicemode( Printer
->dev
.handlename
, q_u
->printer_default
.devmode_cont
.devmode
,
1690 &Printer
->nt_devmode
);
1696 /****************************************************************************
1697 ****************************************************************************/
1699 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1700 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1706 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
1715 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1716 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1722 printer
->info_3
=NULL
;
1723 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1727 printer
->info_6
=NULL
;
1728 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1738 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1739 NT_DEVICEMODE
**pp_nt_devmode
)
1741 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1744 * Ensure nt_devmode is a valid pointer
1745 * as we will be overwriting it.
1748 if (nt_devmode
== NULL
) {
1749 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1750 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1754 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1755 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1757 nt_devmode
->specversion
=devmode
->specversion
;
1758 nt_devmode
->driverversion
=devmode
->driverversion
;
1759 nt_devmode
->size
=devmode
->size
;
1760 nt_devmode
->fields
=devmode
->fields
;
1761 nt_devmode
->orientation
=devmode
->orientation
;
1762 nt_devmode
->papersize
=devmode
->papersize
;
1763 nt_devmode
->paperlength
=devmode
->paperlength
;
1764 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1765 nt_devmode
->scale
=devmode
->scale
;
1766 nt_devmode
->copies
=devmode
->copies
;
1767 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1768 nt_devmode
->printquality
=devmode
->printquality
;
1769 nt_devmode
->color
=devmode
->color
;
1770 nt_devmode
->duplex
=devmode
->duplex
;
1771 nt_devmode
->yresolution
=devmode
->yresolution
;
1772 nt_devmode
->ttoption
=devmode
->ttoption
;
1773 nt_devmode
->collate
=devmode
->collate
;
1775 nt_devmode
->logpixels
=devmode
->logpixels
;
1776 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1777 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1778 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1779 nt_devmode
->displayflags
=devmode
->displayflags
;
1780 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1781 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1782 nt_devmode
->icmintent
=devmode
->icmintent
;
1783 nt_devmode
->mediatype
=devmode
->mediatype
;
1784 nt_devmode
->dithertype
=devmode
->dithertype
;
1785 nt_devmode
->reserved1
=devmode
->reserved1
;
1786 nt_devmode
->reserved2
=devmode
->reserved2
;
1787 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1788 nt_devmode
->panningheight
=devmode
->panningheight
;
1791 * Only change private and driverextra if the incoming devmode
1792 * has a new one. JRA.
1795 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1796 SAFE_FREE(nt_devmode
->private);
1797 nt_devmode
->driverextra
=devmode
->driverextra
;
1798 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
1800 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1803 *pp_nt_devmode
= nt_devmode
;
1808 /********************************************************************
1809 * _spoolss_enddocprinter_internal.
1810 ********************************************************************/
1812 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1814 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1818 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1822 if (!get_printer_snum(p
, handle
, &snum
))
1825 Printer
->document_started
=False
;
1826 print_job_end(snum
, Printer
->jobid
,True
);
1827 /* error codes unhandled so far ... */
1832 /********************************************************************
1833 * api_spoolss_closeprinter
1834 ********************************************************************/
1836 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1838 POLICY_HND
*handle
= &q_u
->handle
;
1840 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1842 if (Printer
&& Printer
->document_started
)
1843 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1845 if (!close_printer_handle(p
, handle
))
1848 /* clear the returned printer handle. Observed behavior
1849 from Win2k server. Don't think this really matters.
1850 Previous code just copied the value of the closed
1853 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1858 /********************************************************************
1859 * api_spoolss_deleteprinter
1861 ********************************************************************/
1863 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1865 POLICY_HND
*handle
= &q_u
->handle
;
1866 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1869 if (Printer
&& Printer
->document_started
)
1870 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1872 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1874 result
= delete_printer_handle(p
, handle
);
1876 update_c_setprinter(False
);
1881 /*******************************************************************
1882 * static function to lookup the version id corresponding to an
1883 * long architecture string
1884 ******************************************************************/
1886 static int get_version_id (char * arch
)
1889 struct table_node archi_table
[]= {
1891 {"Windows 4.0", "WIN40", 0 },
1892 {"Windows NT x86", "W32X86", 2 },
1893 {"Windows NT R4000", "W32MIPS", 2 },
1894 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1895 {"Windows NT PowerPC", "W32PPC", 2 },
1899 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1901 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1902 return (archi_table
[i
].version
);
1908 /********************************************************************
1909 * _spoolss_deleteprinterdriver
1910 ********************************************************************/
1912 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1916 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1917 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
1919 struct current_user user
;
1921 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1923 get_current_user(&user
, p
);
1925 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1926 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1928 /* check that we have a valid driver name first */
1930 if ((version
=get_version_id(arch
)) == -1)
1931 return WERR_INVALID_ENVIRONMENT
;
1934 ZERO_STRUCT(info_win2k
);
1936 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
1938 /* try for Win2k driver if "Windows NT x86" */
1940 if ( version
== 2 ) {
1942 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
1943 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1947 /* otherwise it was a failure */
1949 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1955 if (printer_driver_in_use(info
.info_3
)) {
1956 status
= WERR_PRINTER_DRIVER_IN_USE
;
1962 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
1964 /* if we get to here, we now have 2 driver info structures to remove */
1965 /* remove the Win2k driver first*/
1967 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, False
);
1968 free_a_printer_driver( info_win2k
, 3 );
1970 /* this should not have failed---if it did, report to client */
1971 if ( !W_ERROR_IS_OK(status_win2k
) )
1976 status
= delete_printer_driver(info
.info_3
, &user
, version
, False
);
1978 /* if at least one of the deletes succeeded return OK */
1980 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
1984 free_a_printer_driver( info
, 3 );
1989 /********************************************************************
1990 * spoolss_deleteprinterdriverex
1991 ********************************************************************/
1993 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
1997 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1998 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2000 uint32 flags
= q_u
->delete_flags
;
2002 struct current_user user
;
2004 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2006 get_current_user(&user
, p
);
2008 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2009 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2011 /* check that we have a valid driver name first */
2012 if ((version
=get_version_id(arch
)) == -1) {
2013 /* this is what NT returns */
2014 return WERR_INVALID_ENVIRONMENT
;
2017 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2018 version
= q_u
->version
;
2021 ZERO_STRUCT(info_win2k
);
2023 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2025 if ( !W_ERROR_IS_OK(status
) )
2028 * if the client asked for a specific version,
2029 * or this is something other than Windows NT x86,
2033 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2036 /* try for Win2k driver if "Windows NT x86" */
2039 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2040 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2045 if ( printer_driver_in_use(info
.info_3
) ) {
2046 status
= WERR_PRINTER_DRIVER_IN_USE
;
2051 * we have a couple of cases to consider.
2052 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2053 * then the delete should fail if **any** files overlap with
2055 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2056 * non-overlapping files
2057 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2058 * is set, the do not delete any files
2059 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2062 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2064 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2066 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2067 /* no idea of the correct error here */
2068 status
= WERR_ACCESS_DENIED
;
2073 /* also check for W32X86/3 if necessary; maybe we already have? */
2075 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2076 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2079 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2080 /* no idea of the correct error here */
2081 free_a_printer_driver( info_win2k
, 3 );
2082 status
= WERR_ACCESS_DENIED
;
2086 /* if we get to here, we now have 2 driver info structures to remove */
2087 /* remove the Win2k driver first*/
2089 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, delete_files
);
2090 free_a_printer_driver( info_win2k
, 3 );
2092 /* this should not have failed---if it did, report to client */
2094 if ( !W_ERROR_IS_OK(status_win2k
) )
2099 status
= delete_printer_driver(info
.info_3
, &user
, version
, delete_files
);
2101 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2104 free_a_printer_driver( info
, 3 );
2110 /****************************************************************************
2111 Internal routine for retreiving printerdata
2112 ***************************************************************************/
2114 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2115 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2116 uint32
*needed
, uint32 in_size
)
2118 REGISTRY_VALUE
*val
;
2121 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2122 return WERR_BADFILE
;
2124 *type
= regval_type( val
);
2126 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2128 size
= regval_size( val
);
2130 /* copy the min(in_size, len) */
2133 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2135 /* special case for 0 length values */
2137 if ( (*data
= (uint8
*)talloc_memdup(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2141 if ( (*data
= (uint8
*)talloc_zero(ctx
, in_size
)) == NULL
)
2150 DEBUG(5,("get_printer_dataex: copy done\n"));
2155 /****************************************************************************
2156 Internal routine for removing printerdata
2157 ***************************************************************************/
2159 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2161 delete_printer_data( printer
->info_2
, key
, value
);
2163 return mod_a_printer(*printer
, 2);
2166 /****************************************************************************
2167 Internal routine for storing printerdata
2168 ***************************************************************************/
2170 static WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2171 uint32 type
, uint8
*data
, int real_len
)
2173 delete_printer_data( printer
->info_2
, key
, value
);
2175 add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2177 return mod_a_printer(*printer
, 2);
2180 /********************************************************************
2181 GetPrinterData on a printer server Handle.
2182 ********************************************************************/
2184 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2188 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2190 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2192 if((*data
= (uint8
*)talloc_zero(ctx
, 4*sizeof(uint8
) )) == NULL
)
2198 if (!StrCaseCmp(value
, "BeepEnabled")) {
2200 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2202 SIVAL(*data
, 0, 0x00);
2207 if (!StrCaseCmp(value
, "EventLog")) {
2209 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2211 /* formally was 0x1b */
2212 SIVAL(*data
, 0, 0x0);
2217 if (!StrCaseCmp(value
, "NetPopup")) {
2219 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2221 SIVAL(*data
, 0, 0x00);
2226 if (!StrCaseCmp(value
, "MajorVersion")) {
2228 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2239 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2242 fstrcpy(string
, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH
));
2244 *needed
= 2*(strlen(string
)+1);
2245 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2247 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2249 /* it's done by hand ready to go on the wire */
2250 for (i
=0; i
<strlen(string
); i
++) {
2251 (*data
)[2*i
]=string
[i
];
2252 (*data
)[2*i
+1]='\0';
2257 if (!StrCaseCmp(value
, "Architecture")) {
2258 pstring string
="Windows NT x86";
2260 *needed
= 2*(strlen(string
)+1);
2261 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2263 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2264 for (i
=0; i
<strlen(string
); i
++) {
2265 (*data
)[2*i
]=string
[i
];
2266 (*data
)[2*i
+1]='\0';
2271 if (!StrCaseCmp(value
, "DsPresent")) {
2273 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2275 SIVAL(*data
, 0, 0x01);
2280 if (!StrCaseCmp(value
, "DNSMachineName")) {
2283 if (!get_myfullname(hostname
))
2284 return WERR_BADFILE
;
2286 *needed
= 2*(strlen(hostname
)+1);
2287 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2289 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2290 for (i
=0; i
<strlen(hostname
); i
++) {
2291 (*data
)[2*i
]=hostname
[i
];
2292 (*data
)[2*i
+1]='\0';
2298 return WERR_BADFILE
;
2301 /********************************************************************
2302 * spoolss_getprinterdata
2303 ********************************************************************/
2305 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2307 POLICY_HND
*handle
= &q_u
->handle
;
2308 UNISTR2
*valuename
= &q_u
->valuename
;
2309 uint32 in_size
= q_u
->size
;
2310 uint32
*type
= &r_u
->type
;
2311 uint32
*out_size
= &r_u
->size
;
2312 uint8
**data
= &r_u
->data
;
2313 uint32
*needed
= &r_u
->needed
;
2316 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2317 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2321 * Reminder: when it's a string, the length is in BYTES
2322 * even if UNICODE is negociated.
2327 *out_size
= in_size
;
2329 /* in case of problem, return some default values */
2334 DEBUG(4,("_spoolss_getprinterdata\n"));
2337 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2338 status
= WERR_BADFID
;
2342 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2344 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2345 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2348 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2349 status
= WERR_BADFID
;
2353 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
2354 if ( !W_ERROR_IS_OK(status
) )
2357 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2359 if ( strequal(value
, "ChangeId") ) {
2361 *needed
= sizeof(uint32
);
2362 if ( (*data
= (uint8
*)talloc(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2363 status
= WERR_NOMEM
;
2366 **data
= printer
->info_2
->changeid
;
2370 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2373 if (*needed
> *out_size
)
2374 status
= WERR_MORE_DATA
;
2377 if ( !W_ERROR_IS_OK(status
) )
2379 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2381 /* reply this param doesn't exist */
2384 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
2386 free_a_printer( &printer
, 2 );
2395 /* cleanup & exit */
2398 free_a_printer( &printer
, 2 );
2403 /*********************************************************
2404 Connect to the client machine.
2405 **********************************************************/
2407 static BOOL
spoolss_connect_to_client(struct cli_state
*the_cli
, const char *remote_machine
)
2409 ZERO_STRUCTP(the_cli
);
2410 if(cli_initialise(the_cli
) == NULL
) {
2411 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2415 if(!resolve_name( remote_machine
, &the_cli
->dest_ip
, 0x20)) {
2416 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine
));
2417 cli_shutdown(the_cli
);
2421 if (ismyip(the_cli
->dest_ip
)) {
2422 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2423 cli_shutdown(the_cli
);
2427 if (!cli_connect(the_cli
, remote_machine
, &the_cli
->dest_ip
)) {
2428 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2429 cli_shutdown(the_cli
);
2433 if (!attempt_netbios_session_request(the_cli
, global_myname(), remote_machine
, &the_cli
->dest_ip
)) {
2434 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2436 cli_shutdown(the_cli
);
2440 the_cli
->protocol
= PROTOCOL_NT1
;
2442 if (!cli_negprot(the_cli
)) {
2443 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2444 cli_shutdown(the_cli
);
2448 if (the_cli
->protocol
!= PROTOCOL_NT1
) {
2449 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2450 cli_shutdown(the_cli
);
2455 * Do an anonymous session setup.
2458 if (!cli_session_setup(the_cli
, "", "", 0, "", 0, "")) {
2459 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2460 cli_shutdown(the_cli
);
2464 if (!(the_cli
->sec_mode
& 1)) {
2465 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine
));
2466 cli_shutdown(the_cli
);
2470 if (!cli_send_tconX(the_cli
, "IPC$", "IPC", "", 1)) {
2471 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2472 cli_shutdown(the_cli
);
2477 * Ok - we have an anonymous connection to the IPC$ share.
2478 * Now start the NT Domain stuff :-).
2481 if(cli_nt_session_open(the_cli
, PI_SPOOLSS
) == False
) {
2482 DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
)));
2483 cli_nt_session_close(the_cli
);
2484 cli_ulogoff(the_cli
);
2485 cli_shutdown(the_cli
);
2492 /***************************************************************************
2493 Connect to the client.
2494 ****************************************************************************/
2496 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
, uint32 localprinter
, uint32 type
, POLICY_HND
*handle
)
2501 * If it's the first connection, contact the client
2502 * and connect to the IPC$ share anonumously
2504 if (smb_connections
==0) {
2505 fstring unix_printer
;
2507 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2509 if(!spoolss_connect_to_client(¬ify_cli
, unix_printer
))
2512 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message_list
);
2513 /* Tell the connections db we're now interested in printer
2514 * notify messages. */
2515 register_message_flags( True
, FLAG_MSG_PRINTING
);
2519 * Tell the specific printing tdb we want messages for this printer
2520 * by registering our PID.
2523 if (!print_notify_register_pid(snum
))
2524 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2528 result
= cli_spoolss_reply_open_printer(¬ify_cli
, notify_cli
.mem_ctx
, printer
, localprinter
,
2531 if (!W_ERROR_IS_OK(result
))
2532 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2533 dos_errstr(result
)));
2535 return (W_ERROR_IS_OK(result
));
2538 /********************************************************************
2540 * ReplyFindFirstPrinterChangeNotifyEx
2542 * before replying OK: status=0 a rpc call is made to the workstation
2543 * asking ReplyOpenPrinter
2545 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2546 * called from api_spoolss_rffpcnex
2547 ********************************************************************/
2549 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2551 POLICY_HND
*handle
= &q_u
->handle
;
2552 uint32 flags
= q_u
->flags
;
2553 uint32 options
= q_u
->options
;
2554 UNISTR2
*localmachine
= &q_u
->localmachine
;
2555 uint32 printerlocal
= q_u
->printerlocal
;
2557 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2559 /* store the notify value in the printer struct */
2561 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2564 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2568 Printer
->notify
.flags
=flags
;
2569 Printer
->notify
.options
=options
;
2570 Printer
->notify
.printerlocal
=printerlocal
;
2572 if (Printer
->notify
.option
)
2573 free_spool_notify_option(&Printer
->notify
.option
);
2575 Printer
->notify
.option
=dup_spool_notify_option(option
);
2577 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2578 sizeof(Printer
->notify
.localmachine
)-1);
2580 /* Connect to the client machine and send a ReplyOpenPrinter */
2582 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2584 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
2585 !get_printer_snum(p
, handle
, &snum
) )
2588 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2589 Printer
->notify
.printerlocal
, 1,
2590 &Printer
->notify
.client_hnd
))
2591 return WERR_SERVER_UNAVAILABLE
;
2593 Printer
->notify
.client_connected
=True
;
2598 /*******************************************************************
2599 * fill a notify_info_data with the servername
2600 ********************************************************************/
2602 void spoolss_notify_server_name(int snum
,
2603 SPOOL_NOTIFY_INFO_DATA
*data
,
2604 print_queue_struct
*queue
,
2605 NT_PRINTER_INFO_LEVEL
*printer
,
2606 TALLOC_CTX
*mem_ctx
)
2608 pstring temp_name
, temp
;
2611 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
2613 len
= rpcstr_push(temp
, temp_name
, sizeof(temp
)-2, STR_TERMINATE
);
2615 data
->notify_data
.data
.length
= len
;
2616 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2618 if (!data
->notify_data
.data
.string
) {
2619 data
->notify_data
.data
.length
= 0;
2623 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2626 /*******************************************************************
2627 * fill a notify_info_data with the printername (not including the servername).
2628 ********************************************************************/
2630 void spoolss_notify_printer_name(int snum
,
2631 SPOOL_NOTIFY_INFO_DATA
*data
,
2632 print_queue_struct
*queue
,
2633 NT_PRINTER_INFO_LEVEL
*printer
,
2634 TALLOC_CTX
*mem_ctx
)
2639 /* the notify name should not contain the \\server\ part */
2640 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2643 p
= printer
->info_2
->printername
;
2648 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2650 data
->notify_data
.data
.length
= len
;
2651 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2653 if (!data
->notify_data
.data
.string
) {
2654 data
->notify_data
.data
.length
= 0;
2658 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2661 /*******************************************************************
2662 * fill a notify_info_data with the servicename
2663 ********************************************************************/
2665 void spoolss_notify_share_name(int snum
,
2666 SPOOL_NOTIFY_INFO_DATA
*data
,
2667 print_queue_struct
*queue
,
2668 NT_PRINTER_INFO_LEVEL
*printer
,
2669 TALLOC_CTX
*mem_ctx
)
2674 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2676 data
->notify_data
.data
.length
= len
;
2677 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2679 if (!data
->notify_data
.data
.string
) {
2680 data
->notify_data
.data
.length
= 0;
2684 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2687 /*******************************************************************
2688 * fill a notify_info_data with the port name
2689 ********************************************************************/
2691 void spoolss_notify_port_name(int snum
,
2692 SPOOL_NOTIFY_INFO_DATA
*data
,
2693 print_queue_struct
*queue
,
2694 NT_PRINTER_INFO_LEVEL
*printer
,
2695 TALLOC_CTX
*mem_ctx
)
2700 /* even if it's strange, that's consistant in all the code */
2702 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2704 data
->notify_data
.data
.length
= len
;
2705 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2707 if (!data
->notify_data
.data
.string
) {
2708 data
->notify_data
.data
.length
= 0;
2712 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2715 /*******************************************************************
2716 * fill a notify_info_data with the printername
2717 * but it doesn't exist, have to see what to do
2718 ********************************************************************/
2720 void spoolss_notify_driver_name(int snum
,
2721 SPOOL_NOTIFY_INFO_DATA
*data
,
2722 print_queue_struct
*queue
,
2723 NT_PRINTER_INFO_LEVEL
*printer
,
2724 TALLOC_CTX
*mem_ctx
)
2729 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2731 data
->notify_data
.data
.length
= len
;
2732 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2734 if (!data
->notify_data
.data
.string
) {
2735 data
->notify_data
.data
.length
= 0;
2739 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2742 /*******************************************************************
2743 * fill a notify_info_data with the comment
2744 ********************************************************************/
2746 void spoolss_notify_comment(int snum
,
2747 SPOOL_NOTIFY_INFO_DATA
*data
,
2748 print_queue_struct
*queue
,
2749 NT_PRINTER_INFO_LEVEL
*printer
,
2750 TALLOC_CTX
*mem_ctx
)
2755 if (*printer
->info_2
->comment
== '\0')
2756 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2758 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2760 data
->notify_data
.data
.length
= len
;
2761 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2763 if (!data
->notify_data
.data
.string
) {
2764 data
->notify_data
.data
.length
= 0;
2768 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2771 /*******************************************************************
2772 * fill a notify_info_data with the comment
2773 * location = "Room 1, floor 2, building 3"
2774 ********************************************************************/
2776 void spoolss_notify_location(int snum
,
2777 SPOOL_NOTIFY_INFO_DATA
*data
,
2778 print_queue_struct
*queue
,
2779 NT_PRINTER_INFO_LEVEL
*printer
,
2780 TALLOC_CTX
*mem_ctx
)
2785 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2787 data
->notify_data
.data
.length
= len
;
2788 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2790 if (!data
->notify_data
.data
.string
) {
2791 data
->notify_data
.data
.length
= 0;
2795 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2798 /*******************************************************************
2799 * fill a notify_info_data with the device mode
2800 * jfm:xxxx don't to it for know but that's a real problem !!!
2801 ********************************************************************/
2803 static void spoolss_notify_devmode(int snum
,
2804 SPOOL_NOTIFY_INFO_DATA
*data
,
2805 print_queue_struct
*queue
,
2806 NT_PRINTER_INFO_LEVEL
*printer
,
2807 TALLOC_CTX
*mem_ctx
)
2811 /*******************************************************************
2812 * fill a notify_info_data with the separator file name
2813 ********************************************************************/
2815 void spoolss_notify_sepfile(int snum
,
2816 SPOOL_NOTIFY_INFO_DATA
*data
,
2817 print_queue_struct
*queue
,
2818 NT_PRINTER_INFO_LEVEL
*printer
,
2819 TALLOC_CTX
*mem_ctx
)
2824 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2826 data
->notify_data
.data
.length
= len
;
2827 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2829 if (!data
->notify_data
.data
.string
) {
2830 data
->notify_data
.data
.length
= 0;
2834 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2837 /*******************************************************************
2838 * fill a notify_info_data with the print processor
2839 * jfm:xxxx return always winprint to indicate we don't do anything to it
2840 ********************************************************************/
2842 void spoolss_notify_print_processor(int snum
,
2843 SPOOL_NOTIFY_INFO_DATA
*data
,
2844 print_queue_struct
*queue
,
2845 NT_PRINTER_INFO_LEVEL
*printer
,
2846 TALLOC_CTX
*mem_ctx
)
2851 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
2853 data
->notify_data
.data
.length
= len
;
2854 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2856 if (!data
->notify_data
.data
.string
) {
2857 data
->notify_data
.data
.length
= 0;
2861 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2864 /*******************************************************************
2865 * fill a notify_info_data with the print processor options
2866 * jfm:xxxx send an empty string
2867 ********************************************************************/
2869 void spoolss_notify_parameters(int snum
,
2870 SPOOL_NOTIFY_INFO_DATA
*data
,
2871 print_queue_struct
*queue
,
2872 NT_PRINTER_INFO_LEVEL
*printer
,
2873 TALLOC_CTX
*mem_ctx
)
2878 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
2880 data
->notify_data
.data
.length
= len
;
2881 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2883 if (!data
->notify_data
.data
.string
) {
2884 data
->notify_data
.data
.length
= 0;
2888 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2891 /*******************************************************************
2892 * fill a notify_info_data with the data type
2893 * jfm:xxxx always send RAW as data type
2894 ********************************************************************/
2896 void spoolss_notify_datatype(int snum
,
2897 SPOOL_NOTIFY_INFO_DATA
*data
,
2898 print_queue_struct
*queue
,
2899 NT_PRINTER_INFO_LEVEL
*printer
,
2900 TALLOC_CTX
*mem_ctx
)
2905 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
2907 data
->notify_data
.data
.length
= len
;
2908 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2910 if (!data
->notify_data
.data
.string
) {
2911 data
->notify_data
.data
.length
= 0;
2915 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2918 /*******************************************************************
2919 * fill a notify_info_data with the security descriptor
2920 * jfm:xxxx send an null pointer to say no security desc
2921 * have to implement security before !
2922 ********************************************************************/
2924 static void spoolss_notify_security_desc(int snum
,
2925 SPOOL_NOTIFY_INFO_DATA
*data
,
2926 print_queue_struct
*queue
,
2927 NT_PRINTER_INFO_LEVEL
*printer
,
2928 TALLOC_CTX
*mem_ctx
)
2930 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
2931 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
2934 /*******************************************************************
2935 * fill a notify_info_data with the attributes
2936 * jfm:xxxx a samba printer is always shared
2937 ********************************************************************/
2939 void spoolss_notify_attributes(int snum
,
2940 SPOOL_NOTIFY_INFO_DATA
*data
,
2941 print_queue_struct
*queue
,
2942 NT_PRINTER_INFO_LEVEL
*printer
,
2943 TALLOC_CTX
*mem_ctx
)
2945 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
2946 data
->notify_data
.value
[1] = 0;
2949 /*******************************************************************
2950 * fill a notify_info_data with the priority
2951 ********************************************************************/
2953 static void spoolss_notify_priority(int snum
,
2954 SPOOL_NOTIFY_INFO_DATA
*data
,
2955 print_queue_struct
*queue
,
2956 NT_PRINTER_INFO_LEVEL
*printer
,
2957 TALLOC_CTX
*mem_ctx
)
2959 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
2960 data
->notify_data
.value
[1] = 0;
2963 /*******************************************************************
2964 * fill a notify_info_data with the default priority
2965 ********************************************************************/
2967 static void spoolss_notify_default_priority(int snum
,
2968 SPOOL_NOTIFY_INFO_DATA
*data
,
2969 print_queue_struct
*queue
,
2970 NT_PRINTER_INFO_LEVEL
*printer
,
2971 TALLOC_CTX
*mem_ctx
)
2973 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
2974 data
->notify_data
.value
[1] = 0;
2977 /*******************************************************************
2978 * fill a notify_info_data with the start time
2979 ********************************************************************/
2981 static void spoolss_notify_start_time(int snum
,
2982 SPOOL_NOTIFY_INFO_DATA
*data
,
2983 print_queue_struct
*queue
,
2984 NT_PRINTER_INFO_LEVEL
*printer
,
2985 TALLOC_CTX
*mem_ctx
)
2987 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
2988 data
->notify_data
.value
[1] = 0;
2991 /*******************************************************************
2992 * fill a notify_info_data with the until time
2993 ********************************************************************/
2995 static void spoolss_notify_until_time(int snum
,
2996 SPOOL_NOTIFY_INFO_DATA
*data
,
2997 print_queue_struct
*queue
,
2998 NT_PRINTER_INFO_LEVEL
*printer
,
2999 TALLOC_CTX
*mem_ctx
)
3001 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
3002 data
->notify_data
.value
[1] = 0;
3005 /*******************************************************************
3006 * fill a notify_info_data with the status
3007 ********************************************************************/
3009 static void spoolss_notify_status(int snum
,
3010 SPOOL_NOTIFY_INFO_DATA
*data
,
3011 print_queue_struct
*queue
,
3012 NT_PRINTER_INFO_LEVEL
*printer
,
3013 TALLOC_CTX
*mem_ctx
)
3015 print_status_struct status
;
3017 print_queue_length(snum
, &status
);
3018 data
->notify_data
.value
[0]=(uint32
) status
.status
;
3019 data
->notify_data
.value
[1] = 0;
3022 /*******************************************************************
3023 * fill a notify_info_data with the number of jobs queued
3024 ********************************************************************/
3026 void spoolss_notify_cjobs(int snum
,
3027 SPOOL_NOTIFY_INFO_DATA
*data
,
3028 print_queue_struct
*queue
,
3029 NT_PRINTER_INFO_LEVEL
*printer
,
3030 TALLOC_CTX
*mem_ctx
)
3032 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3033 data
->notify_data
.value
[1] = 0;
3036 /*******************************************************************
3037 * fill a notify_info_data with the average ppm
3038 ********************************************************************/
3040 static void spoolss_notify_average_ppm(int snum
,
3041 SPOOL_NOTIFY_INFO_DATA
*data
,
3042 print_queue_struct
*queue
,
3043 NT_PRINTER_INFO_LEVEL
*printer
,
3044 TALLOC_CTX
*mem_ctx
)
3046 /* always respond 8 pages per minutes */
3047 /* a little hard ! */
3048 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3049 data
->notify_data
.value
[1] = 0;
3052 /*******************************************************************
3053 * fill a notify_info_data with username
3054 ********************************************************************/
3056 static void spoolss_notify_username(int snum
,
3057 SPOOL_NOTIFY_INFO_DATA
*data
,
3058 print_queue_struct
*queue
,
3059 NT_PRINTER_INFO_LEVEL
*printer
,
3060 TALLOC_CTX
*mem_ctx
)
3065 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3067 data
->notify_data
.data
.length
= len
;
3068 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3070 if (!data
->notify_data
.data
.string
) {
3071 data
->notify_data
.data
.length
= 0;
3075 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3078 /*******************************************************************
3079 * fill a notify_info_data with job status
3080 ********************************************************************/
3082 static void spoolss_notify_job_status(int snum
,
3083 SPOOL_NOTIFY_INFO_DATA
*data
,
3084 print_queue_struct
*queue
,
3085 NT_PRINTER_INFO_LEVEL
*printer
,
3086 TALLOC_CTX
*mem_ctx
)
3088 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3089 data
->notify_data
.value
[1] = 0;
3092 /*******************************************************************
3093 * fill a notify_info_data with job name
3094 ********************************************************************/
3096 static void spoolss_notify_job_name(int snum
,
3097 SPOOL_NOTIFY_INFO_DATA
*data
,
3098 print_queue_struct
*queue
,
3099 NT_PRINTER_INFO_LEVEL
*printer
,
3100 TALLOC_CTX
*mem_ctx
)
3105 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3107 data
->notify_data
.data
.length
= len
;
3108 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3110 if (!data
->notify_data
.data
.string
) {
3111 data
->notify_data
.data
.length
= 0;
3115 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3118 /*******************************************************************
3119 * fill a notify_info_data with job status
3120 ********************************************************************/
3122 static void spoolss_notify_job_status_string(int snum
,
3123 SPOOL_NOTIFY_INFO_DATA
*data
,
3124 print_queue_struct
*queue
,
3125 NT_PRINTER_INFO_LEVEL
*printer
,
3126 TALLOC_CTX
*mem_ctx
)
3129 * Now we're returning job status codes we just return a "" here. JRA.
3136 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3139 switch (queue
->status
) {
3144 p
= ""; /* NT provides the paused string */
3153 #endif /* NO LONGER NEEDED. */
3155 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3157 data
->notify_data
.data
.length
= len
;
3158 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3160 if (!data
->notify_data
.data
.string
) {
3161 data
->notify_data
.data
.length
= 0;
3165 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3168 /*******************************************************************
3169 * fill a notify_info_data with job time
3170 ********************************************************************/
3172 static void spoolss_notify_job_time(int snum
,
3173 SPOOL_NOTIFY_INFO_DATA
*data
,
3174 print_queue_struct
*queue
,
3175 NT_PRINTER_INFO_LEVEL
*printer
,
3176 TALLOC_CTX
*mem_ctx
)
3178 data
->notify_data
.value
[0]=0x0;
3179 data
->notify_data
.value
[1]=0;
3182 /*******************************************************************
3183 * fill a notify_info_data with job size
3184 ********************************************************************/
3186 static void spoolss_notify_job_size(int snum
,
3187 SPOOL_NOTIFY_INFO_DATA
*data
,
3188 print_queue_struct
*queue
,
3189 NT_PRINTER_INFO_LEVEL
*printer
,
3190 TALLOC_CTX
*mem_ctx
)
3192 data
->notify_data
.value
[0]=queue
->size
;
3193 data
->notify_data
.value
[1]=0;
3196 /*******************************************************************
3197 * fill a notify_info_data with page info
3198 ********************************************************************/
3199 static void spoolss_notify_total_pages(int snum
,
3200 SPOOL_NOTIFY_INFO_DATA
*data
,
3201 print_queue_struct
*queue
,
3202 NT_PRINTER_INFO_LEVEL
*printer
,
3203 TALLOC_CTX
*mem_ctx
)
3205 data
->notify_data
.value
[0]=queue
->page_count
;
3206 data
->notify_data
.value
[1]=0;
3209 /*******************************************************************
3210 * fill a notify_info_data with pages printed info.
3211 ********************************************************************/
3212 static void spoolss_notify_pages_printed(int snum
,
3213 SPOOL_NOTIFY_INFO_DATA
*data
,
3214 print_queue_struct
*queue
,
3215 NT_PRINTER_INFO_LEVEL
*printer
,
3216 TALLOC_CTX
*mem_ctx
)
3218 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3219 data
->notify_data
.value
[1]=0;
3222 /*******************************************************************
3223 Fill a notify_info_data with job position.
3224 ********************************************************************/
3226 static void spoolss_notify_job_position(int snum
,
3227 SPOOL_NOTIFY_INFO_DATA
*data
,
3228 print_queue_struct
*queue
,
3229 NT_PRINTER_INFO_LEVEL
*printer
,
3230 TALLOC_CTX
*mem_ctx
)
3232 data
->notify_data
.value
[0]=queue
->job
;
3233 data
->notify_data
.value
[1]=0;
3236 /*******************************************************************
3237 Fill a notify_info_data with submitted time.
3238 ********************************************************************/
3240 static void spoolss_notify_submitted_time(int snum
,
3241 SPOOL_NOTIFY_INFO_DATA
*data
,
3242 print_queue_struct
*queue
,
3243 NT_PRINTER_INFO_LEVEL
*printer
,
3244 TALLOC_CTX
*mem_ctx
)
3251 t
=gmtime(&queue
->time
);
3253 len
= sizeof(SYSTEMTIME
);
3255 data
->notify_data
.data
.length
= len
;
3256 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3258 if (!data
->notify_data
.data
.string
) {
3259 data
->notify_data
.data
.length
= 0;
3263 make_systemtime(&st
, t
);
3266 * Systemtime must be linearized as a set of UINT16's.
3267 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3270 p
= (char *)data
->notify_data
.data
.string
;
3271 SSVAL(p
, 0, st
.year
);
3272 SSVAL(p
, 2, st
.month
);
3273 SSVAL(p
, 4, st
.dayofweek
);
3274 SSVAL(p
, 6, st
.day
);
3275 SSVAL(p
, 8, st
.hour
);
3276 SSVAL(p
, 10, st
.minute
);
3277 SSVAL(p
, 12, st
.second
);
3278 SSVAL(p
, 14, st
.milliseconds
);
3281 struct s_notify_info_data_table
3287 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3288 print_queue_struct
*queue
,
3289 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3292 /* A table describing the various print notification constants and
3293 whether the notification data is a pointer to a variable sized
3294 buffer, a one value uint32 or a two value uint32. */
3296 static const struct s_notify_info_data_table notify_info_data_table
[] =
3298 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3299 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3300 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3301 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3302 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3303 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3304 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3305 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3306 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3307 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3308 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3309 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3310 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3311 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3312 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3313 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3314 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3315 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3316 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3317 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3318 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3319 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3320 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3321 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3322 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3323 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3324 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3325 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3326 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3327 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3328 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3329 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3330 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3331 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3332 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3333 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3334 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3335 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3336 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3337 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3338 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3339 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3340 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3341 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3342 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3343 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3344 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3345 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3346 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3349 /*******************************************************************
3350 Return the size of info_data structure.
3351 ********************************************************************/
3353 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3357 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++)
3359 if ( (notify_info_data_table
[i
].type
== type
)
3360 && (notify_info_data_table
[i
].field
== field
) )
3362 switch(notify_info_data_table
[i
].size
)
3364 case NOTIFY_ONE_VALUE
:
3365 case NOTIFY_TWO_VALUE
:
3370 /* The only pointer notify data I have seen on
3371 the wire is the submitted time and this has
3372 the notify size set to 4. -tpot */
3374 case NOTIFY_POINTER
:
3377 case NOTIFY_SECDESC
:
3383 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3388 /*******************************************************************
3389 Return the type of notify_info_data.
3390 ********************************************************************/
3392 static int type_of_notify_info_data(uint16 type
, uint16 field
)
3396 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3397 if (notify_info_data_table
[i
].type
== type
&&
3398 notify_info_data_table
[i
].field
== field
)
3399 return notify_info_data_table
[i
].size
;
3405 /****************************************************************************
3406 ****************************************************************************/
3408 static int search_notify(uint16 type
, uint16 field
, int *value
)
3412 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3413 if (notify_info_data_table
[i
].type
== type
&&
3414 notify_info_data_table
[i
].field
== field
&&
3415 notify_info_data_table
[i
].fn
!= NULL
) {
3424 /****************************************************************************
3425 ****************************************************************************/
3427 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3429 info_data
->type
= type
;
3430 info_data
->field
= field
;
3431 info_data
->reserved
= 0;
3433 info_data
->size
= size_of_notify_info_data(type
, field
);
3434 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3441 /*******************************************************************
3443 * fill a notify_info struct with info asked
3445 ********************************************************************/
3447 static BOOL
construct_notify_printer_info(SPOOL_NOTIFY_INFO
*info
, int
3448 snum
, SPOOL_NOTIFY_OPTION_TYPE
3449 *option_type
, uint32 id
,
3450 TALLOC_CTX
*mem_ctx
)
3456 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3457 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3458 print_queue_struct
*queue
=NULL
;
3460 type
=option_type
->type
;
3462 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3463 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3464 option_type
->count
, lp_servicename(snum
)));
3466 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3469 for(field_num
=0; field_num
<option_type
->count
; field_num
++)
3471 field
= option_type
->fields
[field_num
];
3473 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3475 if (!search_notify(type
, field
, &j
) )
3478 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
)
3480 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3486 current_data
= &info
->data
[info
->count
];
3488 construct_info_data(current_data
, type
, field
, id
);
3490 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3491 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3493 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3499 free_a_printer(&printer
, 2);
3503 /*******************************************************************
3505 * fill a notify_info struct with info asked
3507 ********************************************************************/
3509 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3510 SPOOL_NOTIFY_INFO
*info
,
3511 NT_PRINTER_INFO_LEVEL
*printer
,
3512 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3513 *option_type
, uint32 id
,
3514 TALLOC_CTX
*mem_ctx
)
3520 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3522 DEBUG(4,("construct_notify_jobs_info\n"));
3524 type
= option_type
->type
;
3526 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3527 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3528 option_type
->count
));
3530 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3531 field
= option_type
->fields
[field_num
];
3533 if (!search_notify(type
, field
, &j
) )
3536 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
3537 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3540 else info
->data
= tid
;
3542 current_data
=&(info
->data
[info
->count
]);
3544 construct_info_data(current_data
, type
, field
, id
);
3545 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3554 * JFM: The enumeration is not that simple, it's even non obvious.
3556 * let's take an example: I want to monitor the PRINTER SERVER for
3557 * the printer's name and the number of jobs currently queued.
3558 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3559 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3561 * I have 3 printers on the back of my server.
3563 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3566 * 1 printer 1 name 1
3567 * 2 printer 1 cjob 1
3568 * 3 printer 2 name 2
3569 * 4 printer 2 cjob 2
3570 * 5 printer 3 name 3
3571 * 6 printer 3 name 3
3573 * that's the print server case, the printer case is even worse.
3576 /*******************************************************************
3578 * enumerate all printers on the printserver
3579 * fill a notify_info struct with info asked
3581 ********************************************************************/
3583 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3584 SPOOL_NOTIFY_INFO
*info
,
3585 TALLOC_CTX
*mem_ctx
)
3588 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3589 int n_services
=lp_numservices();
3592 SPOOL_NOTIFY_OPTION
*option
;
3593 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3595 DEBUG(4,("printserver_notify_info\n"));
3600 option
=Printer
->notify
.option
;
3606 for (i
=0; i
<option
->count
; i
++) {
3607 option_type
=&(option
->ctr
.type
[i
]);
3609 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3612 for (snum
=0; snum
<n_services
; snum
++)
3614 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3615 construct_notify_printer_info ( info
, snum
, option_type
, snum
, mem_ctx
);
3621 * Debugging information, don't delete.
3624 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3625 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3626 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3628 for (i
=0; i
<info
->count
; i
++) {
3629 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3630 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3631 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3638 /*******************************************************************
3640 * fill a notify_info struct with info asked
3642 ********************************************************************/
3644 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3645 TALLOC_CTX
*mem_ctx
)
3648 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3651 SPOOL_NOTIFY_OPTION
*option
;
3652 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3654 print_queue_struct
*queue
=NULL
;
3655 print_status_struct status
;
3657 DEBUG(4,("printer_notify_info\n"));
3662 option
=Printer
->notify
.option
;
3668 get_printer_snum(p
, hnd
, &snum
);
3670 for (i
=0; i
<option
->count
; i
++) {
3671 option_type
=&option
->ctr
.type
[i
];
3673 switch ( option_type
->type
) {
3674 case PRINTER_NOTIFY_TYPE
:
3675 if(construct_notify_printer_info(info
, snum
,
3681 case JOB_NOTIFY_TYPE
: {
3682 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3684 count
= print_queue_status(snum
, &queue
, &status
);
3686 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2,
3687 lp_servicename(snum
))))
3690 for (j
=0; j
<count
; j
++) {
3691 construct_notify_jobs_info(&queue
[j
], info
,
3698 free_a_printer(&printer
, 2);
3708 * Debugging information, don't delete.
3711 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3712 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3713 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3715 for (i=0; i<info->count; i++) {
3716 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3717 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3718 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3724 /********************************************************************
3726 ********************************************************************/
3728 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3730 POLICY_HND
*handle
= &q_u
->handle
;
3731 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3733 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3734 WERROR result
= WERR_BADFID
;
3736 /* we always have a NOTIFY_INFO struct */
3740 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3741 OUR_HANDLE(handle
)));
3745 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3748 * We are now using the change value, and
3749 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3750 * I don't have a global notification system, I'm sending back all the
3751 * informations even when _NOTHING_ has changed.
3754 /* We need to keep track of the change value to send back in
3755 RRPCN replies otherwise our updates are ignored. */
3757 Printer
->notify
.fnpcn
= True
;
3759 if (Printer
->notify
.client_connected
) {
3760 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3761 Printer
->notify
.change
= q_u
->change
;
3764 /* just ignore the SPOOL_NOTIFY_OPTION */
3766 switch (Printer
->printer_type
) {
3767 case PRINTER_HANDLE_IS_PRINTSERVER
:
3768 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3771 case PRINTER_HANDLE_IS_PRINTER
:
3772 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3776 Printer
->notify
.fnpcn
= False
;
3782 /********************************************************************
3783 * construct_printer_info_0
3784 * fill a printer_info_0 struct
3785 ********************************************************************/
3787 static BOOL
construct_printer_info_0(PRINTER_INFO_0
*printer
, int snum
)
3791 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3792 counter_printer_0
*session_counter
;
3793 uint32 global_counter
;
3796 print_status_struct status
;
3798 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3801 count
= print_queue_length(snum
, &status
);
3803 /* check if we already have a counter for this printer */
3804 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
3806 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
3807 if (session_counter
->snum
== snum
)
3811 /* it's the first time, add it to the list */
3812 if (session_counter
==NULL
) {
3813 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
3814 free_a_printer(&ntprinter
, 2);
3817 ZERO_STRUCTP(session_counter
);
3818 session_counter
->snum
=snum
;
3819 session_counter
->counter
=0;
3820 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
3824 session_counter
->counter
++;
3827 * the global_counter should be stored in a TDB as it's common to all the clients
3828 * and should be zeroed on samba startup
3830 global_counter
=session_counter
->counter
;
3832 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3834 init_unistr(&printer
->printername
, chaine
);
3836 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_called_name());
3837 init_unistr(&printer
->servername
, chaine
);
3839 printer
->cjobs
= count
;
3840 printer
->total_jobs
= 0;
3841 printer
->total_bytes
= 0;
3843 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3844 t
=gmtime(&setuptime
);
3846 printer
->year
= t
->tm_year
+1900;
3847 printer
->month
= t
->tm_mon
+1;
3848 printer
->dayofweek
= t
->tm_wday
;
3849 printer
->day
= t
->tm_mday
;
3850 printer
->hour
= t
->tm_hour
;
3851 printer
->minute
= t
->tm_min
;
3852 printer
->second
= t
->tm_sec
;
3853 printer
->milliseconds
= 0;
3855 printer
->global_counter
= global_counter
;
3856 printer
->total_pages
= 0;
3858 printer
->major_version
= 0x0005; /* NT 5 */
3859 printer
->build_version
= 0x0893; /* build 2195 */
3861 printer
->major_version
= 0x0004; /* NT 4 */
3862 printer
->build_version
= 0x0565; /* build 1381 */
3864 printer
->unknown7
= 0x1;
3865 printer
->unknown8
= 0x0;
3866 printer
->unknown9
= 0x0;
3867 printer
->session_counter
= session_counter
->counter
;
3868 printer
->unknown11
= 0x0;
3869 printer
->printer_errors
= 0x0; /* number of print failure */
3870 printer
->unknown13
= 0x0;
3871 printer
->unknown14
= 0x1;
3872 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
3873 printer
->unknown16
= 0x0;
3874 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3875 printer
->unknown18
= 0x0;
3876 printer
->status
= nt_printq_status(status
.status
);
3877 printer
->unknown20
= 0x0;
3878 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3879 printer
->unknown22
= 0x0;
3880 printer
->unknown23
= 0x6; /* 6 ???*/
3881 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
3882 printer
->unknown25
= 0;
3883 printer
->unknown26
= 0;
3884 printer
->unknown27
= 0;
3885 printer
->unknown28
= 0;
3886 printer
->unknown29
= 0;
3888 free_a_printer(&ntprinter
,2);
3892 /********************************************************************
3893 * construct_printer_info_1
3894 * fill a printer_info_1 struct
3895 ********************************************************************/
3896 static BOOL
construct_printer_info_1(uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
3900 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3902 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3905 printer
->flags
=flags
;
3907 if (*ntprinter
->info_2
->comment
== '\0') {
3908 init_unistr(&printer
->comment
, lp_comment(snum
));
3909 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3910 ntprinter
->info_2
->drivername
, lp_comment(snum
));
3913 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3914 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3915 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
3918 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
3920 init_unistr(&printer
->description
, chaine
);
3921 init_unistr(&printer
->name
, chaine2
);
3923 free_a_printer(&ntprinter
,2);
3928 /****************************************************************************
3929 Free a DEVMODE struct.
3930 ****************************************************************************/
3932 static void free_dev_mode(DEVICEMODE
*dev
)
3937 SAFE_FREE(dev
->private);
3942 /****************************************************************************
3943 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3944 should be valid upon entry
3945 ****************************************************************************/
3947 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
3949 if ( !devmode
|| !ntdevmode
)
3952 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
3954 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
3956 devmode
->specversion
= ntdevmode
->specversion
;
3957 devmode
->driverversion
= ntdevmode
->driverversion
;
3958 devmode
->size
= ntdevmode
->size
;
3959 devmode
->driverextra
= ntdevmode
->driverextra
;
3960 devmode
->fields
= ntdevmode
->fields
;
3962 devmode
->orientation
= ntdevmode
->orientation
;
3963 devmode
->papersize
= ntdevmode
->papersize
;
3964 devmode
->paperlength
= ntdevmode
->paperlength
;
3965 devmode
->paperwidth
= ntdevmode
->paperwidth
;
3966 devmode
->scale
= ntdevmode
->scale
;
3967 devmode
->copies
= ntdevmode
->copies
;
3968 devmode
->defaultsource
= ntdevmode
->defaultsource
;
3969 devmode
->printquality
= ntdevmode
->printquality
;
3970 devmode
->color
= ntdevmode
->color
;
3971 devmode
->duplex
= ntdevmode
->duplex
;
3972 devmode
->yresolution
= ntdevmode
->yresolution
;
3973 devmode
->ttoption
= ntdevmode
->ttoption
;
3974 devmode
->collate
= ntdevmode
->collate
;
3975 devmode
->icmmethod
= ntdevmode
->icmmethod
;
3976 devmode
->icmintent
= ntdevmode
->icmintent
;
3977 devmode
->mediatype
= ntdevmode
->mediatype
;
3978 devmode
->dithertype
= ntdevmode
->dithertype
;
3980 if (ntdevmode
->private != NULL
) {
3981 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
3988 /****************************************************************************
3989 Create a DEVMODE struct. Returns malloced memory.
3990 ****************************************************************************/
3992 DEVICEMODE
*construct_dev_mode(int snum
)
3994 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3995 DEVICEMODE
*devmode
= NULL
;
3997 DEBUG(7,("construct_dev_mode\n"));
3999 DEBUGADD(8,("getting printer characteristics\n"));
4001 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4004 if ( !printer
->info_2
->devmode
) {
4005 DEBUG(5, ("BONG! There was no device mode!\n"));
4009 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
4010 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4014 ZERO_STRUCTP(devmode
);
4016 DEBUGADD(8,("loading DEVICEMODE\n"));
4018 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
4019 free_dev_mode( devmode
);
4024 free_a_printer(&printer
,2);
4029 /********************************************************************
4030 * construct_printer_info_2
4031 * fill a printer_info_2 struct
4032 ********************************************************************/
4034 static BOOL
construct_printer_info_2(PRINTER_INFO_2
*printer
, int snum
)
4037 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4039 print_status_struct status
;
4041 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4044 count
= print_queue_length(snum
, &status
);
4046 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4047 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4048 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4049 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4050 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4052 if (*ntprinter
->info_2
->comment
== '\0')
4053 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4055 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4057 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4058 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4059 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4060 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4061 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4063 printer
->attributes
= ntprinter
->info_2
->attributes
;
4065 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4066 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4067 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4068 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4069 printer
->status
= nt_printq_status(status
.status
); /* status */
4070 printer
->cjobs
= count
; /* jobs */
4071 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4073 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
4074 DEBUG(8, ("Returning NULL Devicemode!\n"));
4077 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4078 /* steal the printer info sec_desc structure. [badly done]. */
4079 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4080 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
4081 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
4082 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
4085 printer
->secdesc
= NULL
;
4088 free_a_printer(&ntprinter
, 2);
4092 /********************************************************************
4093 * construct_printer_info_3
4094 * fill a printer_info_3 struct
4095 ********************************************************************/
4097 static BOOL
construct_printer_info_3(PRINTER_INFO_3
**pp_printer
, int snum
)
4099 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4100 PRINTER_INFO_3
*printer
= NULL
;
4102 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4106 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
4107 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4111 ZERO_STRUCTP(printer
);
4113 printer
->flags
= 4; /* These are the components of the SD we are returning. */
4114 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4115 /* steal the printer info sec_desc structure. [badly done]. */
4116 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4120 * Set the flags for the components we are returning.
4123 if (printer
->secdesc
->owner_sid
)
4124 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
4126 if (printer
->secdesc
->grp_sid
)
4127 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
4129 if (printer
->secdesc
->dacl
)
4130 printer
->flags
|= DACL_SECURITY_INFORMATION
;
4132 if (printer
->secdesc
->sacl
)
4133 printer
->flags
|= SACL_SECURITY_INFORMATION
;
4136 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
4137 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
4138 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
4141 free_a_printer(&ntprinter
, 2);
4143 *pp_printer
= printer
;
4147 /********************************************************************
4148 * construct_printer_info_4
4149 * fill a printer_info_4 struct
4150 ********************************************************************/
4152 static BOOL
construct_printer_info_4(PRINTER_INFO_4
*printer
, int snum
)
4154 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4156 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4159 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4160 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4161 printer
->attributes
= ntprinter
->info_2
->attributes
;
4163 free_a_printer(&ntprinter
, 2);
4167 /********************************************************************
4168 * construct_printer_info_5
4169 * fill a printer_info_5 struct
4170 ********************************************************************/
4172 static BOOL
construct_printer_info_5(PRINTER_INFO_5
*printer
, int snum
)
4174 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4176 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4179 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4180 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* portname */
4181 printer
->attributes
= ntprinter
->info_2
->attributes
;
4182 printer
->device_not_selected_timeout
= 0x3a98;
4183 printer
->transmission_retry_timeout
= 0xafc8;
4185 free_a_printer(&ntprinter
, 2);
4189 /********************************************************************
4190 * construct_printer_info_7
4191 * fill a printer_info_7 struct
4192 ********************************************************************/
4194 static BOOL
construct_printer_info_7(PRINTER_INFO_7
*printer
, int snum
)
4196 char *guid_str
= NULL
;
4199 if (is_printer_published(snum
, &guid
)) {
4200 asprintf(&guid_str
, "{%s}", uuid_string_static(guid
));
4202 init_unistr(&printer
->guid
, guid_str
);
4203 printer
->action
= SPOOL_DS_PUBLISH
;
4205 init_unistr(&printer
->guid
, "");
4206 printer
->action
= SPOOL_DS_UNPUBLISH
;
4212 /********************************************************************
4213 Spoolss_enumprinters.
4214 ********************************************************************/
4216 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4220 int n_services
=lp_numservices();
4221 PRINTER_INFO_1
*tp
, *printers
=NULL
;
4222 PRINTER_INFO_1 current_prt
;
4224 DEBUG(4,("enum_all_printers_info_1\n"));
4226 for (snum
=0; snum
<n_services
; snum
++) {
4227 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4228 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4230 if (construct_printer_info_1(flags
, ¤t_prt
, snum
)) {
4231 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
4232 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4233 SAFE_FREE(printers
);
4238 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4240 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4246 /* check the required size. */
4247 for (i
=0; i
<*returned
; i
++)
4248 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4250 if (!alloc_buffer_size(buffer
, *needed
))
4251 return WERR_INSUFFICIENT_BUFFER
;
4253 /* fill the buffer with the structures */
4254 for (i
=0; i
<*returned
; i
++)
4255 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4258 SAFE_FREE(printers
);
4260 if (*needed
> offered
) {
4262 return WERR_INSUFFICIENT_BUFFER
;
4268 /********************************************************************
4269 enum_all_printers_info_1_local.
4270 *********************************************************************/
4272 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4274 DEBUG(4,("enum_all_printers_info_1_local\n"));
4276 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4279 /********************************************************************
4280 enum_all_printers_info_1_name.
4281 *********************************************************************/
4283 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4287 DEBUG(4,("enum_all_printers_info_1_name\n"));
4289 if ((name
[0] == '\\') && (name
[1] == '\\'))
4292 if (is_myname_or_ipaddr(s
)) {
4293 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4296 return WERR_INVALID_NAME
;
4299 /********************************************************************
4300 enum_all_printers_info_1_remote.
4301 *********************************************************************/
4303 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4305 PRINTER_INFO_1
*printer
;
4306 fstring printername
;
4309 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4311 /* JFM: currently it's more a place holder than anything else.
4312 * In the spooler world there is a notion of server registration.
4313 * the print servers are registring (sp ?) on the PDC (in the same domain)
4315 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4318 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4323 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4324 slprintf(desc
, sizeof(desc
)-1,"%s", get_called_name());
4325 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4327 init_unistr(&printer
->description
, desc
);
4328 init_unistr(&printer
->name
, printername
);
4329 init_unistr(&printer
->comment
, comment
);
4330 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4332 /* check the required size. */
4333 *needed
+= spoolss_size_printer_info_1(printer
);
4335 if (!alloc_buffer_size(buffer
, *needed
)) {
4337 return WERR_INSUFFICIENT_BUFFER
;
4340 /* fill the buffer with the structures */
4341 smb_io_printer_info_1("", buffer
, printer
, 0);
4346 if (*needed
> offered
) {
4348 return WERR_INSUFFICIENT_BUFFER
;
4354 /********************************************************************
4355 enum_all_printers_info_1_network.
4356 *********************************************************************/
4358 static WERROR
enum_all_printers_info_1_network(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4362 DEBUG(4,("enum_all_printers_info_1_network\n"));
4364 /* If we respond to a enum_printers level 1 on our name with flags
4365 set to PRINTER_ENUM_REMOTE with a list of printers then these
4366 printers incorrectly appear in the APW browse list.
4367 Specifically the printers for the server appear at the workgroup
4368 level where all the other servers in the domain are
4369 listed. Windows responds to this call with a
4370 WERR_CAN_NOT_COMPLETE so we should do the same. */
4372 if (name
[0] == '\\' && name
[1] == '\\')
4375 if (is_myname_or_ipaddr(s
))
4376 return WERR_CAN_NOT_COMPLETE
;
4378 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4381 /********************************************************************
4382 * api_spoolss_enumprinters
4384 * called from api_spoolss_enumprinters (see this to understand)
4385 ********************************************************************/
4387 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4391 int n_services
=lp_numservices();
4392 PRINTER_INFO_2
*tp
, *printers
=NULL
;
4393 PRINTER_INFO_2 current_prt
;
4395 for (snum
=0; snum
<n_services
; snum
++) {
4396 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4397 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4399 if (construct_printer_info_2(¤t_prt
, snum
)) {
4400 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
4401 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4402 SAFE_FREE(printers
);
4407 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
4408 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4414 /* check the required size. */
4415 for (i
=0; i
<*returned
; i
++)
4416 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4418 if (!alloc_buffer_size(buffer
, *needed
)) {
4419 for (i
=0; i
<*returned
; i
++) {
4420 free_devmode(printers
[i
].devmode
);
4422 SAFE_FREE(printers
);
4423 return WERR_INSUFFICIENT_BUFFER
;
4426 /* fill the buffer with the structures */
4427 for (i
=0; i
<*returned
; i
++)
4428 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4431 for (i
=0; i
<*returned
; i
++) {
4432 free_devmode(printers
[i
].devmode
);
4434 SAFE_FREE(printers
);
4436 if (*needed
> offered
) {
4438 return WERR_INSUFFICIENT_BUFFER
;
4444 /********************************************************************
4445 * handle enumeration of printers at level 1
4446 ********************************************************************/
4448 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4449 NEW_BUFFER
*buffer
, uint32 offered
,
4450 uint32
*needed
, uint32
*returned
)
4452 /* Not all the flags are equals */
4454 if (flags
& PRINTER_ENUM_LOCAL
)
4455 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4457 if (flags
& PRINTER_ENUM_NAME
)
4458 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4460 if (flags
& PRINTER_ENUM_REMOTE
)
4461 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4463 if (flags
& PRINTER_ENUM_NETWORK
)
4464 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4466 return WERR_OK
; /* NT4sp5 does that */
4469 /********************************************************************
4470 * handle enumeration of printers at level 2
4471 ********************************************************************/
4473 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4474 NEW_BUFFER
*buffer
, uint32 offered
,
4475 uint32
*needed
, uint32
*returned
)
4477 char *s
= servername
;
4479 if (flags
& PRINTER_ENUM_LOCAL
) {
4480 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4483 if (flags
& PRINTER_ENUM_NAME
) {
4484 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4486 if (is_myname_or_ipaddr(s
))
4487 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4489 return WERR_INVALID_NAME
;
4492 if (flags
& PRINTER_ENUM_REMOTE
)
4493 return WERR_UNKNOWN_LEVEL
;
4498 /********************************************************************
4499 * handle enumeration of printers at level 5
4500 ********************************************************************/
4502 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4503 NEW_BUFFER
*buffer
, uint32 offered
,
4504 uint32
*needed
, uint32
*returned
)
4506 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4510 /********************************************************************
4511 * api_spoolss_enumprinters
4513 * called from api_spoolss_enumprinters (see this to understand)
4514 ********************************************************************/
4516 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4518 uint32 flags
= q_u
->flags
;
4519 UNISTR2
*servername
= &q_u
->servername
;
4520 uint32 level
= q_u
->level
;
4521 NEW_BUFFER
*buffer
= NULL
;
4522 uint32 offered
= q_u
->offered
;
4523 uint32
*needed
= &r_u
->needed
;
4524 uint32
*returned
= &r_u
->returned
;
4528 /* that's an [in out] buffer */
4529 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4530 buffer
= r_u
->buffer
;
4532 DEBUG(4,("_spoolss_enumprinters\n"));
4539 * flags==PRINTER_ENUM_NAME
4540 * if name=="" then enumerates all printers
4541 * if name!="" then enumerate the printer
4542 * flags==PRINTER_ENUM_REMOTE
4543 * name is NULL, enumerate printers
4544 * Level 2: name!="" enumerates printers, name can't be NULL
4545 * Level 3: doesn't exist
4546 * Level 4: does a local registry lookup
4547 * Level 5: same as Level 2
4550 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4555 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4557 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4559 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4564 return WERR_UNKNOWN_LEVEL
;
4567 /****************************************************************************
4568 ****************************************************************************/
4570 static WERROR
getprinter_level_0(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4572 PRINTER_INFO_0
*printer
=NULL
;
4574 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
4577 construct_printer_info_0(printer
, snum
);
4579 /* check the required size. */
4580 *needed
+= spoolss_size_printer_info_0(printer
);
4582 if (!alloc_buffer_size(buffer
, *needed
)) {
4584 return WERR_INSUFFICIENT_BUFFER
;
4587 /* fill the buffer with the structures */
4588 smb_io_printer_info_0("", buffer
, printer
, 0);
4593 if (*needed
> offered
) {
4594 return WERR_INSUFFICIENT_BUFFER
;
4600 /****************************************************************************
4601 ****************************************************************************/
4603 static WERROR
getprinter_level_1(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4605 PRINTER_INFO_1
*printer
=NULL
;
4607 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4610 construct_printer_info_1(PRINTER_ENUM_ICON8
, printer
, snum
);
4612 /* check the required size. */
4613 *needed
+= spoolss_size_printer_info_1(printer
);
4615 if (!alloc_buffer_size(buffer
, *needed
)) {
4617 return WERR_INSUFFICIENT_BUFFER
;
4620 /* fill the buffer with the structures */
4621 smb_io_printer_info_1("", buffer
, printer
, 0);
4626 if (*needed
> offered
) {
4627 return WERR_INSUFFICIENT_BUFFER
;
4633 /****************************************************************************
4634 ****************************************************************************/
4636 static WERROR
getprinter_level_2(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4638 PRINTER_INFO_2
*printer
=NULL
;
4640 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
4643 construct_printer_info_2(printer
, snum
);
4645 /* check the required size. */
4646 *needed
+= spoolss_size_printer_info_2(printer
);
4648 if (!alloc_buffer_size(buffer
, *needed
)) {
4649 free_printer_info_2(printer
);
4650 return WERR_INSUFFICIENT_BUFFER
;
4653 /* fill the buffer with the structures */
4654 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
4655 free_printer_info_2(printer
);
4660 free_printer_info_2(printer
);
4662 if (*needed
> offered
) {
4663 return WERR_INSUFFICIENT_BUFFER
;
4669 /****************************************************************************
4670 ****************************************************************************/
4672 static WERROR
getprinter_level_3(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4674 PRINTER_INFO_3
*printer
=NULL
;
4676 if (!construct_printer_info_3(&printer
, snum
))
4679 /* check the required size. */
4680 *needed
+= spoolss_size_printer_info_3(printer
);
4682 if (!alloc_buffer_size(buffer
, *needed
)) {
4683 free_printer_info_3(printer
);
4684 return WERR_INSUFFICIENT_BUFFER
;
4687 /* fill the buffer with the structures */
4688 smb_io_printer_info_3("", buffer
, printer
, 0);
4691 free_printer_info_3(printer
);
4693 if (*needed
> offered
) {
4694 return WERR_INSUFFICIENT_BUFFER
;
4700 /****************************************************************************
4701 ****************************************************************************/
4703 static WERROR
getprinter_level_4(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4705 PRINTER_INFO_4
*printer
=NULL
;
4707 if((printer
=(PRINTER_INFO_4
*)malloc(sizeof(PRINTER_INFO_4
)))==NULL
)
4710 if (!construct_printer_info_4(printer
, snum
))
4713 /* check the required size. */
4714 *needed
+= spoolss_size_printer_info_4(printer
);
4716 if (!alloc_buffer_size(buffer
, *needed
)) {
4717 free_printer_info_4(printer
);
4718 return WERR_INSUFFICIENT_BUFFER
;
4721 /* fill the buffer with the structures */
4722 smb_io_printer_info_4("", buffer
, printer
, 0);
4725 free_printer_info_4(printer
);
4727 if (*needed
> offered
) {
4728 return WERR_INSUFFICIENT_BUFFER
;
4734 /****************************************************************************
4735 ****************************************************************************/
4737 static WERROR
getprinter_level_5(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4739 PRINTER_INFO_5
*printer
=NULL
;
4741 if((printer
=(PRINTER_INFO_5
*)malloc(sizeof(PRINTER_INFO_5
)))==NULL
)
4744 if (!construct_printer_info_5(printer
, snum
))
4747 /* check the required size. */
4748 *needed
+= spoolss_size_printer_info_5(printer
);
4750 if (!alloc_buffer_size(buffer
, *needed
)) {
4751 free_printer_info_5(printer
);
4752 return WERR_INSUFFICIENT_BUFFER
;
4755 /* fill the buffer with the structures */
4756 smb_io_printer_info_5("", buffer
, printer
, 0);
4759 free_printer_info_5(printer
);
4761 if (*needed
> offered
) {
4762 return WERR_INSUFFICIENT_BUFFER
;
4768 static WERROR
getprinter_level_7(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4770 PRINTER_INFO_7
*printer
=NULL
;
4772 if((printer
=(PRINTER_INFO_7
*)malloc(sizeof(PRINTER_INFO_7
)))==NULL
)
4775 if (!construct_printer_info_7(printer
, snum
))
4778 /* check the required size. */
4779 *needed
+= spoolss_size_printer_info_7(printer
);
4781 if (!alloc_buffer_size(buffer
, *needed
)) {
4782 free_printer_info_7(printer
);
4783 return WERR_INSUFFICIENT_BUFFER
;
4786 /* fill the buffer with the structures */
4787 smb_io_printer_info_7("", buffer
, printer
, 0);
4790 free_printer_info_7(printer
);
4792 if (*needed
> offered
) {
4793 return WERR_INSUFFICIENT_BUFFER
;
4799 /****************************************************************************
4800 ****************************************************************************/
4802 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
4804 POLICY_HND
*handle
= &q_u
->handle
;
4805 uint32 level
= q_u
->level
;
4806 NEW_BUFFER
*buffer
= NULL
;
4807 uint32 offered
= q_u
->offered
;
4808 uint32
*needed
= &r_u
->needed
;
4812 /* that's an [in out] buffer */
4813 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4814 buffer
= r_u
->buffer
;
4818 if (!get_printer_snum(p
, handle
, &snum
))
4823 return getprinter_level_0(snum
, buffer
, offered
, needed
);
4825 return getprinter_level_1(snum
, buffer
, offered
, needed
);
4827 return getprinter_level_2(snum
, buffer
, offered
, needed
);
4829 return getprinter_level_3(snum
, buffer
, offered
, needed
);
4831 return getprinter_level_4(snum
, buffer
, offered
, needed
);
4833 return getprinter_level_5(snum
, buffer
, offered
, needed
);
4835 return getprinter_level_7(snum
, buffer
, offered
, needed
);
4837 return WERR_UNKNOWN_LEVEL
;
4840 /********************************************************************
4841 * fill a DRIVER_INFO_1 struct
4842 ********************************************************************/
4844 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
4846 init_unistr( &info
->name
, driver
.info_3
->name
);
4849 /********************************************************************
4850 * construct_printer_driver_info_1
4851 ********************************************************************/
4853 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4855 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4856 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4858 ZERO_STRUCT(driver
);
4860 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4861 return WERR_INVALID_PRINTER_NAME
;
4863 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4864 return WERR_UNKNOWN_PRINTER_DRIVER
;
4866 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
4868 free_a_printer(&printer
,2);
4873 /********************************************************************
4874 * construct_printer_driver_info_2
4875 * fill a printer_info_2 struct
4876 ********************************************************************/
4878 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4882 info
->version
=driver
.info_3
->cversion
;
4884 init_unistr( &info
->name
, driver
.info_3
->name
);
4885 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4888 if (strlen(driver
.info_3
->driverpath
)) {
4889 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4890 init_unistr( &info
->driverpath
, temp
);
4892 init_unistr( &info
->driverpath
, "" );
4894 if (strlen(driver
.info_3
->datafile
)) {
4895 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4896 init_unistr( &info
->datafile
, temp
);
4898 init_unistr( &info
->datafile
, "" );
4900 if (strlen(driver
.info_3
->configfile
)) {
4901 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4902 init_unistr( &info
->configfile
, temp
);
4904 init_unistr( &info
->configfile
, "" );
4907 /********************************************************************
4908 * construct_printer_driver_info_2
4909 * fill a printer_info_2 struct
4910 ********************************************************************/
4912 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4914 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4915 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4917 ZERO_STRUCT(printer
);
4918 ZERO_STRUCT(driver
);
4920 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4921 return WERR_INVALID_PRINTER_NAME
;
4923 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4924 return WERR_UNKNOWN_PRINTER_DRIVER
;
4926 fill_printer_driver_info_2(info
, driver
, servername
);
4928 free_a_printer(&printer
,2);
4933 /********************************************************************
4934 * copy a strings array and convert to UNICODE
4936 * convert an array of ascii string to a UNICODE string
4937 ********************************************************************/
4939 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
4947 DEBUG(6,("init_unistr_array\n"));
4958 v
= ""; /* hack to handle null lists */
4961 /* hack to allow this to be used in places other than when generating
4962 the list of dependent files */
4965 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
4969 DEBUGADD(6,("%d:%s:%d\n", i
, line
, strlen(line
)));
4971 /* add one extra unit16 for the second terminating NULL */
4973 if ( (tuary
=Realloc(*uni_array
, (j
+1+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
4974 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4982 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
4987 /* special case for ""; we need to add both NULL's here */
4989 (*uni_array
)[j
++]=0x0000;
4990 (*uni_array
)[j
]=0x0000;
4993 DEBUGADD(6,("last one:done\n"));
4995 /* return size of array in uint16's */
5000 /********************************************************************
5001 * construct_printer_info_3
5002 * fill a printer_info_3 struct
5003 ********************************************************************/
5005 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5011 info
->version
=driver
.info_3
->cversion
;
5013 init_unistr( &info
->name
, driver
.info_3
->name
);
5014 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5016 if (strlen(driver
.info_3
->driverpath
)) {
5017 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5018 init_unistr( &info
->driverpath
, temp
);
5020 init_unistr( &info
->driverpath
, "" );
5022 if (strlen(driver
.info_3
->datafile
)) {
5023 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5024 init_unistr( &info
->datafile
, temp
);
5026 init_unistr( &info
->datafile
, "" );
5028 if (strlen(driver
.info_3
->configfile
)) {
5029 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5030 init_unistr( &info
->configfile
, temp
);
5032 init_unistr( &info
->configfile
, "" );
5034 if (strlen(driver
.info_3
->helpfile
)) {
5035 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5036 init_unistr( &info
->helpfile
, temp
);
5038 init_unistr( &info
->helpfile
, "" );
5040 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5041 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5043 info
->dependentfiles
=NULL
;
5044 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5047 /********************************************************************
5048 * construct_printer_info_3
5049 * fill a printer_info_3 struct
5050 ********************************************************************/
5052 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5054 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5055 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5057 ZERO_STRUCT(driver
);
5059 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
5060 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5061 if (!W_ERROR_IS_OK(status
))
5062 return WERR_INVALID_PRINTER_NAME
;
5064 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5065 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5070 * I put this code in during testing. Helpful when commenting out the
5071 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5072 * as win2k always queries the driver using an infor level of 6.
5073 * I've left it in (but ifdef'd out) because I'll probably
5074 * use it in experimentation again in the future. --jerry 22/01/2002
5077 if (!W_ERROR_IS_OK(status
)) {
5079 * Is this a W2k client ?
5082 /* Yes - try again with a WinNT driver. */
5084 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5085 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5089 if (!W_ERROR_IS_OK(status
)) {
5090 free_a_printer(&printer
,2);
5091 return WERR_UNKNOWN_PRINTER_DRIVER
;
5099 fill_printer_driver_info_3(info
, driver
, servername
);
5101 free_a_printer(&printer
,2);
5106 /********************************************************************
5107 * construct_printer_info_6
5108 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5109 ********************************************************************/
5111 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5117 memset(&nullstr
, '\0', sizeof(fstring
));
5119 info
->version
=driver
.info_3
->cversion
;
5121 init_unistr( &info
->name
, driver
.info_3
->name
);
5122 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5124 if (strlen(driver
.info_3
->driverpath
)) {
5125 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5126 init_unistr( &info
->driverpath
, temp
);
5128 init_unistr( &info
->driverpath
, "" );
5130 if (strlen(driver
.info_3
->datafile
)) {
5131 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5132 init_unistr( &info
->datafile
, temp
);
5134 init_unistr( &info
->datafile
, "" );
5136 if (strlen(driver
.info_3
->configfile
)) {
5137 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5138 init_unistr( &info
->configfile
, temp
);
5140 init_unistr( &info
->configfile
, "" );
5142 if (strlen(driver
.info_3
->helpfile
)) {
5143 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5144 init_unistr( &info
->helpfile
, temp
);
5146 init_unistr( &info
->helpfile
, "" );
5148 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5149 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5151 info
->dependentfiles
= NULL
;
5152 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5154 info
->previousdrivernames
=NULL
;
5155 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5157 info
->driver_date
.low
=0;
5158 info
->driver_date
.high
=0;
5161 info
->driver_version_low
=0;
5162 info
->driver_version_high
=0;
5164 init_unistr( &info
->mfgname
, "");
5165 init_unistr( &info
->oem_url
, "");
5166 init_unistr( &info
->hardware_id
, "");
5167 init_unistr( &info
->provider
, "");
5170 /********************************************************************
5171 * construct_printer_info_6
5172 * fill a printer_info_6 struct
5173 ********************************************************************/
5175 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5176 fstring servername
, fstring architecture
, uint32 version
)
5178 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5179 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5182 ZERO_STRUCT(driver
);
5184 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
5186 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5188 if (!W_ERROR_IS_OK(status
))
5189 return WERR_INVALID_PRINTER_NAME
;
5191 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5193 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5195 if (!W_ERROR_IS_OK(status
))
5198 * Is this a W2k client ?
5202 free_a_printer(&printer
,2);
5203 return WERR_UNKNOWN_PRINTER_DRIVER
;
5206 /* Yes - try again with a WinNT driver. */
5208 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5209 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5210 if (!W_ERROR_IS_OK(status
)) {
5211 free_a_printer(&printer
,2);
5212 return WERR_UNKNOWN_PRINTER_DRIVER
;
5216 fill_printer_driver_info_6(info
, driver
, servername
);
5218 free_a_printer(&printer
,2);
5219 free_a_printer_driver(driver
, 3);
5224 /****************************************************************************
5225 ****************************************************************************/
5227 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5229 SAFE_FREE(info
->dependentfiles
);
5232 /****************************************************************************
5233 ****************************************************************************/
5235 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5237 SAFE_FREE(info
->dependentfiles
);
5241 /****************************************************************************
5242 ****************************************************************************/
5244 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5246 DRIVER_INFO_1
*info
=NULL
;
5249 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
5252 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5253 if (!W_ERROR_IS_OK(status
)) {
5258 /* check the required size. */
5259 *needed
+= spoolss_size_printer_driver_info_1(info
);
5261 if (!alloc_buffer_size(buffer
, *needed
)) {
5263 return WERR_INSUFFICIENT_BUFFER
;
5266 /* fill the buffer with the structures */
5267 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5272 if (*needed
> offered
)
5273 return WERR_INSUFFICIENT_BUFFER
;
5278 /****************************************************************************
5279 ****************************************************************************/
5281 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5283 DRIVER_INFO_2
*info
=NULL
;
5286 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
5289 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5290 if (!W_ERROR_IS_OK(status
)) {
5295 /* check the required size. */
5296 *needed
+= spoolss_size_printer_driver_info_2(info
);
5298 if (!alloc_buffer_size(buffer
, *needed
)) {
5300 return WERR_INSUFFICIENT_BUFFER
;
5303 /* fill the buffer with the structures */
5304 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5309 if (*needed
> offered
)
5310 return WERR_INSUFFICIENT_BUFFER
;
5315 /****************************************************************************
5316 ****************************************************************************/
5318 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5325 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5326 if (!W_ERROR_IS_OK(status
)) {
5330 /* check the required size. */
5331 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5333 if (!alloc_buffer_size(buffer
, *needed
)) {
5334 free_printer_driver_info_3(&info
);
5335 return WERR_INSUFFICIENT_BUFFER
;
5338 /* fill the buffer with the structures */
5339 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5341 free_printer_driver_info_3(&info
);
5343 if (*needed
> offered
)
5344 return WERR_INSUFFICIENT_BUFFER
;
5349 /****************************************************************************
5350 ****************************************************************************/
5352 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5359 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5360 if (!W_ERROR_IS_OK(status
)) {
5364 /* check the required size. */
5365 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5367 if (!alloc_buffer_size(buffer
, *needed
)) {
5368 free_printer_driver_info_6(&info
);
5369 return WERR_INSUFFICIENT_BUFFER
;
5372 /* fill the buffer with the structures */
5373 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5375 free_printer_driver_info_6(&info
);
5377 if (*needed
> offered
)
5378 return WERR_INSUFFICIENT_BUFFER
;
5383 /****************************************************************************
5384 ****************************************************************************/
5386 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5388 POLICY_HND
*handle
= &q_u
->handle
;
5389 UNISTR2
*uni_arch
= &q_u
->architecture
;
5390 uint32 level
= q_u
->level
;
5391 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5392 NEW_BUFFER
*buffer
= NULL
;
5393 uint32 offered
= q_u
->offered
;
5394 uint32
*needed
= &r_u
->needed
;
5395 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5396 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5399 fstring architecture
;
5402 /* that's an [in out] buffer */
5403 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5404 buffer
= r_u
->buffer
;
5406 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5409 *servermajorversion
= 0;
5410 *serverminorversion
= 0;
5412 fstrcpy(servername
, get_called_name());
5413 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5415 if (!get_printer_snum(p
, handle
, &snum
))
5420 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5422 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5424 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5426 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5429 return WERR_UNKNOWN_LEVEL
;
5432 /****************************************************************************
5433 ****************************************************************************/
5435 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5437 POLICY_HND
*handle
= &q_u
->handle
;
5439 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5442 DEBUG(3,("Error in startpageprinter printer handle\n"));
5446 Printer
->page_started
=True
;
5450 /****************************************************************************
5451 ****************************************************************************/
5453 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5455 POLICY_HND
*handle
= &q_u
->handle
;
5458 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5461 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5465 if (!get_printer_snum(p
, handle
, &snum
))
5468 Printer
->page_started
=False
;
5469 print_job_endpage(snum
, Printer
->jobid
);
5474 /********************************************************************
5475 * api_spoolss_getprinter
5476 * called from the spoolss dispatcher
5478 ********************************************************************/
5480 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5482 POLICY_HND
*handle
= &q_u
->handle
;
5483 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5484 uint32
*jobid
= &r_u
->jobid
;
5486 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5490 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5491 struct current_user user
;
5494 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5498 get_current_user(&user
, p
);
5501 * a nice thing with NT is it doesn't listen to what you tell it.
5502 * when asked to send _only_ RAW datas, it tries to send datas
5505 * So I add checks like in NT Server ...
5508 if (info_1
->p_datatype
!= 0) {
5509 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5510 if (strcmp(datatype
, "RAW") != 0) {
5512 return WERR_INVALID_DATATYPE
;
5516 /* get the share number of the printer */
5517 if (!get_printer_snum(p
, handle
, &snum
)) {
5521 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5523 Printer
->jobid
= print_job_start(&user
, snum
, jobname
, Printer
->nt_devmode
);
5525 /* An error occured in print_job_start() so return an appropriate
5528 if (Printer
->jobid
== -1) {
5529 return map_werror_from_unix(errno
);
5532 Printer
->document_started
=True
;
5533 (*jobid
) = Printer
->jobid
;
5538 /********************************************************************
5539 * api_spoolss_getprinter
5540 * called from the spoolss dispatcher
5542 ********************************************************************/
5544 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5546 POLICY_HND
*handle
= &q_u
->handle
;
5548 return _spoolss_enddocprinter_internal(p
, handle
);
5551 /****************************************************************************
5552 ****************************************************************************/
5554 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5556 POLICY_HND
*handle
= &q_u
->handle
;
5557 uint32 buffer_size
= q_u
->buffer_size
;
5558 uint8
*buffer
= q_u
->buffer
;
5559 uint32
*buffer_written
= &q_u
->buffer_size2
;
5561 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5564 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5565 r_u
->buffer_written
= q_u
->buffer_size2
;
5569 if (!get_printer_snum(p
, handle
, &snum
))
5572 (*buffer_written
) = print_job_write(snum
, Printer
->jobid
, (char *)buffer
, buffer_size
);
5573 if (*buffer_written
== -1) {
5574 r_u
->buffer_written
= 0;
5575 if (errno
== ENOSPC
)
5576 return WERR_NO_SPOOL_SPACE
;
5578 return WERR_ACCESS_DENIED
;
5581 r_u
->buffer_written
= q_u
->buffer_size2
;
5586 /********************************************************************
5587 * api_spoolss_getprinter
5588 * called from the spoolss dispatcher
5590 ********************************************************************/
5592 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5595 struct current_user user
;
5597 WERROR errcode
= WERR_BADFUNC
;
5598 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5600 get_current_user(&user
, p
);
5603 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5607 if (!get_printer_snum(p
, handle
, &snum
))
5611 case PRINTER_CONTROL_PAUSE
:
5612 if (print_queue_pause(&user
, snum
, &errcode
)) {
5616 case PRINTER_CONTROL_RESUME
:
5617 case PRINTER_CONTROL_UNPAUSE
:
5618 if (print_queue_resume(&user
, snum
, &errcode
)) {
5622 case PRINTER_CONTROL_PURGE
:
5623 if (print_queue_purge(&user
, snum
, &errcode
)) {
5628 return WERR_UNKNOWN_LEVEL
;
5634 /********************************************************************
5635 * api_spoolss_abortprinter
5636 * From MSDN: "Deletes printer's spool file if printer is configured
5638 ********************************************************************/
5640 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5642 POLICY_HND
*handle
= &q_u
->handle
;
5643 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5645 struct current_user user
;
5646 WERROR errcode
= WERR_OK
;
5649 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5653 if (!get_printer_snum(p
, handle
, &snum
))
5656 get_current_user( &user
, p
);
5658 print_job_delete( &user
, snum
, Printer
->jobid
, &errcode
);
5663 /********************************************************************
5664 * called by spoolss_api_setprinter
5665 * when updating a printer description
5666 ********************************************************************/
5668 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5669 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5670 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5672 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5673 struct current_user user
;
5677 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5679 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5680 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5681 OUR_HANDLE(handle
)));
5683 result
= WERR_BADFID
;
5687 /* NT seems to like setting the security descriptor even though
5688 nothing may have actually changed. This causes annoying
5689 dialog boxes when the user doesn't have permission to change
5690 the security descriptor. */
5692 nt_printing_getsec(p
->mem_ctx
, Printer
->dev
.handlename
, &old_secdesc_ctr
);
5694 if (DEBUGLEVEL
>= 10) {
5698 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5699 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5700 PRINTERNAME(snum
), the_acl
->num_aces
));
5702 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5705 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5707 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5708 the_acl
->ace
[i
].info
.mask
));
5711 the_acl
= secdesc_ctr
->sec
->dacl
;
5714 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5715 PRINTERNAME(snum
), the_acl
->num_aces
));
5717 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5720 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5722 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5723 the_acl
->ace
[i
].info
.mask
));
5726 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5730 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5732 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5737 /* Work out which user is performing the operation */
5739 get_current_user(&user
, p
);
5741 /* Check the user has permissions to change the security
5742 descriptor. By experimentation with two NT machines, the user
5743 requires Full Access to the printer to change security
5746 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5747 result
= WERR_ACCESS_DENIED
;
5751 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
5758 /********************************************************************
5759 Do Samba sanity checks on a printer info struct.
5760 this has changed purpose: it now "canonicalises" printer
5761 info from a client rather than just checking it is correct
5762 ********************************************************************/
5764 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5766 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5767 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5769 /* we force some elements to "correct" values */
5770 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", get_called_name());
5771 fstrcpy(info
->sharename
, lp_servicename(snum
));
5772 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5773 get_called_name(), info
->sharename
);
5774 info
->attributes
= PRINTER_ATTRIBUTE_SHARED
| PRINTER_ATTRIBUTE_NETWORK
;
5779 /****************************************************************************
5780 ****************************************************************************/
5782 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
5784 extern userdom_struct current_user_info
;
5785 char *cmd
= lp_addprinter_cmd();
5791 fstring remote_machine
= "%m";
5793 standard_sub_basic(current_user_info
.smb_name
, remote_machine
,sizeof(remote_machine
));
5795 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5796 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5797 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5798 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
5800 DEBUG(10,("Running [%s]\n", command
));
5801 ret
= smbrun(command
, &fd
);
5802 DEBUGADD(10,("returned [%d]\n", ret
));
5811 /* Get lines and convert them back to dos-codepage */
5812 qlines
= fd_lines_load(fd
, &numlines
);
5813 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5817 /* Set the portname to what the script says the portname should be. */
5818 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5819 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5821 /* Send SIGHUP to process group... is there a better way? */
5824 /* reload our services immediately */
5825 reload_services( False
);
5828 file_lines_free(qlines
);
5832 /********************************************************************
5833 * Called by spoolss_api_setprinter
5834 * when updating a printer description.
5835 ********************************************************************/
5837 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
5838 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5839 DEVICEMODE
*devmode
)
5842 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
5843 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5846 DEBUG(8,("update_printer\n"));
5851 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5852 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5853 result
= WERR_UNKNOWN_LEVEL
;
5858 result
= WERR_BADFID
;
5862 if (!get_printer_snum(p
, handle
, &snum
)) {
5863 result
= WERR_BADFID
;
5867 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))) ||
5868 (!W_ERROR_IS_OK(get_a_printer(&old_printer
, 2, lp_servicename(snum
))))) {
5869 result
= WERR_BADFID
;
5873 DEBUGADD(8,("Converting info_2 struct\n"));
5876 * convert_printer_info converts the incoming
5877 * info from the client and overwrites the info
5878 * just read from the tdb in the pointer 'printer'.
5881 if (!convert_printer_info(info
, printer
, level
)) {
5882 result
= WERR_NOMEM
;
5887 /* we have a valid devmode
5888 convert it and link it*/
5890 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5891 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5892 &printer
->info_2
->devmode
)) {
5893 result
= WERR_NOMEM
;
5898 * make sure we actually reload the services after
5899 * this as smb.conf could have a new section in it
5900 * .... shouldn't .... but could
5902 reload_services(False
);
5905 /* Do sanity check on the requested changes for Samba */
5907 if (!check_printer_ok(printer
->info_2
, snum
)) {
5908 result
= WERR_INVALID_PARAM
;
5912 /* Check calling user has permission to update printer description */
5914 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5915 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5916 result
= WERR_ACCESS_DENIED
;
5920 /* Call addprinter hook */
5921 /* Check changes to see if this is really needed */
5923 if ( *lp_addprinter_cmd()
5924 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
5925 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
5926 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
5927 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
5929 if ( !add_printer_hook(printer
) ) {
5930 result
= WERR_ACCESS_DENIED
;
5936 * When a *new* driver is bound to a printer, the drivername is used to
5937 * lookup previously saved driver initialization info, which is then
5938 * bound to the printer, simulating what happens in the Windows arch.
5940 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
5942 if (!set_driver_init(printer
, 2))
5944 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5945 printer
->info_2
->drivername
));
5948 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5949 printer
->info_2
->drivername
));
5951 notify_printer_driver(snum
, printer
->info_2
->drivername
);
5954 /* Update printer info */
5955 result
= mod_a_printer(*printer
, 2);
5957 /* flag which changes actually occured. This is a small subset of
5958 all the possible changes */
5960 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
))
5961 notify_printer_comment(snum
, printer
->info_2
->comment
);
5963 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
))
5964 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
5966 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
))
5967 notify_printer_port(snum
, printer
->info_2
->portname
);
5969 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
))
5970 notify_printer_location(snum
, printer
->info_2
->location
);
5973 free_a_printer(&printer
, 2);
5974 free_a_printer(&old_printer
, 2);
5980 /****************************************************************************
5981 ****************************************************************************/
5982 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
5983 const SPOOL_PRINTER_INFO_LEVEL
*info
)
5986 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
5988 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5991 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
5998 if (!get_printer_snum(p
, handle
, &snum
))
6001 nt_printer_publish(snum
, info7
->action
);
6005 return WERR_UNKNOWN_LEVEL
;
6008 /****************************************************************************
6009 ****************************************************************************/
6011 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
6013 POLICY_HND
*handle
= &q_u
->handle
;
6014 uint32 level
= q_u
->level
;
6015 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6016 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
6017 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
6018 uint32 command
= q_u
->command
;
6020 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6023 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6027 /* check the level */
6030 return control_printer(handle
, command
, p
);
6032 return update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6034 return update_printer_sec(handle
, level
, info
, p
,
6037 return publish_or_unpublish_printer(p
, handle
, info
);
6039 return WERR_UNKNOWN_LEVEL
;
6043 /****************************************************************************
6044 ****************************************************************************/
6046 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6048 POLICY_HND
*handle
= &q_u
->handle
;
6049 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6052 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6056 if (Printer
->notify
.client_connected
==True
) {
6059 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
6061 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
6062 !get_printer_snum(p
, handle
, &snum
) )
6065 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6068 Printer
->notify
.flags
=0;
6069 Printer
->notify
.options
=0;
6070 Printer
->notify
.localmachine
[0]='\0';
6071 Printer
->notify
.printerlocal
=0;
6072 if (Printer
->notify
.option
)
6073 free_spool_notify_option(&Printer
->notify
.option
);
6074 Printer
->notify
.client_connected
=False
;
6079 /****************************************************************************
6080 ****************************************************************************/
6082 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6084 /* that's an [in out] buffer (despite appearences to the contrary) */
6085 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6088 return WERR_INVALID_PARAM
; /* this is what a NT server
6089 returns for AddJob. AddJob
6090 must fail on non-local
6094 /****************************************************************************
6095 ****************************************************************************/
6097 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
6098 int position
, int snum
)
6104 t
=gmtime(&queue
->time
);
6105 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
6107 job_info
->jobid
=queue
->job
;
6108 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6109 init_unistr(&job_info
->machinename
, temp_name
);
6110 init_unistr(&job_info
->username
, queue
->fs_user
);
6111 init_unistr(&job_info
->document
, queue
->fs_file
);
6112 init_unistr(&job_info
->datatype
, "RAW");
6113 init_unistr(&job_info
->text_status
, "");
6114 job_info
->status
=nt_printj_status(queue
->status
);
6115 job_info
->priority
=queue
->priority
;
6116 job_info
->position
=position
;
6117 job_info
->totalpages
=queue
->page_count
;
6118 job_info
->pagesprinted
=0;
6120 make_systemtime(&job_info
->submitted
, t
);
6123 /****************************************************************************
6124 ****************************************************************************/
6126 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
6127 int position
, int snum
,
6128 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6129 DEVICEMODE
*devmode
)
6135 t
=gmtime(&queue
->time
);
6136 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
6138 job_info
->jobid
=queue
->job
;
6140 slprintf(chaine
, sizeof(chaine
)-1, "\\\\%s\\%s", get_called_name(), ntprinter
->info_2
->printername
);
6142 init_unistr(&job_info
->printername
, chaine
);
6144 init_unistr(&job_info
->machinename
, temp_name
);
6145 init_unistr(&job_info
->username
, queue
->fs_user
);
6146 init_unistr(&job_info
->document
, queue
->fs_file
);
6147 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6148 init_unistr(&job_info
->datatype
, "RAW");
6149 init_unistr(&job_info
->printprocessor
, "winprint");
6150 init_unistr(&job_info
->parameters
, "");
6151 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6152 init_unistr(&job_info
->text_status
, "");
6154 /* and here the security descriptor */
6156 job_info
->status
=nt_printj_status(queue
->status
);
6157 job_info
->priority
=queue
->priority
;
6158 job_info
->position
=position
;
6159 job_info
->starttime
=0;
6160 job_info
->untiltime
=0;
6161 job_info
->totalpages
=queue
->page_count
;
6162 job_info
->size
=queue
->size
;
6163 make_systemtime(&(job_info
->submitted
), t
);
6164 job_info
->timeelapsed
=0;
6165 job_info
->pagesprinted
=0;
6167 job_info
->devmode
= devmode
;
6172 /****************************************************************************
6173 Enumjobs at level 1.
6174 ****************************************************************************/
6176 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
6177 NEW_BUFFER
*buffer
, uint32 offered
,
6178 uint32
*needed
, uint32
*returned
)
6183 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
6190 for (i
=0; i
<*returned
; i
++)
6191 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
6195 /* check the required size. */
6196 for (i
=0; i
<*returned
; i
++)
6197 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6199 if (!alloc_buffer_size(buffer
, *needed
)) {
6201 return WERR_INSUFFICIENT_BUFFER
;
6204 /* fill the buffer with the structures */
6205 for (i
=0; i
<*returned
; i
++)
6206 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6211 if (*needed
> offered
) {
6213 return WERR_INSUFFICIENT_BUFFER
;
6219 /****************************************************************************
6220 Enumjobs at level 2.
6221 ****************************************************************************/
6223 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
6224 NEW_BUFFER
*buffer
, uint32 offered
,
6225 uint32
*needed
, uint32
*returned
)
6227 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6228 JOB_INFO_2
*info
= NULL
;
6231 DEVICEMODE
*devmode
= NULL
;
6233 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
6236 result
= WERR_NOMEM
;
6240 result
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
6241 if (!W_ERROR_IS_OK(result
)) {
6246 /* this should not be a failure condition if the devmode is NULL */
6248 devmode
= construct_dev_mode(snum
);
6250 for (i
=0; i
<*returned
; i
++)
6251 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
,
6254 free_a_printer(&ntprinter
, 2);
6257 /* check the required size. */
6258 for (i
=0; i
<*returned
; i
++)
6259 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6261 if (*needed
> offered
) {
6263 result
= WERR_INSUFFICIENT_BUFFER
;
6267 if (!alloc_buffer_size(buffer
, *needed
)) {
6269 result
= WERR_INSUFFICIENT_BUFFER
;
6273 /* fill the buffer with the structures */
6274 for (i
=0; i
<*returned
; i
++)
6275 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6280 free_a_printer(&ntprinter
, 2);
6281 free_devmode(devmode
);
6289 /****************************************************************************
6291 ****************************************************************************/
6293 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6295 POLICY_HND
*handle
= &q_u
->handle
;
6296 uint32 level
= q_u
->level
;
6297 NEW_BUFFER
*buffer
= NULL
;
6298 uint32 offered
= q_u
->offered
;
6299 uint32
*needed
= &r_u
->needed
;
6300 uint32
*returned
= &r_u
->returned
;
6303 print_status_struct prt_status
;
6304 print_queue_struct
*queue
=NULL
;
6306 /* that's an [in out] buffer */
6307 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6308 buffer
= r_u
->buffer
;
6310 DEBUG(4,("_spoolss_enumjobs\n"));
6315 if (!get_printer_snum(p
, handle
, &snum
))
6318 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6319 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6321 if (*returned
== 0) {
6328 return enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
6330 return enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
6334 return WERR_UNKNOWN_LEVEL
;
6338 /****************************************************************************
6339 ****************************************************************************/
6341 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6346 /****************************************************************************
6347 ****************************************************************************/
6349 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6351 POLICY_HND
*handle
= &q_u
->handle
;
6352 uint32 jobid
= q_u
->jobid
;
6353 uint32 command
= q_u
->command
;
6355 struct current_user user
;
6357 WERROR errcode
= WERR_BADFUNC
;
6359 if (!get_printer_snum(p
, handle
, &snum
)) {
6363 if (!print_job_exists(snum
, jobid
)) {
6364 return WERR_INVALID_PRINTER_NAME
;
6367 get_current_user(&user
, p
);
6370 case JOB_CONTROL_CANCEL
:
6371 case JOB_CONTROL_DELETE
:
6372 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
6376 case JOB_CONTROL_PAUSE
:
6377 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
6381 case JOB_CONTROL_RESTART
:
6382 case JOB_CONTROL_RESUME
:
6383 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
6388 return WERR_UNKNOWN_LEVEL
;
6394 /****************************************************************************
6395 Enumerates all printer drivers at level 1.
6396 ****************************************************************************/
6398 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6403 fstring
*list
= NULL
;
6405 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6406 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
6410 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6412 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6413 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6419 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
6420 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6421 SAFE_FREE(driver_info_1
);
6425 else driver_info_1
= tdi1
;
6428 for (i
=0; i
<ndrivers
; i
++) {
6430 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6431 ZERO_STRUCT(driver
);
6432 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6433 architecture
, version
);
6434 if (!W_ERROR_IS_OK(status
)) {
6438 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6439 free_a_printer_driver(driver
, 3);
6442 *returned
+=ndrivers
;
6446 /* check the required size. */
6447 for (i
=0; i
<*returned
; i
++) {
6448 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6449 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6452 if (!alloc_buffer_size(buffer
, *needed
)) {
6453 SAFE_FREE(driver_info_1
);
6454 return WERR_INSUFFICIENT_BUFFER
;
6457 /* fill the buffer with the driver structures */
6458 for (i
=0; i
<*returned
; i
++) {
6459 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6460 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6463 SAFE_FREE(driver_info_1
);
6465 if (*needed
> offered
) {
6467 return WERR_INSUFFICIENT_BUFFER
;
6473 /****************************************************************************
6474 Enumerates all printer drivers at level 2.
6475 ****************************************************************************/
6477 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6482 fstring
*list
= NULL
;
6484 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6485 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
6489 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6491 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6492 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6498 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
6499 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6500 SAFE_FREE(driver_info_2
);
6504 else driver_info_2
= tdi2
;
6507 for (i
=0; i
<ndrivers
; i
++) {
6510 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6511 ZERO_STRUCT(driver
);
6512 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6513 architecture
, version
);
6514 if (!W_ERROR_IS_OK(status
)) {
6518 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6519 free_a_printer_driver(driver
, 3);
6522 *returned
+=ndrivers
;
6526 /* check the required size. */
6527 for (i
=0; i
<*returned
; i
++) {
6528 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6529 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6532 if (!alloc_buffer_size(buffer
, *needed
)) {
6533 SAFE_FREE(driver_info_2
);
6534 return WERR_INSUFFICIENT_BUFFER
;
6537 /* fill the buffer with the form structures */
6538 for (i
=0; i
<*returned
; i
++) {
6539 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6540 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6543 SAFE_FREE(driver_info_2
);
6545 if (*needed
> offered
) {
6547 return WERR_INSUFFICIENT_BUFFER
;
6553 /****************************************************************************
6554 Enumerates all printer drivers at level 3.
6555 ****************************************************************************/
6557 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6562 fstring
*list
= NULL
;
6564 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6565 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
6569 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6571 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6572 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6578 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
6579 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6580 SAFE_FREE(driver_info_3
);
6584 else driver_info_3
= tdi3
;
6587 for (i
=0; i
<ndrivers
; i
++) {
6590 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6591 ZERO_STRUCT(driver
);
6592 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6593 architecture
, version
);
6594 if (!W_ERROR_IS_OK(status
)) {
6598 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6599 free_a_printer_driver(driver
, 3);
6602 *returned
+=ndrivers
;
6606 /* check the required size. */
6607 for (i
=0; i
<*returned
; i
++) {
6608 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6609 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6612 if (!alloc_buffer_size(buffer
, *needed
)) {
6613 SAFE_FREE(driver_info_3
);
6614 return WERR_INSUFFICIENT_BUFFER
;
6617 /* fill the buffer with the driver structures */
6618 for (i
=0; i
<*returned
; i
++) {
6619 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6620 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6623 for (i
=0; i
<*returned
; i
++)
6624 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6626 SAFE_FREE(driver_info_3
);
6628 if (*needed
> offered
) {
6630 return WERR_INSUFFICIENT_BUFFER
;
6636 /****************************************************************************
6637 Enumerates all printer drivers.
6638 ****************************************************************************/
6640 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6642 UNISTR2
*environment
= &q_u
->environment
;
6643 uint32 level
= q_u
->level
;
6644 NEW_BUFFER
*buffer
= NULL
;
6645 uint32 offered
= q_u
->offered
;
6646 uint32
*needed
= &r_u
->needed
;
6647 uint32
*returned
= &r_u
->returned
;
6649 fstring
*list
= NULL
;
6651 fstring architecture
;
6653 /* that's an [in out] buffer */
6654 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6655 buffer
= r_u
->buffer
;
6657 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6658 fstrcpy(servername
, get_called_name());
6662 unistr2_to_ascii(architecture
, environment
, sizeof(architecture
)-1);
6666 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
6668 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
6670 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
6674 return WERR_UNKNOWN_LEVEL
;
6678 /****************************************************************************
6679 ****************************************************************************/
6681 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
6683 form
->flag
=list
->flag
;
6684 init_unistr(&form
->name
, list
->name
);
6685 form
->width
=list
->width
;
6686 form
->length
=list
->length
;
6687 form
->left
=list
->left
;
6688 form
->top
=list
->top
;
6689 form
->right
=list
->right
;
6690 form
->bottom
=list
->bottom
;
6693 /****************************************************************************
6694 ****************************************************************************/
6696 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
6698 uint32 level
= q_u
->level
;
6699 NEW_BUFFER
*buffer
= NULL
;
6700 uint32 offered
= q_u
->offered
;
6701 uint32
*needed
= &r_u
->needed
;
6702 uint32
*numofforms
= &r_u
->numofforms
;
6703 uint32 numbuiltinforms
;
6705 nt_forms_struct
*list
=NULL
;
6706 nt_forms_struct
*builtinlist
=NULL
;
6711 /* that's an [in out] buffer */
6712 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6713 buffer
= r_u
->buffer
;
6715 DEBUG(4,("_spoolss_enumforms\n"));
6716 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6717 DEBUGADD(5,("Info level [%d]\n", level
));
6719 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
6720 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
6721 *numofforms
= get_ntforms(&list
);
6722 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
6723 *numofforms
+= numbuiltinforms
;
6725 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
6729 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
6734 /* construct the list of form structures */
6735 for (i
=0; i
<numbuiltinforms
; i
++) {
6736 DEBUGADD(6,("Filling form number [%d]\n",i
));
6737 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
6740 SAFE_FREE(builtinlist
);
6742 for (; i
<*numofforms
; i
++) {
6743 DEBUGADD(6,("Filling form number [%d]\n",i
));
6744 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
6749 /* check the required size. */
6750 for (i
=0; i
<numbuiltinforms
; i
++) {
6751 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6752 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6754 for (; i
<*numofforms
; i
++) {
6755 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6756 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6759 *needed
=buffer_size
;
6761 if (!alloc_buffer_size(buffer
, buffer_size
)){
6763 return WERR_INSUFFICIENT_BUFFER
;
6766 /* fill the buffer with the form structures */
6767 for (i
=0; i
<numbuiltinforms
; i
++) {
6768 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6769 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6771 for (; i
<*numofforms
; i
++) {
6772 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6773 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6778 if (*needed
> offered
) {
6780 return WERR_INSUFFICIENT_BUFFER
;
6787 SAFE_FREE(builtinlist
);
6788 return WERR_UNKNOWN_LEVEL
;
6793 /****************************************************************************
6794 ****************************************************************************/
6796 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
6798 uint32 level
= q_u
->level
;
6799 UNISTR2
*uni_formname
= &q_u
->formname
;
6800 NEW_BUFFER
*buffer
= NULL
;
6801 uint32 offered
= q_u
->offered
;
6802 uint32
*needed
= &r_u
->needed
;
6804 nt_forms_struct
*list
=NULL
;
6805 nt_forms_struct builtin_form
;
6810 int numofforms
=0, i
=0;
6812 /* that's an [in out] buffer */
6813 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6814 buffer
= r_u
->buffer
;
6816 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
6818 DEBUG(4,("_spoolss_getform\n"));
6819 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6820 DEBUGADD(5,("Info level [%d]\n", level
));
6822 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
6823 if (!foundBuiltin
) {
6824 numofforms
= get_ntforms(&list
);
6825 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
6827 if (numofforms
== 0)
6834 fill_form_1(&form_1
, &builtin_form
);
6837 /* Check if the requested name is in the list of form structures */
6838 for (i
=0; i
<numofforms
; i
++) {
6840 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
6842 if (strequal(form_name
, list
[i
].name
)) {
6843 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
6844 fill_form_1(&form_1
, &list
[i
]);
6850 if (i
== numofforms
) {
6854 /* check the required size. */
6856 *needed
=spoolss_size_form_1(&form_1
);
6858 if (!alloc_buffer_size(buffer
, buffer_size
)){
6859 return WERR_INSUFFICIENT_BUFFER
;
6862 if (*needed
> offered
) {
6863 return WERR_INSUFFICIENT_BUFFER
;
6866 /* fill the buffer with the form structures */
6867 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
6868 smb_io_form_1("", buffer
, &form_1
, 0);
6874 return WERR_UNKNOWN_LEVEL
;
6878 /****************************************************************************
6879 ****************************************************************************/
6881 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
6883 init_unistr(&port
->port_name
, name
);
6886 /****************************************************************************
6887 ****************************************************************************/
6889 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
6891 init_unistr(&port
->port_name
, name
);
6892 init_unistr(&port
->monitor_name
, "Local Monitor");
6893 init_unistr(&port
->description
, "Local Port");
6894 #define PORT_TYPE_WRITE 1
6895 port
->port_type
=PORT_TYPE_WRITE
;
6899 /****************************************************************************
6901 ****************************************************************************/
6903 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6905 PORT_INFO_1
*ports
=NULL
;
6908 if (*lp_enumports_cmd()) {
6909 char *cmd
= lp_enumports_cmd();
6916 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
6918 DEBUG(10,("Running [%s]\n", command
));
6919 ret
= smbrun(command
, &fd
);
6920 DEBUG(10,("Returned [%d]\n", ret
));
6924 /* Is this the best error to return here? */
6925 return WERR_ACCESS_DENIED
;
6929 qlines
= fd_lines_load(fd
, &numlines
);
6930 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6934 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
6935 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6936 dos_errstr(WERR_NOMEM
)));
6937 file_lines_free(qlines
);
6941 for (i
=0; i
<numlines
; i
++) {
6942 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6943 fill_port_1(&ports
[i
], qlines
[i
]);
6946 file_lines_free(qlines
);
6949 *returned
= numlines
;
6952 *returned
= 1; /* Sole Samba port returned. */
6954 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
6957 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
6959 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
6962 /* check the required size. */
6963 for (i
=0; i
<*returned
; i
++) {
6964 DEBUGADD(6,("adding port [%d]'s size\n", i
));
6965 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
6968 if (!alloc_buffer_size(buffer
, *needed
)) {
6970 return WERR_INSUFFICIENT_BUFFER
;
6973 /* fill the buffer with the ports structures */
6974 for (i
=0; i
<*returned
; i
++) {
6975 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
6976 smb_io_port_1("", buffer
, &ports
[i
], 0);
6981 if (*needed
> offered
) {
6983 return WERR_INSUFFICIENT_BUFFER
;
6989 /****************************************************************************
6991 ****************************************************************************/
6993 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6995 PORT_INFO_2
*ports
=NULL
;
6998 if (*lp_enumports_cmd()) {
6999 char *cmd
= lp_enumports_cmd();
7008 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
7009 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
7011 path
= lp_lockdir();
7013 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
7014 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
7017 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
7018 ret
= smbrun(command
, &fd
);
7019 DEBUGADD(10,("returned [%d]\n", ret
));
7023 /* Is this the best error to return here? */
7024 return WERR_ACCESS_DENIED
;
7028 qlines
= fd_lines_load(fd
, &numlines
);
7029 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7033 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
7034 file_lines_free(qlines
);
7038 for (i
=0; i
<numlines
; i
++) {
7039 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7040 fill_port_2(&(ports
[i
]), qlines
[i
]);
7043 file_lines_free(qlines
);
7046 *returned
= numlines
;
7052 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
7055 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7057 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7060 /* check the required size. */
7061 for (i
=0; i
<*returned
; i
++) {
7062 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7063 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7066 if (!alloc_buffer_size(buffer
, *needed
)) {
7068 return WERR_INSUFFICIENT_BUFFER
;
7071 /* fill the buffer with the ports structures */
7072 for (i
=0; i
<*returned
; i
++) {
7073 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7074 smb_io_port_2("", buffer
, &ports
[i
], 0);
7079 if (*needed
> offered
) {
7081 return WERR_INSUFFICIENT_BUFFER
;
7087 /****************************************************************************
7089 ****************************************************************************/
7091 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7093 uint32 level
= q_u
->level
;
7094 NEW_BUFFER
*buffer
= NULL
;
7095 uint32 offered
= q_u
->offered
;
7096 uint32
*needed
= &r_u
->needed
;
7097 uint32
*returned
= &r_u
->returned
;
7099 /* that's an [in out] buffer */
7100 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7101 buffer
= r_u
->buffer
;
7103 DEBUG(4,("_spoolss_enumports\n"));
7110 return enumports_level_1(buffer
, offered
, needed
, returned
);
7112 return enumports_level_2(buffer
, offered
, needed
, returned
);
7114 return WERR_UNKNOWN_LEVEL
;
7118 /****************************************************************************
7119 ****************************************************************************/
7121 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7122 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7123 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7124 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7127 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7130 WERROR err
= WERR_OK
;
7132 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
7133 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7137 ZERO_STRUCTP(printer
);
7139 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7140 if (!convert_printer_info(info
, printer
, 2)) {
7141 free_a_printer(&printer
, 2);
7145 /* check to see if the printer already exists */
7147 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7148 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7149 printer
->info_2
->sharename
));
7150 free_a_printer(&printer
, 2);
7151 return WERR_PRINTER_ALREADY_EXISTS
;
7154 if (*lp_addprinter_cmd() ) {
7155 if ( !add_printer_hook(printer
) ) {
7156 free_a_printer(&printer
,2);
7157 return WERR_ACCESS_DENIED
;
7161 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", get_called_name(),
7162 printer
->info_2
->sharename
);
7165 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7166 free_a_printer(&printer
,2);
7167 return WERR_ACCESS_DENIED
;
7170 /* you must be a printer admin to add a new printer */
7171 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7172 free_a_printer(&printer
,2);
7173 return WERR_ACCESS_DENIED
;
7177 * Do sanity check on the requested changes for Samba.
7180 if (!check_printer_ok(printer
->info_2
, snum
)) {
7181 free_a_printer(&printer
,2);
7182 return WERR_INVALID_PARAM
;
7186 * When a printer is created, the drivername bound to the printer is used
7187 * to lookup previously saved driver initialization info, which is then
7188 * bound to the new printer, simulating what happens in the Windows arch.
7193 set_driver_init(printer
, 2);
7197 /* A valid devmode was included, convert and link it
7199 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7201 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7202 &printer
->info_2
->devmode
))
7206 /* write the ASCII on disk */
7207 err
= mod_a_printer(*printer
, 2);
7208 if (!W_ERROR_IS_OK(err
)) {
7209 free_a_printer(&printer
,2);
7213 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7214 /* Handle open failed - remove addition. */
7215 del_a_printer(printer
->info_2
->sharename
);
7216 free_a_printer(&printer
,2);
7217 return WERR_ACCESS_DENIED
;
7220 update_c_setprinter(False
);
7221 free_a_printer(&printer
,2);
7226 /****************************************************************************
7227 ****************************************************************************/
7229 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7231 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
7232 uint32 level
= q_u
->level
;
7233 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7234 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7235 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7236 uint32 user_switch
= q_u
->user_switch
;
7237 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7238 POLICY_HND
*handle
= &r_u
->handle
;
7242 /* we don't handle yet */
7243 /* but I know what to do ... */
7244 return WERR_UNKNOWN_LEVEL
;
7246 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7248 user_switch
, user
, handle
);
7250 return WERR_UNKNOWN_LEVEL
;
7254 /****************************************************************************
7255 ****************************************************************************/
7257 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7259 uint32 level
= q_u
->level
;
7260 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7261 WERROR err
= WERR_OK
;
7262 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7263 struct current_user user
;
7264 fstring driver_name
;
7267 ZERO_STRUCT(driver
);
7269 get_current_user(&user
, p
);
7271 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7276 DEBUG(5,("Cleaning driver's information\n"));
7277 err
= clean_up_driver_struct(driver
, level
, &user
);
7278 if (!W_ERROR_IS_OK(err
))
7281 DEBUG(5,("Moving driver to final destination\n"));
7282 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
7283 if (W_ERROR_IS_OK(err
))
7284 err
= WERR_ACCESS_DENIED
;
7288 if (add_a_printer_driver(driver
, level
)!=0) {
7289 err
= WERR_ACCESS_DENIED
;
7293 /* BEGIN_ADMIN_LOG */
7296 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7297 driver
.info_3
->name
,drv_ver_to_os
[driver
.info_3
->cversion
],uidtoname(user
.uid
));
7298 fstrcpy(driver_name
, driver
.info_3
->name
);
7301 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7302 driver
.info_6
->name
,drv_ver_to_os
[driver
.info_6
->version
],uidtoname(user
.uid
));
7303 fstrcpy(driver_name
, driver
.info_6
->name
);
7309 * I think this is where he DrvUpgradePrinter() hook would be
7310 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7311 * server. Right now, we just need to send ourselves a message
7312 * to update each printer bound to this driver. --jerry
7315 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7316 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7321 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7322 * decide if the driver init data should be deleted. The rules are:
7323 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7324 * 2) delete init data only if there is no 2k/Xp driver
7325 * 3) always delete init data
7326 * The generalized rule is always use init data from the highest order driver.
7327 * It is necessary to follow the driver install by an initialization step to
7328 * finish off this process.
7331 version
= driver
.info_3
->cversion
;
7332 else if (level
== 6)
7333 version
= driver
.info_6
->version
;
7338 * 9x printer driver - never delete init data
7341 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7346 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7347 * there is no 2k/Xp driver init data for this driver name.
7351 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7353 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7355 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7357 if (!del_driver_init(driver_name
))
7358 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7361 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7363 free_a_printer_driver(driver1
,3);
7364 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7371 * 2k or Xp printer driver - always delete init data
7374 if (!del_driver_init(driver_name
))
7375 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7379 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7385 free_a_printer_driver(driver
, level
);
7389 /********************************************************************
7390 * spoolss_addprinterdriverex
7391 ********************************************************************/
7393 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7395 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7396 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7399 * we only support the semantics of AddPrinterDriver()
7400 * i.e. only copy files that are newer than existing ones
7403 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7404 return WERR_ACCESS_DENIED
;
7406 ZERO_STRUCT(q_u_local
);
7407 ZERO_STRUCT(r_u_local
);
7409 /* just pass the information off to _spoolss_addprinterdriver() */
7410 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7411 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7412 q_u_local
.level
= q_u
->level
;
7413 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7415 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7418 /****************************************************************************
7419 ****************************************************************************/
7421 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7423 init_unistr(&info
->name
, name
);
7426 /****************************************************************************
7427 ****************************************************************************/
7429 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7433 pstring short_archi
;
7434 DRIVER_DIRECTORY_1
*info
=NULL
;
7436 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7438 if (get_short_archi(short_archi
, long_archi
)==False
)
7439 return WERR_INVALID_ENVIRONMENT
;
7441 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
7444 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi
);
7446 DEBUG(4,("printer driver directory: [%s]\n", path
));
7448 fill_driverdir_1(info
, path
);
7450 *needed
+= spoolss_size_driverdir_info_1(info
);
7452 if (!alloc_buffer_size(buffer
, *needed
)) {
7454 return WERR_INSUFFICIENT_BUFFER
;
7457 smb_io_driverdir_1("", buffer
, info
, 0);
7461 if (*needed
> offered
)
7462 return WERR_INSUFFICIENT_BUFFER
;
7467 /****************************************************************************
7468 ****************************************************************************/
7470 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7472 UNISTR2
*name
= &q_u
->name
;
7473 UNISTR2
*uni_environment
= &q_u
->environment
;
7474 uint32 level
= q_u
->level
;
7475 NEW_BUFFER
*buffer
= NULL
;
7476 uint32 offered
= q_u
->offered
;
7477 uint32
*needed
= &r_u
->needed
;
7479 /* that's an [in out] buffer */
7480 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7481 buffer
= r_u
->buffer
;
7483 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7489 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7491 return WERR_UNKNOWN_LEVEL
;
7495 /****************************************************************************
7496 ****************************************************************************/
7498 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7500 POLICY_HND
*handle
= &q_u
->handle
;
7501 uint32 idx
= q_u
->index
;
7502 uint32 in_value_len
= q_u
->valuesize
;
7503 uint32 in_data_len
= q_u
->datasize
;
7504 uint32
*out_max_value_len
= &r_u
->valuesize
;
7505 uint16
**out_value
= &r_u
->value
;
7506 uint32
*out_value_len
= &r_u
->realvaluesize
;
7507 uint32
*out_type
= &r_u
->type
;
7508 uint32
*out_max_data_len
= &r_u
->datasize
;
7509 uint8
**data_out
= &r_u
->data
;
7510 uint32
*out_data_len
= &r_u
->realdatasize
;
7512 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7515 uint32 biggest_valuesize
;
7516 uint32 biggest_datasize
;
7518 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7521 REGISTRY_VALUE
*val
;
7522 NT_PRINTER_DATA
*p_data
;
7523 int i
, key_index
, num_values
;
7526 ZERO_STRUCT( printer
);
7530 *out_max_data_len
= 0;
7534 DEBUG(5,("spoolss_enumprinterdata\n"));
7537 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7541 if (!get_printer_snum(p
,handle
, &snum
))
7544 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7545 if (!W_ERROR_IS_OK(result
))
7548 p_data
= &printer
->info_2
->data
;
7549 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7554 * The NT machine wants to know the biggest size of value and data
7556 * cf: MSDN EnumPrinterData remark section
7559 if ( !in_value_len
&& !in_data_len
)
7561 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7564 biggest_valuesize
= 0;
7565 biggest_datasize
= 0;
7567 num_values
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
7569 for ( i
=0; i
<num_values
; i
++ )
7571 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
7573 name_length
= strlen(val
->valuename
);
7574 if ( strlen(val
->valuename
) > biggest_valuesize
)
7575 biggest_valuesize
= name_length
;
7577 if ( val
->size
> biggest_datasize
)
7578 biggest_datasize
= val
->size
;
7580 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7584 /* the value is an UNICODE string but real_value_size is the length
7585 in bytes including the trailing 0 */
7587 *out_value_len
= 2 * (1+biggest_valuesize
);
7588 *out_data_len
= biggest_datasize
;
7590 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7596 * the value len is wrong in NT sp3
7597 * that's the number of bytes not the number of unicode chars
7600 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, idx
);
7605 /* out_value should default to "" or else NT4 has
7606 problems unmarshalling the response */
7608 *out_max_value_len
= (in_value_len
/sizeof(uint16
));
7610 if ( (*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7612 result
= WERR_NOMEM
;
7616 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
7618 /* the data is counted in bytes */
7620 *out_max_data_len
= in_data_len
;
7621 *out_data_len
= in_data_len
;
7623 /* only allocate when given a non-zero data_len */
7625 if ( in_data_len
&& ((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
7627 result
= WERR_NOMEM
;
7631 result
= WERR_NO_MORE_ITEMS
;
7637 * - counted in bytes in the request
7638 * - counted in UNICODE chars in the max reply
7639 * - counted in bytes in the real size
7641 * take a pause *before* coding not *during* coding
7645 *out_max_value_len
= ( in_value_len
/ sizeof(uint16
) );
7646 if ( (*out_value
= (uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7648 result
= WERR_NOMEM
;
7652 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), in_value_len
, 0);
7656 *out_type
= regval_type( val
);
7658 /* data - counted in bytes */
7660 *out_max_data_len
= in_data_len
;
7661 if ( (*data_out
= (uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
7663 result
= WERR_NOMEM
;
7666 data_len
= (size_t)regval_size(val
);
7667 memcpy( *data_out
, regval_data_p(val
), data_len
);
7668 *out_data_len
= data_len
;
7672 free_a_printer(&printer
, 2);
7676 /****************************************************************************
7677 ****************************************************************************/
7679 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
7681 POLICY_HND
*handle
= &q_u
->handle
;
7682 UNISTR2
*value
= &q_u
->value
;
7683 uint32 type
= q_u
->type
;
7684 uint8
*data
= q_u
->data
;
7685 uint32 real_len
= q_u
->real_len
;
7687 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7689 WERROR status
= WERR_OK
;
7690 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7693 DEBUG(5,("spoolss_setprinterdata\n"));
7696 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7700 if (!get_printer_snum(p
,handle
, &snum
))
7704 * Access check : NT returns "access denied" if you make a
7705 * SetPrinterData call without the necessary privildge.
7706 * we were originally returning OK if nothing changed
7707 * which made Win2k issue **a lot** of SetPrinterData
7708 * when connecting to a printer --jerry
7711 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
7713 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7714 status
= WERR_ACCESS_DENIED
;
7718 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7719 if (!W_ERROR_IS_OK(status
))
7722 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
7725 * When client side code sets a magic printer data key, detect it and save
7726 * the current printer data and the magic key's data (its the DEVMODE) for
7727 * future printer/driver initializations.
7729 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
7731 /* Set devmode and printer initialization info */
7732 status
= save_driver_init( printer
, 2, data
, real_len
);
7734 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
7738 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
7739 type
, data
, real_len
);
7740 if ( W_ERROR_IS_OK(status
) )
7741 status
= mod_a_printer(*printer
, 2);
7745 free_a_printer(&printer
, 2);
7750 /****************************************************************************
7751 ****************************************************************************/
7753 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
7755 POLICY_HND
*handle
= &q_u
->handle
;
7756 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7759 DEBUG(5,("_spoolss_resetprinter\n"));
7762 * All we do is to check to see if the handle and queue is valid.
7763 * This call really doesn't mean anything to us because we only
7764 * support RAW printing. --jerry
7768 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7772 if (!get_printer_snum(p
,handle
, &snum
))
7776 /* blindly return success */
7781 /****************************************************************************
7782 ****************************************************************************/
7784 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
7786 POLICY_HND
*handle
= &q_u
->handle
;
7787 UNISTR2
*value
= &q_u
->valuename
;
7789 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7791 WERROR status
= WERR_OK
;
7792 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7795 DEBUG(5,("spoolss_deleteprinterdata\n"));
7798 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7802 if (!get_printer_snum(p
, handle
, &snum
))
7805 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7806 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7807 return WERR_ACCESS_DENIED
;
7810 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7811 if (!W_ERROR_IS_OK(status
))
7814 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
7816 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
7818 free_a_printer(&printer
, 2);
7823 /****************************************************************************
7824 ****************************************************************************/
7826 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
7828 POLICY_HND
*handle
= &q_u
->handle
;
7829 FORM
*form
= &q_u
->form
;
7830 nt_forms_struct tmpForm
;
7832 WERROR status
= WERR_OK
;
7833 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7836 nt_forms_struct
*list
=NULL
;
7837 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7839 DEBUG(5,("spoolss_addform\n"));
7842 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7847 /* forms can be added on printer of on the print server handle */
7849 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7851 if (!get_printer_snum(p
,handle
, &snum
))
7854 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7855 if (!W_ERROR_IS_OK(status
))
7859 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7860 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7861 status
= WERR_ACCESS_DENIED
;
7865 /* can't add if builtin */
7867 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7868 status
= WERR_ALREADY_EXISTS
;
7872 count
= get_ntforms(&list
);
7874 if(!add_a_form(&list
, form
, &count
)) {
7875 status
= WERR_NOMEM
;
7879 write_ntforms(&list
, count
);
7882 * ChangeID must always be set if this is a printer
7885 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7886 status
= mod_a_printer(*printer
, 2);
7890 free_a_printer(&printer
, 2);
7896 /****************************************************************************
7897 ****************************************************************************/
7899 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
7901 POLICY_HND
*handle
= &q_u
->handle
;
7902 UNISTR2
*form_name
= &q_u
->name
;
7903 nt_forms_struct tmpForm
;
7905 nt_forms_struct
*list
=NULL
;
7906 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7908 WERROR status
= WERR_OK
;
7909 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7911 DEBUG(5,("spoolss_deleteform\n"));
7914 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7918 /* forms can be deleted on printer of on the print server handle */
7920 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7922 if (!get_printer_snum(p
,handle
, &snum
))
7925 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7926 if (!W_ERROR_IS_OK(status
))
7930 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7931 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7932 status
= WERR_ACCESS_DENIED
;
7936 /* can't delete if builtin */
7938 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
7939 status
= WERR_INVALID_PARAM
;
7943 count
= get_ntforms(&list
);
7945 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
7949 * ChangeID must always be set if this is a printer
7952 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7953 status
= mod_a_printer(*printer
, 2);
7957 free_a_printer(&printer
, 2);
7963 /****************************************************************************
7964 ****************************************************************************/
7966 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
7968 POLICY_HND
*handle
= &q_u
->handle
;
7969 FORM
*form
= &q_u
->form
;
7970 nt_forms_struct tmpForm
;
7972 WERROR status
= WERR_OK
;
7973 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7976 nt_forms_struct
*list
=NULL
;
7977 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7979 DEBUG(5,("spoolss_setform\n"));
7982 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7986 /* forms can be modified on printer of on the print server handle */
7988 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7990 if (!get_printer_snum(p
,handle
, &snum
))
7993 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7994 if (!W_ERROR_IS_OK(status
))
7998 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7999 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8000 status
= WERR_ACCESS_DENIED
;
8004 /* can't set if builtin */
8005 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8006 status
= WERR_INVALID_PARAM
;
8010 count
= get_ntforms(&list
);
8011 update_a_form(&list
, form
, count
);
8012 write_ntforms(&list
, count
);
8015 * ChangeID must always be set if this is a printer
8018 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8019 status
= mod_a_printer(*printer
, 2);
8024 free_a_printer(&printer
, 2);
8030 /****************************************************************************
8031 enumprintprocessors level 1.
8032 ****************************************************************************/
8034 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8036 PRINTPROCESSOR_1
*info_1
=NULL
;
8038 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
8043 init_unistr(&info_1
->name
, "winprint");
8045 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8047 if (!alloc_buffer_size(buffer
, *needed
))
8048 return WERR_INSUFFICIENT_BUFFER
;
8050 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8054 if (*needed
> offered
) {
8056 return WERR_INSUFFICIENT_BUFFER
;
8062 /****************************************************************************
8063 ****************************************************************************/
8065 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8067 uint32 level
= q_u
->level
;
8068 NEW_BUFFER
*buffer
= NULL
;
8069 uint32 offered
= q_u
->offered
;
8070 uint32
*needed
= &r_u
->needed
;
8071 uint32
*returned
= &r_u
->returned
;
8073 /* that's an [in out] buffer */
8074 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8075 buffer
= r_u
->buffer
;
8077 DEBUG(5,("spoolss_enumprintprocessors\n"));
8080 * Enumerate the print processors ...
8082 * Just reply with "winprint", to keep NT happy
8083 * and I can use my nice printer checker.
8091 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8093 return WERR_UNKNOWN_LEVEL
;
8097 /****************************************************************************
8098 enumprintprocdatatypes level 1.
8099 ****************************************************************************/
8101 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8103 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8105 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
8110 init_unistr(&info_1
->name
, "RAW");
8112 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8114 if (!alloc_buffer_size(buffer
, *needed
))
8115 return WERR_INSUFFICIENT_BUFFER
;
8117 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8121 if (*needed
> offered
) {
8123 return WERR_INSUFFICIENT_BUFFER
;
8129 /****************************************************************************
8130 ****************************************************************************/
8132 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8134 uint32 level
= q_u
->level
;
8135 NEW_BUFFER
*buffer
= NULL
;
8136 uint32 offered
= q_u
->offered
;
8137 uint32
*needed
= &r_u
->needed
;
8138 uint32
*returned
= &r_u
->returned
;
8140 /* that's an [in out] buffer */
8141 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8142 buffer
= r_u
->buffer
;
8144 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8151 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8153 return WERR_UNKNOWN_LEVEL
;
8157 /****************************************************************************
8158 enumprintmonitors level 1.
8159 ****************************************************************************/
8161 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8163 PRINTMONITOR_1
*info_1
=NULL
;
8165 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
8170 init_unistr(&info_1
->name
, "Local Port");
8172 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
8174 if (!alloc_buffer_size(buffer
, *needed
))
8175 return WERR_INSUFFICIENT_BUFFER
;
8177 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
8181 if (*needed
> offered
) {
8183 return WERR_INSUFFICIENT_BUFFER
;
8189 /****************************************************************************
8190 enumprintmonitors level 2.
8191 ****************************************************************************/
8193 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8195 PRINTMONITOR_2
*info_2
=NULL
;
8197 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
8202 init_unistr(&info_2
->name
, "Local Port");
8203 init_unistr(&info_2
->environment
, "Windows NT X86");
8204 init_unistr(&info_2
->dll_name
, "localmon.dll");
8206 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
8208 if (!alloc_buffer_size(buffer
, *needed
))
8209 return WERR_INSUFFICIENT_BUFFER
;
8211 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
8215 if (*needed
> offered
) {
8217 return WERR_INSUFFICIENT_BUFFER
;
8223 /****************************************************************************
8224 ****************************************************************************/
8226 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8228 uint32 level
= q_u
->level
;
8229 NEW_BUFFER
*buffer
= NULL
;
8230 uint32 offered
= q_u
->offered
;
8231 uint32
*needed
= &r_u
->needed
;
8232 uint32
*returned
= &r_u
->returned
;
8234 /* that's an [in out] buffer */
8235 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8236 buffer
= r_u
->buffer
;
8238 DEBUG(5,("spoolss_enumprintmonitors\n"));
8241 * Enumerate the print monitors ...
8243 * Just reply with "Local Port", to keep NT happy
8244 * and I can use my nice printer checker.
8252 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8254 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8256 return WERR_UNKNOWN_LEVEL
;
8260 /****************************************************************************
8261 ****************************************************************************/
8263 static WERROR
getjob_level_1(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
8267 JOB_INFO_1
*info_1
=NULL
;
8269 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
8271 if (info_1
== NULL
) {
8276 for (i
=0; i
<count
&& found
==False
; i
++) {
8277 if (queue
[i
].job
==(int)jobid
)
8284 /* NT treats not found as bad param... yet another bad choice */
8285 return WERR_INVALID_PARAM
;
8288 fill_job_info_1(info_1
, &(queue
[i
-1]), i
, snum
);
8290 *needed
+= spoolss_size_job_info_1(info_1
);
8292 if (!alloc_buffer_size(buffer
, *needed
)) {
8294 return WERR_INSUFFICIENT_BUFFER
;
8297 smb_io_job_info_1("", buffer
, info_1
, 0);
8301 if (*needed
> offered
)
8302 return WERR_INSUFFICIENT_BUFFER
;
8307 /****************************************************************************
8308 ****************************************************************************/
8310 static WERROR
getjob_level_2(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
8315 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8317 DEVICEMODE
*devmode
= NULL
;
8318 NT_DEVICEMODE
*nt_devmode
= NULL
;
8320 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
8322 ZERO_STRUCTP(info_2
);
8324 if (info_2
== NULL
) {
8329 for ( i
=0; i
<count
&& found
==False
; i
++ )
8331 if (queue
[i
].job
== (int)jobid
)
8337 /* NT treats not found as bad param... yet another bad
8339 ret
= WERR_INVALID_PARAM
;
8343 ret
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
8344 if (!W_ERROR_IS_OK(ret
))
8348 * if the print job does not have a DEVMODE associated with it,
8349 * just use the one for the printer. A NULL devicemode is not
8350 * a failure condition
8353 if ( !(nt_devmode
=print_job_devmode( snum
, jobid
)) )
8354 devmode
= construct_dev_mode(snum
);
8356 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) != NULL
) {
8357 ZERO_STRUCTP( devmode
);
8358 convert_nt_devicemode( devmode
, nt_devmode
);
8362 fill_job_info_2(info_2
, &(queue
[i
-1]), i
, snum
, ntprinter
, devmode
);
8364 *needed
+= spoolss_size_job_info_2(info_2
);
8366 if (!alloc_buffer_size(buffer
, *needed
)) {
8367 ret
= WERR_INSUFFICIENT_BUFFER
;
8371 smb_io_job_info_2("", buffer
, info_2
, 0);
8373 if (*needed
> offered
) {
8374 ret
= WERR_INSUFFICIENT_BUFFER
;
8381 /* Cleanup allocated memory */
8383 free_job_info_2(info_2
); /* Also frees devmode */
8385 free_a_printer(&ntprinter
, 2);
8390 /****************************************************************************
8391 ****************************************************************************/
8393 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8395 POLICY_HND
*handle
= &q_u
->handle
;
8396 uint32 jobid
= q_u
->jobid
;
8397 uint32 level
= q_u
->level
;
8398 NEW_BUFFER
*buffer
= NULL
;
8399 uint32 offered
= q_u
->offered
;
8400 uint32
*needed
= &r_u
->needed
;
8401 WERROR wstatus
= WERR_OK
;
8405 print_queue_struct
*queue
= NULL
;
8406 print_status_struct prt_status
;
8408 /* that's an [in out] buffer */
8409 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8410 buffer
= r_u
->buffer
;
8412 DEBUG(5,("spoolss_getjob\n"));
8416 if (!get_printer_snum(p
, handle
, &snum
))
8419 count
= print_queue_status(snum
, &queue
, &prt_status
);
8421 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8422 count
, prt_status
.status
, prt_status
.message
));
8426 wstatus
= getjob_level_1(queue
, count
, snum
, jobid
,
8427 buffer
, offered
, needed
);
8430 wstatus
= getjob_level_2(queue
, count
, snum
, jobid
,
8431 buffer
, offered
, needed
);
8434 wstatus
= WERR_UNKNOWN_LEVEL
;
8442 /********************************************************************
8443 spoolss_getprinterdataex
8445 From MSDN documentation of GetPrinterDataEx: pass request
8446 to GetPrinterData if key is "PrinterDriverData".
8447 ********************************************************************/
8449 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8451 POLICY_HND
*handle
= &q_u
->handle
;
8452 uint32 in_size
= q_u
->size
;
8453 uint32
*type
= &r_u
->type
;
8454 uint32
*out_size
= &r_u
->size
;
8455 uint8
**data
= &r_u
->data
;
8456 uint32
*needed
= &r_u
->needed
;
8457 fstring keyname
, valuename
;
8459 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8461 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8463 WERROR status
= WERR_OK
;
8465 DEBUG(4,("_spoolss_getprinterdataex\n"));
8467 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8468 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
8470 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8471 keyname
, valuename
));
8473 /* in case of problem, return some default values */
8477 *out_size
= in_size
;
8480 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8481 status
= WERR_BADFID
;
8485 /* Is the handle to a printer or to the server? */
8487 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8488 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8489 status
= WERR_INVALID_PARAM
;
8493 if ( !get_printer_snum(p
,handle
, &snum
) )
8496 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8497 if ( !W_ERROR_IS_OK(status
) )
8500 /* check to see if the keyname is valid */
8501 if ( !strlen(keyname
) ) {
8502 status
= WERR_INVALID_PARAM
;
8506 if ( lookup_printerkey( &printer
->info_2
->data
, keyname
) == -1 ) {
8507 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
8508 free_a_printer( &printer
, 2 );
8509 status
= WERR_BADFILE
;
8513 /* When given a new keyname, we should just create it */
8515 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
8517 if (*needed
> *out_size
)
8518 status
= WERR_MORE_DATA
;
8521 if ( !W_ERROR_IS_OK(status
) )
8523 DEBUG(5, ("error: allocating %d\n", *out_size
));
8525 /* reply this param doesn't exist */
8529 if( (*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
8530 status
= WERR_NOMEM
;
8540 free_a_printer( &printer
, 2 );
8545 /********************************************************************
8546 * spoolss_setprinterdataex
8547 ********************************************************************/
8549 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
8551 POLICY_HND
*handle
= &q_u
->handle
;
8552 uint32 type
= q_u
->type
;
8553 uint8
*data
= q_u
->data
;
8554 uint32 real_len
= q_u
->real_len
;
8556 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8558 WERROR status
= WERR_OK
;
8559 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8564 DEBUG(4,("_spoolss_setprinterdataex\n"));
8566 /* From MSDN documentation of SetPrinterDataEx: pass request to
8567 SetPrinterData if key is "PrinterDriverData" */
8570 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8574 if ( !get_printer_snum(p
,handle
, &snum
) )
8578 * Access check : NT returns "access denied" if you make a
8579 * SetPrinterData call without the necessary privildge.
8580 * we were originally returning OK if nothing changed
8581 * which made Win2k issue **a lot** of SetPrinterData
8582 * when connecting to a printer --jerry
8585 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8587 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8588 return WERR_ACCESS_DENIED
;
8591 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8592 if (!W_ERROR_IS_OK(status
))
8595 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
8596 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
8598 /* check for OID in valuename */
8600 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
8606 /* save the registry data */
8608 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
8610 /* save the OID if one was specified and the previous set call succeeded */
8612 if ( W_ERROR_IS_OK(status
) && oid_string
)
8615 fstrcat( keyname
, "\\" );
8616 fstrcat( keyname
, SPOOL_OID_KEY
);
8619 * I'm not checking the status here on purpose. Don't know
8620 * if this is right, but I'm returning the status from the
8621 * previous set_printer_dataex() call. I have no idea if
8622 * this is right. --jerry
8625 set_printer_dataex( printer
, keyname
, valuename
,
8626 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
8629 free_a_printer(&printer
, 2);
8635 /********************************************************************
8636 * spoolss_deleteprinterdataex
8637 ********************************************************************/
8639 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
8641 POLICY_HND
*handle
= &q_u
->handle
;
8642 UNISTR2
*value
= &q_u
->valuename
;
8643 UNISTR2
*key
= &q_u
->keyname
;
8645 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8647 WERROR status
= WERR_OK
;
8648 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8649 pstring valuename
, keyname
;
8651 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8654 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8658 if (!get_printer_snum(p
, handle
, &snum
))
8661 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8662 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8663 return WERR_ACCESS_DENIED
;
8666 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8667 if (!W_ERROR_IS_OK(status
))
8670 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8671 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
8673 status
= delete_printer_dataex( printer
, keyname
, valuename
);
8675 free_a_printer(&printer
, 2);
8680 /********************************************************************
8681 * spoolss_enumprinterkey
8682 ********************************************************************/
8685 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
8688 fstring
*keynames
= NULL
;
8689 uint16
*enumkeys
= NULL
;
8692 POLICY_HND
*handle
= &q_u
->handle
;
8693 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8694 NT_PRINTER_DATA
*data
;
8695 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8697 WERROR status
= WERR_BADFILE
;
8700 DEBUG(4,("_spoolss_enumprinterkey\n"));
8703 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8707 if ( !get_printer_snum(p
,handle
, &snum
) )
8710 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8711 if (!W_ERROR_IS_OK(status
))
8714 /* get the list of subkey names */
8716 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
8717 data
= &printer
->info_2
->data
;
8719 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
8721 if ( num_keys
== -1 ) {
8722 status
= WERR_BADFILE
;
8726 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
8728 r_u
->needed
= printerkey_len
*2;
8730 if ( q_u
->size
< r_u
->needed
) {
8731 status
= WERR_MORE_DATA
;
8735 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
8736 status
= WERR_NOMEM
;
8742 if ( q_u
->size
< r_u
->needed
)
8743 status
= WERR_MORE_DATA
;
8746 free_a_printer( &printer
, 2 );
8747 SAFE_FREE( keynames
);
8752 /********************************************************************
8753 * spoolss_deleteprinterkey
8754 ********************************************************************/
8756 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
8758 POLICY_HND
*handle
= &q_u
->handle
;
8759 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
8761 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8765 DEBUG(5,("spoolss_deleteprinterkey\n"));
8768 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8772 /* if keyname == NULL, return error */
8774 if ( !q_u
->keyname
.buffer
)
8775 return WERR_INVALID_PARAM
;
8777 if (!get_printer_snum(p
, handle
, &snum
))
8780 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8781 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8782 return WERR_ACCESS_DENIED
;
8785 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8786 if (!W_ERROR_IS_OK(status
))
8789 /* delete the key and all subneys */
8791 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
8793 status
= delete_all_printer_data( printer
->info_2
, key
);
8795 if ( W_ERROR_IS_OK(status
) )
8796 status
= mod_a_printer(*printer
, 2);
8798 free_a_printer( &printer
, 2 );
8804 /********************************************************************
8805 * spoolss_enumprinterdataex
8806 ********************************************************************/
8808 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
8810 POLICY_HND
*handle
= &q_u
->handle
;
8811 uint32 in_size
= q_u
->size
;
8814 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8815 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
8816 NT_PRINTER_DATA
*p_data
;
8818 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8823 REGISTRY_VALUE
*val
;
8828 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8831 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
8835 /* first get the printer off of disk */
8837 if (!get_printer_snum(p
,handle
, &snum
))
8840 ZERO_STRUCT(printer
);
8841 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8842 if (!W_ERROR_IS_OK(result
))
8845 /* now look for a match on the key name */
8847 p_data
= &printer
->info_2
->data
;
8849 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
8850 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
8852 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
8853 result
= WERR_INVALID_PARAM
;
8860 /* allocate the memory for the array of pointers -- if necessary */
8862 num_entries
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
8865 if ( (enum_values
=talloc(p
->mem_ctx
, num_entries
*sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
8867 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8868 num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
8869 result
= WERR_NOMEM
;
8873 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
8877 * loop through all params and build the array to pass
8878 * back to the client
8881 for ( i
=0; i
<num_entries
; i
++ )
8883 /* lookup the registry value */
8885 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
8886 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
8890 value_name
= regval_name( val
);
8891 init_unistr( &enum_values
[i
].valuename
, value_name
);
8892 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
8893 enum_values
[i
].type
= regval_type( val
);
8895 data_len
= regval_size( val
);
8897 if ( !(enum_values
[i
].data
= talloc_memdup(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
8899 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8901 result
= WERR_NOMEM
;
8905 enum_values
[i
].data_len
= data_len
;
8907 /* keep track of the size of the array in bytes */
8909 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
8912 /* housekeeping information in the reply */
8914 r_u
->needed
= needed
;
8915 r_u
->returned
= num_entries
;
8917 if (needed
> in_size
) {
8918 result
= WERR_MORE_DATA
;
8922 /* copy data into the reply */
8924 r_u
->ctr
.size
= r_u
->needed
;
8925 r_u
->ctr
.size_of_array
= r_u
->returned
;
8926 r_u
->ctr
.values
= enum_values
;
8931 free_a_printer(&printer
, 2);
8936 /****************************************************************************
8937 ****************************************************************************/
8939 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
8941 init_unistr(&info
->name
, name
);
8944 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
8945 UNISTR2
*environment
,
8952 pstring short_archi
;
8953 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
8955 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
8957 if (get_short_archi(short_archi
, long_archi
)==False
)
8958 return WERR_INVALID_ENVIRONMENT
;
8960 if((info
=(PRINTPROCESSOR_DIRECTORY_1
*)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1
))) == NULL
)
8963 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8965 fill_printprocessordirectory_1(info
, path
);
8967 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
8969 if (!alloc_buffer_size(buffer
, *needed
)) {
8971 return WERR_INSUFFICIENT_BUFFER
;
8974 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
8978 if (*needed
> offered
)
8979 return WERR_INSUFFICIENT_BUFFER
;
8984 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
8986 uint32 level
= q_u
->level
;
8987 NEW_BUFFER
*buffer
= NULL
;
8988 uint32 offered
= q_u
->offered
;
8989 uint32
*needed
= &r_u
->needed
;
8992 /* that's an [in out] buffer */
8993 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8994 buffer
= r_u
->buffer
;
8996 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9002 result
= getprintprocessordirectory_level_1
9003 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
9006 result
= WERR_UNKNOWN_LEVEL
;
9014 WERROR
_spoolss_replyopenprinter(pipes_struct
*p
, SPOOL_Q_REPLYOPENPRINTER
*q_u
,
9015 SPOOL_R_REPLYOPENPRINTER
*r_u
)
9017 DEBUG(5,("_spoolss_replyopenprinter\n"));
9019 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u
->printer
));
9024 WERROR
_spoolss_replycloseprinter(pipes_struct
*p
, SPOOL_Q_REPLYCLOSEPRINTER
*q_u
,
9025 SPOOL_R_REPLYCLOSEPRINTER
*r_u
)
9027 DEBUG(5,("_spoolss_replycloseprinter\n"));