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 client'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
= talloc(mem_ctx
, prs_offset(&ps
));
711 prs_copy_all_data_out((char *)data
->notify_data
.data
.string
, &ps
);
716 struct notify2_message_table
{
718 void (*fn
)(struct spoolss_notify_msg
*msg
,
719 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
722 static struct notify2_message_table printer_notify_table
[] = {
723 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
724 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
725 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
726 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
727 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
728 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
729 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
730 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
731 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
732 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
733 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
734 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
735 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
736 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
737 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
738 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
739 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
740 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
741 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
744 static struct notify2_message_table job_notify_table
[] = {
745 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
746 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
747 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
748 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
749 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
750 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
751 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
752 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
753 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
754 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
755 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
756 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
757 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
758 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
759 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
760 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
761 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
762 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
763 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
764 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
765 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
766 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
767 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
768 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
772 /***********************************************************************
773 Allocate talloc context for container object
774 **********************************************************************/
776 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
781 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
786 /***********************************************************************
787 release all allocated memory and zero out structure
788 **********************************************************************/
790 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
796 talloc_destroy(ctr
->ctx
);
803 /***********************************************************************
804 **********************************************************************/
806 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
814 /***********************************************************************
815 **********************************************************************/
817 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
819 if ( !ctr
|| !ctr
->msg_groups
)
822 if ( idx
>= ctr
->num_groups
)
825 return &ctr
->msg_groups
[idx
];
829 /***********************************************************************
830 How many groups of change messages do we have ?
831 **********************************************************************/
833 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
838 return ctr
->num_groups
;
841 /***********************************************************************
842 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
843 **********************************************************************/
845 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
847 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
848 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
849 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
855 /* loop over all groups looking for a matching printer name */
857 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
858 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
862 /* add a new group? */
864 if ( i
== ctr
->num_groups
)
868 if ( !(groups
= talloc_realloc( ctr
->ctx
, ctr
->msg_groups
, sizeof(SPOOLSS_NOTIFY_MSG_GROUP
)*ctr
->num_groups
)) ) {
869 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
872 ctr
->msg_groups
= groups
;
874 /* clear the new entry and set the printer name */
876 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
877 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
880 /* add the change messages; 'i' is the correct index now regardless */
882 msg_grp
= &ctr
->msg_groups
[i
];
886 if ( !(msg_list
= talloc_realloc( ctr
->ctx
, msg_grp
->msgs
, sizeof(SPOOLSS_NOTIFY_MSG
)*msg_grp
->num_msgs
)) ) {
887 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
890 msg_grp
->msgs
= msg_list
;
892 new_slot
= msg_grp
->num_msgs
-1;
893 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
895 /* need to allocate own copy of data */
898 msg_grp
->msgs
[new_slot
].notify
.data
= talloc_memdup( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
900 return ctr
->num_groups
;
903 /***********************************************************************
904 Send a change notication message on all handles which have a call
906 **********************************************************************/
908 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
911 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
912 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
913 SPOOLSS_NOTIFY_MSG
*messages
;
917 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
921 messages
= msg_group
->msgs
;
924 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
928 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
930 /* loop over all printers */
932 for (p
= printers_list
; p
; p
= p
->next
)
934 SPOOL_NOTIFY_INFO_DATA
*data
;
939 /* Is there notification on this handle? */
941 if ( !p
->notify
.client_connected
)
944 DEBUG(10,("Client connected! [%s]\n", p
->dev
.handlename
));
946 /* For this printer? Print servers always receive
949 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
950 ( !strequal(msg_group
->printername
, p
->dev
.handlename
) ) )
953 DEBUG(10,("Our printer\n"));
955 /* allocate the max entries possible */
957 data
= talloc( mem_ctx
, msg_group
->num_msgs
*sizeof(SPOOL_NOTIFY_INFO_DATA
) );
962 /* build the array of change notifications */
964 for ( i
=0; i
<msg_group
->num_msgs
; i
++ )
966 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
968 /* Are we monitoring this event? */
970 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
974 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
975 msg
->type
, msg
->field
, p
->dev
.handlename
));
978 * if the is a printer notification handle and not a job notification
979 * type, then set the id to 0. Other wise just use what was specified
982 * When registering change notification on a print server handle
983 * we always need to send back the id (snum) matching the printer
984 * for which the change took place. For change notify registered
985 * on a printer handle, this does not matter and the id should be 0.
990 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
996 /* Convert unix jobid to smb jobid */
998 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
)
1000 id
= sysjob_to_jobid(msg
->id
);
1003 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1008 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1011 case PRINTER_NOTIFY_TYPE
:
1012 if ( printer_notify_table
[msg
->field
].fn
)
1013 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1016 case JOB_NOTIFY_TYPE
:
1017 if ( job_notify_table
[msg
->field
].fn
)
1018 job_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1022 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1029 cli_spoolss_rrpcn( ¬ify_cli
, mem_ctx
, &p
->notify
.client_hnd
,
1030 data_len
, data
, p
->notify
.change
, 0 );
1034 DEBUG(8,("send_notify2_changes: Exit...\n"));
1038 /***********************************************************************
1039 **********************************************************************/
1041 static BOOL
notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, void *buf
, size_t len
)
1046 /* Unpack message */
1048 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
1051 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddd",
1052 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1055 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
1056 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1058 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
1059 &msg
->len
, &msg
->notify
.data
);
1061 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1062 msg
->type
, msg
->field
, msg
->flags
));
1065 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1066 msg
->notify
.value
[1]));
1068 dump_data(3, msg
->notify
.data
, msg
->len
);
1073 /********************************************************************
1074 Receive a notify2 message list
1075 ********************************************************************/
1077 static void receive_notify2_message_list(int msg_type
, pid_t src
, void *msg
, size_t len
)
1079 size_t msg_count
, i
;
1080 char *buf
= (char *)msg
;
1083 SPOOLSS_NOTIFY_MSG notify
;
1084 SPOOLSS_NOTIFY_MSG_CTR messages
;
1088 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1092 msg_count
= IVAL(buf
, 0);
1095 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count
));
1097 if (msg_count
== 0) {
1098 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1102 /* initialize the container */
1104 ZERO_STRUCT( messages
);
1105 notify_msg_ctr_init( &messages
);
1108 * build message groups for each printer identified
1109 * in a change_notify msg. Remember that a PCN message
1110 * includes the handle returned for the srv_spoolss_replyopenprinter()
1111 * call. Therefore messages are grouped according to printer handle.
1114 for ( i
=0; i
<msg_count
; i
++ )
1116 if (msg_ptr
+ 4 - buf
> len
) {
1117 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1121 msg_len
= IVAL(msg_ptr
,0);
1124 if (msg_ptr
+ msg_len
- buf
> len
) {
1125 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1129 /* unpack messages */
1131 ZERO_STRUCT( notify
);
1132 notify2_unpack_msg( ¬ify
, msg_ptr
, msg_len
);
1135 /* add to correct list in container */
1137 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1139 /* free memory that might have been allocated by notify2_unpack_msg() */
1141 if ( notify
.len
!= 0 )
1142 SAFE_FREE( notify
.notify
.data
);
1145 /* process each group of messages */
1147 num_groups
= notify_msg_ctr_numgroups( &messages
);
1148 for ( i
=0; i
<num_groups
; i
++ )
1149 send_notify2_changes( &messages
, i
);
1154 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1156 notify_msg_ctr_destroy( &messages
);
1161 /********************************************************************
1162 Send a message to ourself about new driver being installed
1163 so we can upgrade the information for each printer bound to this
1165 ********************************************************************/
1167 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
1169 int len
= strlen(drivername
);
1174 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1177 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
1182 /**********************************************************************
1183 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1184 over all printers, upgrading ones as neessary
1185 **********************************************************************/
1187 void do_drv_upgrade_printer(int msg_type
, pid_t src
, void *buf
, size_t len
)
1191 int n_services
= lp_numservices();
1193 len
= MIN(len
,sizeof(drivername
)-1);
1194 strncpy(drivername
, buf
, len
);
1196 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1198 /* Iterate the printer list */
1200 for (snum
=0; snum
<n_services
; snum
++)
1202 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1205 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1207 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
1208 if (!W_ERROR_IS_OK(result
))
1211 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1213 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1215 /* all we care about currently is the change_id */
1217 result
= mod_a_printer(*printer
, 2);
1218 if (!W_ERROR_IS_OK(result
)) {
1219 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1220 dos_errstr(result
)));
1224 free_a_printer(&printer
, 2);
1231 /********************************************************************
1232 Update the cahce for all printq's with a registered client
1234 ********************************************************************/
1236 void update_monitored_printq_cache( void )
1238 Printer_entry
*printer
= printers_list
;
1241 /* loop through all printers and update the cache where
1242 client_connected == True */
1245 if ( (printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
1246 && printer
->notify
.client_connected
)
1248 snum
= print_queue_snum(printer
->dev
.handlename
);
1249 print_queue_status( snum
, NULL
, NULL
);
1252 printer
= printer
->next
;
1257 /********************************************************************
1258 Send a message to ourself about new driver being installed
1259 so we can upgrade the information for each printer bound to this
1261 ********************************************************************/
1263 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1265 int len
= strlen(drivername
);
1270 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1273 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1278 /**********************************************************************
1279 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1280 over all printers, resetting printer data as neessary
1281 **********************************************************************/
1283 void reset_all_printerdata(int msg_type
, pid_t src
, void *buf
, size_t len
)
1287 int n_services
= lp_numservices();
1289 len
= MIN( len
, sizeof(drivername
)-1 );
1290 strncpy( drivername
, buf
, len
);
1292 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1294 /* Iterate the printer list */
1296 for ( snum
=0; snum
<n_services
; snum
++ )
1298 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1301 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1303 result
= get_a_printer( &printer
, 2, lp_servicename(snum
) );
1304 if ( !W_ERROR_IS_OK(result
) )
1308 * if the printer is bound to the driver,
1309 * then reset to the new driver initdata
1312 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1314 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1316 if ( !set_driver_init(printer
, 2) ) {
1317 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1318 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1321 result
= mod_a_printer( *printer
, 2 );
1322 if ( !W_ERROR_IS_OK(result
) ) {
1323 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1324 get_dos_error_msg(result
)));
1328 free_a_printer( &printer
, 2 );
1337 /********************************************************************
1338 Copy routines used by convert_to_openprinterex()
1339 *******************************************************************/
1341 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1349 DEBUG (8,("dup_devmode\n"));
1351 /* bulk copy first */
1353 d
= talloc_memdup(ctx
, devmode
, sizeof(DEVICEMODE
));
1357 /* dup the pointer members separately */
1359 len
= unistrlen(devmode
->devicename
.buffer
);
1361 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1362 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1367 len
= unistrlen(devmode
->formname
.buffer
);
1369 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1370 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1374 d
->private = talloc_memdup(ctx
, devmode
->private, devmode
->driverextra
);
1379 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1381 if (!new_ctr
|| !ctr
)
1384 DEBUG(8,("copy_devmode_ctr\n"));
1386 new_ctr
->size
= ctr
->size
;
1387 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1389 if(ctr
->devmode_ptr
)
1390 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1393 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1395 if (!new_def
|| !def
)
1398 DEBUG(8,("copy_printer_defaults\n"));
1400 new_def
->datatype_ptr
= def
->datatype_ptr
;
1402 if (def
->datatype_ptr
)
1403 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1405 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1407 new_def
->access_required
= def
->access_required
;
1410 /********************************************************************
1411 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1412 * SPOOL_Q_OPEN_PRINTER_EX structure
1413 ********************************************************************/
1415 static void convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1417 if (!q_u_ex
|| !q_u
)
1420 DEBUG(8,("convert_to_openprinterex\n"));
1422 q_u_ex
->printername_ptr
= q_u
->printername_ptr
;
1424 if (q_u
->printername_ptr
)
1425 copy_unistr2(&q_u_ex
->printername
, &q_u
->printername
);
1427 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1430 /********************************************************************
1431 * spoolss_open_printer
1433 * called from the spoolss dispatcher
1434 ********************************************************************/
1436 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1438 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1439 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1444 ZERO_STRUCT(q_u_ex
);
1445 ZERO_STRUCT(r_u_ex
);
1447 /* convert the OpenPrinter() call to OpenPrinterEx() */
1449 convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1451 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1453 /* convert back to OpenPrinter() */
1455 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1460 /********************************************************************
1461 * spoolss_open_printer
1463 * If the openprinterex rpc call contains a devmode,
1464 * it's a per-user one. This per-user devmode is derivated
1465 * from the global devmode. Openprinterex() contains a per-user
1466 * devmode for when you do EMF printing and spooling.
1467 * In the EMF case, the NT workstation is only doing half the job
1468 * of rendering the page. The other half is done by running the printer
1469 * driver on the server.
1470 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1471 * The EMF file only contains what is to be printed on the page.
1472 * So in order for the server to know how to print, the NT client sends
1473 * a devicemode attached to the openprinterex call.
1474 * But this devicemode is short lived, it's only valid for the current print job.
1476 * If Samba would have supported EMF spooling, this devicemode would
1477 * have been attached to the handle, to sent it to the driver to correctly
1478 * rasterize the EMF file.
1480 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1481 * we just act as a pass-thru between windows and the printer.
1483 * In order to know that Samba supports only RAW spooling, NT has to call
1484 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1485 * and until NT sends a RAW job, we refuse it.
1487 * But to call getprinter() or startdoc(), you first need a valid handle,
1488 * and to get an handle you have to call openprintex(). Hence why you have
1489 * a devicemode in the openprinterex() call.
1492 * Differences between NT4 and NT 2000.
1495 * On NT4, you only have a global devicemode. This global devicemode can be changed
1496 * by the administrator (or by a user with enough privs). Everytime a user
1497 * wants to print, the devicemode is resetted to the default. In Word, everytime
1498 * you print, the printer's characteristics are always reset to the global devicemode.
1502 * In W2K, there is the notion of per-user devicemode. The first time you use
1503 * a printer, a per-user devicemode is build from the global devicemode.
1504 * If you change your per-user devicemode, it is saved in the registry, under the
1505 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1506 * printer preferences available.
1508 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1509 * on the General Tab of the printer properties windows.
1511 * To change the global devicemode: it's the "Printing Defaults..." button
1512 * on the Advanced Tab of the printer properties window.
1515 ********************************************************************/
1517 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1519 UNISTR2
*printername
= NULL
;
1520 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1521 POLICY_HND
*handle
= &r_u
->handle
;
1525 struct current_user user
;
1526 Printer_entry
*Printer
=NULL
;
1528 if (q_u
->printername_ptr
!= 0)
1529 printername
= &q_u
->printername
;
1531 if (printername
== NULL
)
1532 return WERR_INVALID_PRINTER_NAME
;
1534 /* some sanity check because you can open a printer or a print server */
1535 /* aka: \\server\printer or \\server */
1536 unistr2_to_ascii(name
, printername
, sizeof(name
)-1);
1538 DEBUGADD(3,("checking name: %s\n",name
));
1540 if (!open_printer_hnd(p
, handle
, name
, 0))
1541 return WERR_INVALID_PRINTER_NAME
;
1543 Printer
=find_printer_index_by_hnd(p
, handle
);
1545 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1546 Can't find printer handle we created for printer %s\n", name
));
1547 close_printer_handle(p
,handle
);
1548 return WERR_INVALID_PRINTER_NAME
;
1551 get_current_user(&user
, p
);
1554 * First case: the user is opening the print server:
1556 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1557 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1559 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1560 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1561 * or if the user is listed in the smb.conf printer admin parameter.
1563 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1564 * client view printer folder, but does not show the MSAPW.
1566 * Note: this test needs code to check access rights here too. Jeremy
1567 * could you look at this?
1569 * Second case: the user is opening a printer:
1570 * NT doesn't let us connect to a printer if the connecting user
1571 * doesn't have print permission.
1574 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1576 /* Printserver handles use global struct... */
1580 /* Map standard access rights to object specific access rights */
1582 se_map_standard(&printer_default
->access_required
,
1583 &printserver_std_mapping
);
1585 /* Deny any object specific bits that don't apply to print
1586 servers (i.e printer and job specific bits) */
1588 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1590 if (printer_default
->access_required
&
1591 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1592 DEBUG(3, ("access DENIED for non-printserver bits"));
1593 close_printer_handle(p
, handle
);
1594 return WERR_ACCESS_DENIED
;
1597 /* Allow admin access */
1599 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1601 if (!lp_ms_add_printer_wizard()) {
1602 close_printer_handle(p
, handle
);
1603 return WERR_ACCESS_DENIED
;
1606 /* if the user is not root and not a printer admin, then fail */
1609 && !user_in_list(uidtoname(user
.uid
), lp_printer_admin(snum
), user
.groups
, user
.ngroups
) )
1611 close_printer_handle(p
, handle
);
1612 return WERR_ACCESS_DENIED
;
1615 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1619 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1622 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1623 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1625 /* We fall through to return WERR_OK */
1630 /* NT doesn't let us connect to a printer if the connecting user
1631 doesn't have print permission. */
1633 if (!get_printer_snum(p
, handle
, &snum
))
1636 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1638 /* map an empty access mask to the minimum access mask */
1639 if (printer_default
->access_required
== 0x0)
1640 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1643 * If we are not serving the printer driver for this printer,
1644 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1645 * will keep NT clients happy --jerry
1648 if (lp_use_client_driver(snum
)
1649 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1651 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1654 /* check smb.conf parameters and the the sec_desc */
1656 if (!user_ok(uidtoname(user
.uid
), snum
, user
.groups
, user
.ngroups
) || !print_access_check(&user
, snum
, printer_default
->access_required
)) {
1657 DEBUG(3, ("access DENIED for printer open\n"));
1658 close_printer_handle(p
, handle
);
1659 return WERR_ACCESS_DENIED
;
1662 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1663 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1664 close_printer_handle(p
, handle
);
1665 return WERR_ACCESS_DENIED
;
1668 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1669 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1671 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1673 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1674 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1678 Printer
->access_granted
= printer_default
->access_required
;
1681 * If the client sent a devmode in the OpenPrinter() call, then
1682 * save it here in case we get a job submission on this handle
1685 if ( (Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTSERVER
)
1686 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1688 convert_devicemode( Printer
->dev
.handlename
, q_u
->printer_default
.devmode_cont
.devmode
,
1689 &Printer
->nt_devmode
);
1695 /****************************************************************************
1696 ****************************************************************************/
1698 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1699 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1705 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
1714 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1715 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1721 printer
->info_3
=NULL
;
1722 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1726 printer
->info_6
=NULL
;
1727 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1737 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1738 NT_DEVICEMODE
**pp_nt_devmode
)
1740 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1743 * Ensure nt_devmode is a valid pointer
1744 * as we will be overwriting it.
1747 if (nt_devmode
== NULL
) {
1748 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1749 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1753 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1754 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1756 nt_devmode
->specversion
=devmode
->specversion
;
1757 nt_devmode
->driverversion
=devmode
->driverversion
;
1758 nt_devmode
->size
=devmode
->size
;
1759 nt_devmode
->fields
=devmode
->fields
;
1760 nt_devmode
->orientation
=devmode
->orientation
;
1761 nt_devmode
->papersize
=devmode
->papersize
;
1762 nt_devmode
->paperlength
=devmode
->paperlength
;
1763 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1764 nt_devmode
->scale
=devmode
->scale
;
1765 nt_devmode
->copies
=devmode
->copies
;
1766 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1767 nt_devmode
->printquality
=devmode
->printquality
;
1768 nt_devmode
->color
=devmode
->color
;
1769 nt_devmode
->duplex
=devmode
->duplex
;
1770 nt_devmode
->yresolution
=devmode
->yresolution
;
1771 nt_devmode
->ttoption
=devmode
->ttoption
;
1772 nt_devmode
->collate
=devmode
->collate
;
1774 nt_devmode
->logpixels
=devmode
->logpixels
;
1775 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1776 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1777 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1778 nt_devmode
->displayflags
=devmode
->displayflags
;
1779 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1780 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1781 nt_devmode
->icmintent
=devmode
->icmintent
;
1782 nt_devmode
->mediatype
=devmode
->mediatype
;
1783 nt_devmode
->dithertype
=devmode
->dithertype
;
1784 nt_devmode
->reserved1
=devmode
->reserved1
;
1785 nt_devmode
->reserved2
=devmode
->reserved2
;
1786 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1787 nt_devmode
->panningheight
=devmode
->panningheight
;
1790 * Only change private and driverextra if the incoming devmode
1791 * has a new one. JRA.
1794 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1795 SAFE_FREE(nt_devmode
->private);
1796 nt_devmode
->driverextra
=devmode
->driverextra
;
1797 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
1799 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1802 *pp_nt_devmode
= nt_devmode
;
1807 /********************************************************************
1808 * _spoolss_enddocprinter_internal.
1809 ********************************************************************/
1811 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1813 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1817 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1821 if (!get_printer_snum(p
, handle
, &snum
))
1824 Printer
->document_started
=False
;
1825 print_job_end(snum
, Printer
->jobid
,True
);
1826 /* error codes unhandled so far ... */
1831 /********************************************************************
1832 * api_spoolss_closeprinter
1833 ********************************************************************/
1835 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1837 POLICY_HND
*handle
= &q_u
->handle
;
1839 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1841 if (Printer
&& Printer
->document_started
)
1842 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1844 if (!close_printer_handle(p
, handle
))
1847 /* clear the returned printer handle. Observed behavior
1848 from Win2k server. Don't think this really matters.
1849 Previous code just copied the value of the closed
1852 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1857 /********************************************************************
1858 * api_spoolss_deleteprinter
1860 ********************************************************************/
1862 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1864 POLICY_HND
*handle
= &q_u
->handle
;
1865 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1868 if (Printer
&& Printer
->document_started
)
1869 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1871 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1873 result
= delete_printer_handle(p
, handle
);
1875 update_c_setprinter(False
);
1880 /*******************************************************************
1881 * static function to lookup the version id corresponding to an
1882 * long architecture string
1883 ******************************************************************/
1885 static int get_version_id (char * arch
)
1888 struct table_node archi_table
[]= {
1890 {"Windows 4.0", "WIN40", 0 },
1891 {"Windows NT x86", "W32X86", 2 },
1892 {"Windows NT R4000", "W32MIPS", 2 },
1893 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1894 {"Windows NT PowerPC", "W32PPC", 2 },
1898 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1900 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1901 return (archi_table
[i
].version
);
1907 /********************************************************************
1908 * _spoolss_deleteprinterdriver
1909 ********************************************************************/
1911 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1915 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1916 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
1918 struct current_user user
;
1920 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1922 get_current_user(&user
, p
);
1924 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1925 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1927 /* check that we have a valid driver name first */
1929 if ((version
=get_version_id(arch
)) == -1)
1930 return WERR_INVALID_ENVIRONMENT
;
1933 ZERO_STRUCT(info_win2k
);
1935 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
1937 /* try for Win2k driver if "Windows NT x86" */
1939 if ( version
== 2 ) {
1941 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
1942 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1946 /* otherwise it was a failure */
1948 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1954 if (printer_driver_in_use(info
.info_3
)) {
1955 status
= WERR_PRINTER_DRIVER_IN_USE
;
1961 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
1963 /* if we get to here, we now have 2 driver info structures to remove */
1964 /* remove the Win2k driver first*/
1966 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, False
);
1967 free_a_printer_driver( info_win2k
, 3 );
1969 /* this should not have failed---if it did, report to client */
1970 if ( !W_ERROR_IS_OK(status_win2k
) )
1975 status
= delete_printer_driver(info
.info_3
, &user
, version
, False
);
1977 /* if at least one of the deletes succeeded return OK */
1979 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
1983 free_a_printer_driver( info
, 3 );
1988 /********************************************************************
1989 * spoolss_deleteprinterdriverex
1990 ********************************************************************/
1992 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
1996 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1997 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
1999 uint32 flags
= q_u
->delete_flags
;
2001 struct current_user user
;
2003 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2005 get_current_user(&user
, p
);
2007 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2008 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2010 /* check that we have a valid driver name first */
2011 if ((version
=get_version_id(arch
)) == -1) {
2012 /* this is what NT returns */
2013 return WERR_INVALID_ENVIRONMENT
;
2016 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2017 version
= q_u
->version
;
2020 ZERO_STRUCT(info_win2k
);
2022 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2024 if ( !W_ERROR_IS_OK(status
) )
2027 * if the client asked for a specific version,
2028 * or this is something other than Windows NT x86,
2032 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2035 /* try for Win2k driver if "Windows NT x86" */
2038 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2039 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2044 if ( printer_driver_in_use(info
.info_3
) ) {
2045 status
= WERR_PRINTER_DRIVER_IN_USE
;
2050 * we have a couple of cases to consider.
2051 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2052 * then the delete should fail if **any** files overlap with
2054 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2055 * non-overlapping files
2056 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2057 * is set, the do not delete any files
2058 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2061 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2063 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2065 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2066 /* no idea of the correct error here */
2067 status
= WERR_ACCESS_DENIED
;
2072 /* also check for W32X86/3 if necessary; maybe we already have? */
2074 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2075 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2078 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2079 /* no idea of the correct error here */
2080 free_a_printer_driver( info_win2k
, 3 );
2081 status
= WERR_ACCESS_DENIED
;
2085 /* if we get to here, we now have 2 driver info structures to remove */
2086 /* remove the Win2k driver first*/
2088 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, delete_files
);
2089 free_a_printer_driver( info_win2k
, 3 );
2091 /* this should not have failed---if it did, report to client */
2093 if ( !W_ERROR_IS_OK(status_win2k
) )
2098 status
= delete_printer_driver(info
.info_3
, &user
, version
, delete_files
);
2100 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2103 free_a_printer_driver( info
, 3 );
2109 /****************************************************************************
2110 Internal routine for retreiving printerdata
2111 ***************************************************************************/
2113 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2114 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2115 uint32
*needed
, uint32 in_size
)
2117 REGISTRY_VALUE
*val
;
2120 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2121 return WERR_BADFILE
;
2123 *type
= regval_type( val
);
2125 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2127 size
= regval_size( val
);
2129 /* copy the min(in_size, len) */
2132 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2134 /* special case for 0 length values */
2136 if ( (*data
= (uint8
*)talloc_memdup(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2140 if ( (*data
= (uint8
*)talloc_zero(ctx
, in_size
)) == NULL
)
2149 DEBUG(5,("get_printer_dataex: copy done\n"));
2154 /****************************************************************************
2155 Internal routine for removing printerdata
2156 ***************************************************************************/
2158 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2160 delete_printer_data( printer
->info_2
, key
, value
);
2162 return mod_a_printer(*printer
, 2);
2165 /****************************************************************************
2166 Internal routine for storing printerdata
2167 ***************************************************************************/
2169 static WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2170 uint32 type
, uint8
*data
, int real_len
)
2172 delete_printer_data( printer
->info_2
, key
, value
);
2174 add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2176 return mod_a_printer(*printer
, 2);
2179 /********************************************************************
2180 GetPrinterData on a printer server Handle.
2181 ********************************************************************/
2183 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2187 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2189 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2191 if((*data
= (uint8
*)talloc_zero(ctx
, 4*sizeof(uint8
) )) == NULL
)
2197 if (!StrCaseCmp(value
, "BeepEnabled")) {
2199 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2201 SIVAL(*data
, 0, 0x00);
2206 if (!StrCaseCmp(value
, "EventLog")) {
2208 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2210 /* formally was 0x1b */
2211 SIVAL(*data
, 0, 0x0);
2216 if (!StrCaseCmp(value
, "NetPopup")) {
2218 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2220 SIVAL(*data
, 0, 0x00);
2225 if (!StrCaseCmp(value
, "MajorVersion")) {
2227 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2238 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2241 fstrcpy(string
, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH
));
2243 *needed
= 2*(strlen(string
)+1);
2244 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2246 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2248 /* it's done by hand ready to go on the wire */
2249 for (i
=0; i
<strlen(string
); i
++) {
2250 (*data
)[2*i
]=string
[i
];
2251 (*data
)[2*i
+1]='\0';
2256 if (!StrCaseCmp(value
, "Architecture")) {
2257 pstring string
="Windows NT x86";
2259 *needed
= 2*(strlen(string
)+1);
2260 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2262 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2263 for (i
=0; i
<strlen(string
); i
++) {
2264 (*data
)[2*i
]=string
[i
];
2265 (*data
)[2*i
+1]='\0';
2270 if (!StrCaseCmp(value
, "DsPresent")) {
2272 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2274 SIVAL(*data
, 0, 0x01);
2279 if (!StrCaseCmp(value
, "DNSMachineName")) {
2282 if (!get_myfullname(hostname
))
2283 return WERR_BADFILE
;
2285 *needed
= 2*(strlen(hostname
)+1);
2286 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2288 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2289 for (i
=0; i
<strlen(hostname
); i
++) {
2290 (*data
)[2*i
]=hostname
[i
];
2291 (*data
)[2*i
+1]='\0';
2297 return WERR_BADFILE
;
2300 /********************************************************************
2301 * spoolss_getprinterdata
2302 ********************************************************************/
2304 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2306 POLICY_HND
*handle
= &q_u
->handle
;
2307 UNISTR2
*valuename
= &q_u
->valuename
;
2308 uint32 in_size
= q_u
->size
;
2309 uint32
*type
= &r_u
->type
;
2310 uint32
*out_size
= &r_u
->size
;
2311 uint8
**data
= &r_u
->data
;
2312 uint32
*needed
= &r_u
->needed
;
2315 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2316 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2320 * Reminder: when it's a string, the length is in BYTES
2321 * even if UNICODE is negociated.
2326 *out_size
= in_size
;
2328 /* in case of problem, return some default values */
2333 DEBUG(4,("_spoolss_getprinterdata\n"));
2336 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2337 status
= WERR_BADFID
;
2341 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2343 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2344 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2347 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2348 status
= WERR_BADFID
;
2352 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
2353 if ( !W_ERROR_IS_OK(status
) )
2356 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2358 if ( strequal(value
, "ChangeId") ) {
2360 *needed
= sizeof(uint32
);
2361 if ( (*data
= (uint8
*)talloc(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2362 status
= WERR_NOMEM
;
2365 **data
= printer
->info_2
->changeid
;
2369 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2372 if (*needed
> *out_size
)
2373 status
= WERR_MORE_DATA
;
2376 if ( !W_ERROR_IS_OK(status
) )
2378 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2380 /* reply this param doesn't exist */
2383 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
2385 free_a_printer( &printer
, 2 );
2394 /* cleanup & exit */
2397 free_a_printer( &printer
, 2 );
2402 /*********************************************************
2403 Connect to the client machine.
2404 **********************************************************/
2406 static BOOL
spoolss_connect_to_client(struct cli_state
*the_cli
, const char *remote_machine
)
2408 ZERO_STRUCTP(the_cli
);
2409 if(cli_initialise(the_cli
) == NULL
) {
2410 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2414 if(!resolve_name( remote_machine
, &the_cli
->dest_ip
, 0x20)) {
2415 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine
));
2416 cli_shutdown(the_cli
);
2420 if (ismyip(the_cli
->dest_ip
)) {
2421 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2422 cli_shutdown(the_cli
);
2426 if (!cli_connect(the_cli
, remote_machine
, &the_cli
->dest_ip
)) {
2427 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2428 cli_shutdown(the_cli
);
2432 if (!attempt_netbios_session_request(the_cli
, global_myname(), remote_machine
, &the_cli
->dest_ip
)) {
2433 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2435 cli_shutdown(the_cli
);
2439 the_cli
->protocol
= PROTOCOL_NT1
;
2441 if (!cli_negprot(the_cli
)) {
2442 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2443 cli_shutdown(the_cli
);
2447 if (the_cli
->protocol
!= PROTOCOL_NT1
) {
2448 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2449 cli_shutdown(the_cli
);
2454 * Do an anonymous session setup.
2457 if (!cli_session_setup(the_cli
, "", "", 0, "", 0, "")) {
2458 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2459 cli_shutdown(the_cli
);
2463 if (!(the_cli
->sec_mode
& 1)) {
2464 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine
));
2465 cli_shutdown(the_cli
);
2469 if (!cli_send_tconX(the_cli
, "IPC$", "IPC", "", 1)) {
2470 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2471 cli_shutdown(the_cli
);
2476 * Ok - we have an anonymous connection to the IPC$ share.
2477 * Now start the NT Domain stuff :-).
2480 if(cli_nt_session_open(the_cli
, PI_SPOOLSS
) == False
) {
2481 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
)));
2482 cli_nt_session_close(the_cli
);
2483 cli_ulogoff(the_cli
);
2484 cli_shutdown(the_cli
);
2491 /***************************************************************************
2492 Connect to the client.
2493 ****************************************************************************/
2495 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
, uint32 localprinter
, uint32 type
, POLICY_HND
*handle
)
2500 * If it's the first connection, contact the client
2501 * and connect to the IPC$ share anonumously
2503 if (smb_connections
==0) {
2504 fstring unix_printer
;
2506 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2508 if(!spoolss_connect_to_client(¬ify_cli
, unix_printer
))
2511 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message_list
);
2512 /* Tell the connections db we're now interested in printer
2513 * notify messages. */
2514 register_message_flags( True
, FLAG_MSG_PRINTING
);
2518 * Tell the specific printing tdb we want messages for this printer
2519 * by registering our PID.
2522 if (!print_notify_register_pid(snum
))
2523 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2527 result
= cli_spoolss_reply_open_printer(¬ify_cli
, notify_cli
.mem_ctx
, printer
, localprinter
,
2530 if (!W_ERROR_IS_OK(result
))
2531 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2532 dos_errstr(result
)));
2534 return (W_ERROR_IS_OK(result
));
2537 /********************************************************************
2539 * ReplyFindFirstPrinterChangeNotifyEx
2541 * before replying OK: status=0 a rpc call is made to the workstation
2542 * asking ReplyOpenPrinter
2544 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2545 * called from api_spoolss_rffpcnex
2546 ********************************************************************/
2548 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2550 POLICY_HND
*handle
= &q_u
->handle
;
2551 uint32 flags
= q_u
->flags
;
2552 uint32 options
= q_u
->options
;
2553 UNISTR2
*localmachine
= &q_u
->localmachine
;
2554 uint32 printerlocal
= q_u
->printerlocal
;
2556 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2558 /* store the notify value in the printer struct */
2560 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2563 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2567 Printer
->notify
.flags
=flags
;
2568 Printer
->notify
.options
=options
;
2569 Printer
->notify
.printerlocal
=printerlocal
;
2571 if (Printer
->notify
.option
)
2572 free_spool_notify_option(&Printer
->notify
.option
);
2574 Printer
->notify
.option
=dup_spool_notify_option(option
);
2576 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2577 sizeof(Printer
->notify
.localmachine
)-1);
2579 /* Connect to the client machine and send a ReplyOpenPrinter */
2581 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2583 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
2584 !get_printer_snum(p
, handle
, &snum
) )
2587 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2588 Printer
->notify
.printerlocal
, 1,
2589 &Printer
->notify
.client_hnd
))
2590 return WERR_SERVER_UNAVAILABLE
;
2592 Printer
->notify
.client_connected
=True
;
2597 /*******************************************************************
2598 * fill a notify_info_data with the servername
2599 ********************************************************************/
2601 void spoolss_notify_server_name(int snum
,
2602 SPOOL_NOTIFY_INFO_DATA
*data
,
2603 print_queue_struct
*queue
,
2604 NT_PRINTER_INFO_LEVEL
*printer
,
2605 TALLOC_CTX
*mem_ctx
)
2607 pstring temp_name
, temp
;
2610 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
2612 len
= rpcstr_push(temp
, temp_name
, sizeof(temp
)-2, STR_TERMINATE
);
2614 data
->notify_data
.data
.length
= len
;
2615 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2617 if (!data
->notify_data
.data
.string
) {
2618 data
->notify_data
.data
.length
= 0;
2622 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2625 /*******************************************************************
2626 * fill a notify_info_data with the printername (not including the servername).
2627 ********************************************************************/
2629 void spoolss_notify_printer_name(int snum
,
2630 SPOOL_NOTIFY_INFO_DATA
*data
,
2631 print_queue_struct
*queue
,
2632 NT_PRINTER_INFO_LEVEL
*printer
,
2633 TALLOC_CTX
*mem_ctx
)
2638 /* the notify name should not contain the \\server\ part */
2639 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2642 p
= printer
->info_2
->printername
;
2647 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2649 data
->notify_data
.data
.length
= len
;
2650 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2652 if (!data
->notify_data
.data
.string
) {
2653 data
->notify_data
.data
.length
= 0;
2657 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2660 /*******************************************************************
2661 * fill a notify_info_data with the servicename
2662 ********************************************************************/
2664 void spoolss_notify_share_name(int snum
,
2665 SPOOL_NOTIFY_INFO_DATA
*data
,
2666 print_queue_struct
*queue
,
2667 NT_PRINTER_INFO_LEVEL
*printer
,
2668 TALLOC_CTX
*mem_ctx
)
2673 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2675 data
->notify_data
.data
.length
= len
;
2676 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2678 if (!data
->notify_data
.data
.string
) {
2679 data
->notify_data
.data
.length
= 0;
2683 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2686 /*******************************************************************
2687 * fill a notify_info_data with the port name
2688 ********************************************************************/
2690 void spoolss_notify_port_name(int snum
,
2691 SPOOL_NOTIFY_INFO_DATA
*data
,
2692 print_queue_struct
*queue
,
2693 NT_PRINTER_INFO_LEVEL
*printer
,
2694 TALLOC_CTX
*mem_ctx
)
2699 /* even if it's strange, that's consistant in all the code */
2701 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2703 data
->notify_data
.data
.length
= len
;
2704 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2706 if (!data
->notify_data
.data
.string
) {
2707 data
->notify_data
.data
.length
= 0;
2711 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2714 /*******************************************************************
2715 * fill a notify_info_data with the printername
2716 * but it doesn't exist, have to see what to do
2717 ********************************************************************/
2719 void spoolss_notify_driver_name(int snum
,
2720 SPOOL_NOTIFY_INFO_DATA
*data
,
2721 print_queue_struct
*queue
,
2722 NT_PRINTER_INFO_LEVEL
*printer
,
2723 TALLOC_CTX
*mem_ctx
)
2728 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2730 data
->notify_data
.data
.length
= len
;
2731 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2733 if (!data
->notify_data
.data
.string
) {
2734 data
->notify_data
.data
.length
= 0;
2738 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2741 /*******************************************************************
2742 * fill a notify_info_data with the comment
2743 ********************************************************************/
2745 void spoolss_notify_comment(int snum
,
2746 SPOOL_NOTIFY_INFO_DATA
*data
,
2747 print_queue_struct
*queue
,
2748 NT_PRINTER_INFO_LEVEL
*printer
,
2749 TALLOC_CTX
*mem_ctx
)
2754 if (*printer
->info_2
->comment
== '\0')
2755 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2757 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2759 data
->notify_data
.data
.length
= len
;
2760 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2762 if (!data
->notify_data
.data
.string
) {
2763 data
->notify_data
.data
.length
= 0;
2767 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2770 /*******************************************************************
2771 * fill a notify_info_data with the comment
2772 * location = "Room 1, floor 2, building 3"
2773 ********************************************************************/
2775 void spoolss_notify_location(int snum
,
2776 SPOOL_NOTIFY_INFO_DATA
*data
,
2777 print_queue_struct
*queue
,
2778 NT_PRINTER_INFO_LEVEL
*printer
,
2779 TALLOC_CTX
*mem_ctx
)
2784 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2786 data
->notify_data
.data
.length
= len
;
2787 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2789 if (!data
->notify_data
.data
.string
) {
2790 data
->notify_data
.data
.length
= 0;
2794 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2797 /*******************************************************************
2798 * fill a notify_info_data with the device mode
2799 * jfm:xxxx don't to it for know but that's a real problem !!!
2800 ********************************************************************/
2802 static void spoolss_notify_devmode(int snum
,
2803 SPOOL_NOTIFY_INFO_DATA
*data
,
2804 print_queue_struct
*queue
,
2805 NT_PRINTER_INFO_LEVEL
*printer
,
2806 TALLOC_CTX
*mem_ctx
)
2810 /*******************************************************************
2811 * fill a notify_info_data with the separator file name
2812 ********************************************************************/
2814 void spoolss_notify_sepfile(int snum
,
2815 SPOOL_NOTIFY_INFO_DATA
*data
,
2816 print_queue_struct
*queue
,
2817 NT_PRINTER_INFO_LEVEL
*printer
,
2818 TALLOC_CTX
*mem_ctx
)
2823 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2825 data
->notify_data
.data
.length
= len
;
2826 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2828 if (!data
->notify_data
.data
.string
) {
2829 data
->notify_data
.data
.length
= 0;
2833 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2836 /*******************************************************************
2837 * fill a notify_info_data with the print processor
2838 * jfm:xxxx return always winprint to indicate we don't do anything to it
2839 ********************************************************************/
2841 void spoolss_notify_print_processor(int snum
,
2842 SPOOL_NOTIFY_INFO_DATA
*data
,
2843 print_queue_struct
*queue
,
2844 NT_PRINTER_INFO_LEVEL
*printer
,
2845 TALLOC_CTX
*mem_ctx
)
2850 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
2852 data
->notify_data
.data
.length
= len
;
2853 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2855 if (!data
->notify_data
.data
.string
) {
2856 data
->notify_data
.data
.length
= 0;
2860 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2863 /*******************************************************************
2864 * fill a notify_info_data with the print processor options
2865 * jfm:xxxx send an empty string
2866 ********************************************************************/
2868 void spoolss_notify_parameters(int snum
,
2869 SPOOL_NOTIFY_INFO_DATA
*data
,
2870 print_queue_struct
*queue
,
2871 NT_PRINTER_INFO_LEVEL
*printer
,
2872 TALLOC_CTX
*mem_ctx
)
2877 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
2879 data
->notify_data
.data
.length
= len
;
2880 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2882 if (!data
->notify_data
.data
.string
) {
2883 data
->notify_data
.data
.length
= 0;
2887 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2890 /*******************************************************************
2891 * fill a notify_info_data with the data type
2892 * jfm:xxxx always send RAW as data type
2893 ********************************************************************/
2895 void spoolss_notify_datatype(int snum
,
2896 SPOOL_NOTIFY_INFO_DATA
*data
,
2897 print_queue_struct
*queue
,
2898 NT_PRINTER_INFO_LEVEL
*printer
,
2899 TALLOC_CTX
*mem_ctx
)
2904 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
2906 data
->notify_data
.data
.length
= len
;
2907 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2909 if (!data
->notify_data
.data
.string
) {
2910 data
->notify_data
.data
.length
= 0;
2914 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2917 /*******************************************************************
2918 * fill a notify_info_data with the security descriptor
2919 * jfm:xxxx send an null pointer to say no security desc
2920 * have to implement security before !
2921 ********************************************************************/
2923 static void spoolss_notify_security_desc(int snum
,
2924 SPOOL_NOTIFY_INFO_DATA
*data
,
2925 print_queue_struct
*queue
,
2926 NT_PRINTER_INFO_LEVEL
*printer
,
2927 TALLOC_CTX
*mem_ctx
)
2929 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
2930 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
2933 /*******************************************************************
2934 * fill a notify_info_data with the attributes
2935 * jfm:xxxx a samba printer is always shared
2936 ********************************************************************/
2938 void spoolss_notify_attributes(int snum
,
2939 SPOOL_NOTIFY_INFO_DATA
*data
,
2940 print_queue_struct
*queue
,
2941 NT_PRINTER_INFO_LEVEL
*printer
,
2942 TALLOC_CTX
*mem_ctx
)
2944 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
2945 data
->notify_data
.value
[1] = 0;
2948 /*******************************************************************
2949 * fill a notify_info_data with the priority
2950 ********************************************************************/
2952 static void spoolss_notify_priority(int snum
,
2953 SPOOL_NOTIFY_INFO_DATA
*data
,
2954 print_queue_struct
*queue
,
2955 NT_PRINTER_INFO_LEVEL
*printer
,
2956 TALLOC_CTX
*mem_ctx
)
2958 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
2959 data
->notify_data
.value
[1] = 0;
2962 /*******************************************************************
2963 * fill a notify_info_data with the default priority
2964 ********************************************************************/
2966 static void spoolss_notify_default_priority(int snum
,
2967 SPOOL_NOTIFY_INFO_DATA
*data
,
2968 print_queue_struct
*queue
,
2969 NT_PRINTER_INFO_LEVEL
*printer
,
2970 TALLOC_CTX
*mem_ctx
)
2972 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
2973 data
->notify_data
.value
[1] = 0;
2976 /*******************************************************************
2977 * fill a notify_info_data with the start time
2978 ********************************************************************/
2980 static void spoolss_notify_start_time(int snum
,
2981 SPOOL_NOTIFY_INFO_DATA
*data
,
2982 print_queue_struct
*queue
,
2983 NT_PRINTER_INFO_LEVEL
*printer
,
2984 TALLOC_CTX
*mem_ctx
)
2986 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
2987 data
->notify_data
.value
[1] = 0;
2990 /*******************************************************************
2991 * fill a notify_info_data with the until time
2992 ********************************************************************/
2994 static void spoolss_notify_until_time(int snum
,
2995 SPOOL_NOTIFY_INFO_DATA
*data
,
2996 print_queue_struct
*queue
,
2997 NT_PRINTER_INFO_LEVEL
*printer
,
2998 TALLOC_CTX
*mem_ctx
)
3000 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
3001 data
->notify_data
.value
[1] = 0;
3004 /*******************************************************************
3005 * fill a notify_info_data with the status
3006 ********************************************************************/
3008 static void spoolss_notify_status(int snum
,
3009 SPOOL_NOTIFY_INFO_DATA
*data
,
3010 print_queue_struct
*queue
,
3011 NT_PRINTER_INFO_LEVEL
*printer
,
3012 TALLOC_CTX
*mem_ctx
)
3014 print_status_struct status
;
3016 print_queue_length(snum
, &status
);
3017 data
->notify_data
.value
[0]=(uint32
) status
.status
;
3018 data
->notify_data
.value
[1] = 0;
3021 /*******************************************************************
3022 * fill a notify_info_data with the number of jobs queued
3023 ********************************************************************/
3025 void spoolss_notify_cjobs(int snum
,
3026 SPOOL_NOTIFY_INFO_DATA
*data
,
3027 print_queue_struct
*queue
,
3028 NT_PRINTER_INFO_LEVEL
*printer
,
3029 TALLOC_CTX
*mem_ctx
)
3031 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3032 data
->notify_data
.value
[1] = 0;
3035 /*******************************************************************
3036 * fill a notify_info_data with the average ppm
3037 ********************************************************************/
3039 static void spoolss_notify_average_ppm(int snum
,
3040 SPOOL_NOTIFY_INFO_DATA
*data
,
3041 print_queue_struct
*queue
,
3042 NT_PRINTER_INFO_LEVEL
*printer
,
3043 TALLOC_CTX
*mem_ctx
)
3045 /* always respond 8 pages per minutes */
3046 /* a little hard ! */
3047 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3048 data
->notify_data
.value
[1] = 0;
3051 /*******************************************************************
3052 * fill a notify_info_data with username
3053 ********************************************************************/
3055 static void spoolss_notify_username(int snum
,
3056 SPOOL_NOTIFY_INFO_DATA
*data
,
3057 print_queue_struct
*queue
,
3058 NT_PRINTER_INFO_LEVEL
*printer
,
3059 TALLOC_CTX
*mem_ctx
)
3064 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3066 data
->notify_data
.data
.length
= len
;
3067 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3069 if (!data
->notify_data
.data
.string
) {
3070 data
->notify_data
.data
.length
= 0;
3074 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3077 /*******************************************************************
3078 * fill a notify_info_data with job status
3079 ********************************************************************/
3081 static void spoolss_notify_job_status(int snum
,
3082 SPOOL_NOTIFY_INFO_DATA
*data
,
3083 print_queue_struct
*queue
,
3084 NT_PRINTER_INFO_LEVEL
*printer
,
3085 TALLOC_CTX
*mem_ctx
)
3087 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3088 data
->notify_data
.value
[1] = 0;
3091 /*******************************************************************
3092 * fill a notify_info_data with job name
3093 ********************************************************************/
3095 static void spoolss_notify_job_name(int snum
,
3096 SPOOL_NOTIFY_INFO_DATA
*data
,
3097 print_queue_struct
*queue
,
3098 NT_PRINTER_INFO_LEVEL
*printer
,
3099 TALLOC_CTX
*mem_ctx
)
3104 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3106 data
->notify_data
.data
.length
= len
;
3107 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3109 if (!data
->notify_data
.data
.string
) {
3110 data
->notify_data
.data
.length
= 0;
3114 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3117 /*******************************************************************
3118 * fill a notify_info_data with job status
3119 ********************************************************************/
3121 static void spoolss_notify_job_status_string(int snum
,
3122 SPOOL_NOTIFY_INFO_DATA
*data
,
3123 print_queue_struct
*queue
,
3124 NT_PRINTER_INFO_LEVEL
*printer
,
3125 TALLOC_CTX
*mem_ctx
)
3128 * Now we're returning job status codes we just return a "" here. JRA.
3135 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3138 switch (queue
->status
) {
3143 p
= ""; /* NT provides the paused string */
3152 #endif /* NO LONGER NEEDED. */
3154 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3156 data
->notify_data
.data
.length
= len
;
3157 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3159 if (!data
->notify_data
.data
.string
) {
3160 data
->notify_data
.data
.length
= 0;
3164 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3167 /*******************************************************************
3168 * fill a notify_info_data with job time
3169 ********************************************************************/
3171 static void spoolss_notify_job_time(int snum
,
3172 SPOOL_NOTIFY_INFO_DATA
*data
,
3173 print_queue_struct
*queue
,
3174 NT_PRINTER_INFO_LEVEL
*printer
,
3175 TALLOC_CTX
*mem_ctx
)
3177 data
->notify_data
.value
[0]=0x0;
3178 data
->notify_data
.value
[1]=0;
3181 /*******************************************************************
3182 * fill a notify_info_data with job size
3183 ********************************************************************/
3185 static void spoolss_notify_job_size(int snum
,
3186 SPOOL_NOTIFY_INFO_DATA
*data
,
3187 print_queue_struct
*queue
,
3188 NT_PRINTER_INFO_LEVEL
*printer
,
3189 TALLOC_CTX
*mem_ctx
)
3191 data
->notify_data
.value
[0]=queue
->size
;
3192 data
->notify_data
.value
[1]=0;
3195 /*******************************************************************
3196 * fill a notify_info_data with page info
3197 ********************************************************************/
3198 static void spoolss_notify_total_pages(int snum
,
3199 SPOOL_NOTIFY_INFO_DATA
*data
,
3200 print_queue_struct
*queue
,
3201 NT_PRINTER_INFO_LEVEL
*printer
,
3202 TALLOC_CTX
*mem_ctx
)
3204 data
->notify_data
.value
[0]=queue
->page_count
;
3205 data
->notify_data
.value
[1]=0;
3208 /*******************************************************************
3209 * fill a notify_info_data with pages printed info.
3210 ********************************************************************/
3211 static void spoolss_notify_pages_printed(int snum
,
3212 SPOOL_NOTIFY_INFO_DATA
*data
,
3213 print_queue_struct
*queue
,
3214 NT_PRINTER_INFO_LEVEL
*printer
,
3215 TALLOC_CTX
*mem_ctx
)
3217 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3218 data
->notify_data
.value
[1]=0;
3221 /*******************************************************************
3222 Fill a notify_info_data with job position.
3223 ********************************************************************/
3225 static void spoolss_notify_job_position(int snum
,
3226 SPOOL_NOTIFY_INFO_DATA
*data
,
3227 print_queue_struct
*queue
,
3228 NT_PRINTER_INFO_LEVEL
*printer
,
3229 TALLOC_CTX
*mem_ctx
)
3231 data
->notify_data
.value
[0]=queue
->job
;
3232 data
->notify_data
.value
[1]=0;
3235 /*******************************************************************
3236 Fill a notify_info_data with submitted time.
3237 ********************************************************************/
3239 static void spoolss_notify_submitted_time(int snum
,
3240 SPOOL_NOTIFY_INFO_DATA
*data
,
3241 print_queue_struct
*queue
,
3242 NT_PRINTER_INFO_LEVEL
*printer
,
3243 TALLOC_CTX
*mem_ctx
)
3250 t
=gmtime(&queue
->time
);
3252 len
= sizeof(SYSTEMTIME
);
3254 data
->notify_data
.data
.length
= len
;
3255 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3257 if (!data
->notify_data
.data
.string
) {
3258 data
->notify_data
.data
.length
= 0;
3262 make_systemtime(&st
, t
);
3265 * Systemtime must be linearized as a set of UINT16's.
3266 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3269 p
= (char *)data
->notify_data
.data
.string
;
3270 SSVAL(p
, 0, st
.year
);
3271 SSVAL(p
, 2, st
.month
);
3272 SSVAL(p
, 4, st
.dayofweek
);
3273 SSVAL(p
, 6, st
.day
);
3274 SSVAL(p
, 8, st
.hour
);
3275 SSVAL(p
, 10, st
.minute
);
3276 SSVAL(p
, 12, st
.second
);
3277 SSVAL(p
, 14, st
.milliseconds
);
3280 struct s_notify_info_data_table
3286 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3287 print_queue_struct
*queue
,
3288 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3291 /* A table describing the various print notification constants and
3292 whether the notification data is a pointer to a variable sized
3293 buffer, a one value uint32 or a two value uint32. */
3295 static const struct s_notify_info_data_table notify_info_data_table
[] =
3297 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3298 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3299 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3300 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3301 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3302 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3303 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3304 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3305 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3306 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3307 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3308 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3309 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3310 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3311 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3312 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3313 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3314 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3315 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3316 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3317 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3318 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3319 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3320 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3321 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3322 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3323 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3324 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3325 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3326 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3327 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3328 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3329 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3330 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3331 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3332 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3333 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3334 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3335 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3336 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3337 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3338 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3339 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3340 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3341 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3342 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3343 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3344 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3345 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3348 /*******************************************************************
3349 Return the size of info_data structure.
3350 ********************************************************************/
3352 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3356 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++)
3358 if ( (notify_info_data_table
[i
].type
== type
)
3359 && (notify_info_data_table
[i
].field
== field
) )
3361 switch(notify_info_data_table
[i
].size
)
3363 case NOTIFY_ONE_VALUE
:
3364 case NOTIFY_TWO_VALUE
:
3369 /* The only pointer notify data I have seen on
3370 the wire is the submitted time and this has
3371 the notify size set to 4. -tpot */
3373 case NOTIFY_POINTER
:
3376 case NOTIFY_SECDESC
:
3382 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3387 /*******************************************************************
3388 Return the type of notify_info_data.
3389 ********************************************************************/
3391 static int type_of_notify_info_data(uint16 type
, uint16 field
)
3395 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3396 if (notify_info_data_table
[i
].type
== type
&&
3397 notify_info_data_table
[i
].field
== field
)
3398 return notify_info_data_table
[i
].size
;
3404 /****************************************************************************
3405 ****************************************************************************/
3407 static int search_notify(uint16 type
, uint16 field
, int *value
)
3411 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3412 if (notify_info_data_table
[i
].type
== type
&&
3413 notify_info_data_table
[i
].field
== field
&&
3414 notify_info_data_table
[i
].fn
!= NULL
) {
3423 /****************************************************************************
3424 ****************************************************************************/
3426 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3428 info_data
->type
= type
;
3429 info_data
->field
= field
;
3430 info_data
->reserved
= 0;
3432 info_data
->size
= size_of_notify_info_data(type
, field
);
3433 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3440 /*******************************************************************
3442 * fill a notify_info struct with info asked
3444 ********************************************************************/
3446 static BOOL
construct_notify_printer_info(SPOOL_NOTIFY_INFO
*info
, int
3447 snum
, SPOOL_NOTIFY_OPTION_TYPE
3448 *option_type
, uint32 id
,
3449 TALLOC_CTX
*mem_ctx
)
3455 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3456 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3457 print_queue_struct
*queue
=NULL
;
3459 type
=option_type
->type
;
3461 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3462 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3463 option_type
->count
, lp_servicename(snum
)));
3465 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3468 for(field_num
=0; field_num
<option_type
->count
; field_num
++)
3470 field
= option_type
->fields
[field_num
];
3472 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3474 if (!search_notify(type
, field
, &j
) )
3477 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
)
3479 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3485 current_data
= &info
->data
[info
->count
];
3487 construct_info_data(current_data
, type
, field
, id
);
3489 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3490 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3492 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3498 free_a_printer(&printer
, 2);
3502 /*******************************************************************
3504 * fill a notify_info struct with info asked
3506 ********************************************************************/
3508 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3509 SPOOL_NOTIFY_INFO
*info
,
3510 NT_PRINTER_INFO_LEVEL
*printer
,
3511 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3512 *option_type
, uint32 id
,
3513 TALLOC_CTX
*mem_ctx
)
3519 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3521 DEBUG(4,("construct_notify_jobs_info\n"));
3523 type
= option_type
->type
;
3525 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3526 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3527 option_type
->count
));
3529 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3530 field
= option_type
->fields
[field_num
];
3532 if (!search_notify(type
, field
, &j
) )
3535 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
3536 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3539 else info
->data
= tid
;
3541 current_data
=&(info
->data
[info
->count
]);
3543 construct_info_data(current_data
, type
, field
, id
);
3544 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3553 * JFM: The enumeration is not that simple, it's even non obvious.
3555 * let's take an example: I want to monitor the PRINTER SERVER for
3556 * the printer's name and the number of jobs currently queued.
3557 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3558 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3560 * I have 3 printers on the back of my server.
3562 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3565 * 1 printer 1 name 1
3566 * 2 printer 1 cjob 1
3567 * 3 printer 2 name 2
3568 * 4 printer 2 cjob 2
3569 * 5 printer 3 name 3
3570 * 6 printer 3 name 3
3572 * that's the print server case, the printer case is even worse.
3575 /*******************************************************************
3577 * enumerate all printers on the printserver
3578 * fill a notify_info struct with info asked
3580 ********************************************************************/
3582 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3583 SPOOL_NOTIFY_INFO
*info
,
3584 TALLOC_CTX
*mem_ctx
)
3587 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3588 int n_services
=lp_numservices();
3591 SPOOL_NOTIFY_OPTION
*option
;
3592 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3594 DEBUG(4,("printserver_notify_info\n"));
3599 option
=Printer
->notify
.option
;
3605 for (i
=0; i
<option
->count
; i
++) {
3606 option_type
=&(option
->ctr
.type
[i
]);
3608 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3611 for (snum
=0; snum
<n_services
; snum
++)
3613 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3614 construct_notify_printer_info ( info
, snum
, option_type
, snum
, mem_ctx
);
3620 * Debugging information, don't delete.
3623 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3624 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3625 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3627 for (i
=0; i
<info
->count
; i
++) {
3628 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3629 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3630 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3637 /*******************************************************************
3639 * fill a notify_info struct with info asked
3641 ********************************************************************/
3643 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3644 TALLOC_CTX
*mem_ctx
)
3647 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3650 SPOOL_NOTIFY_OPTION
*option
;
3651 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3653 print_queue_struct
*queue
=NULL
;
3654 print_status_struct status
;
3656 DEBUG(4,("printer_notify_info\n"));
3661 option
=Printer
->notify
.option
;
3667 get_printer_snum(p
, hnd
, &snum
);
3669 for (i
=0; i
<option
->count
; i
++) {
3670 option_type
=&option
->ctr
.type
[i
];
3672 switch ( option_type
->type
) {
3673 case PRINTER_NOTIFY_TYPE
:
3674 if(construct_notify_printer_info(info
, snum
,
3680 case JOB_NOTIFY_TYPE
: {
3681 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3683 count
= print_queue_status(snum
, &queue
, &status
);
3685 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2,
3686 lp_servicename(snum
))))
3689 for (j
=0; j
<count
; j
++) {
3690 construct_notify_jobs_info(&queue
[j
], info
,
3697 free_a_printer(&printer
, 2);
3707 * Debugging information, don't delete.
3710 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3711 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3712 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3714 for (i=0; i<info->count; i++) {
3715 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3716 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3717 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3723 /********************************************************************
3725 ********************************************************************/
3727 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3729 POLICY_HND
*handle
= &q_u
->handle
;
3730 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3732 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3733 WERROR result
= WERR_BADFID
;
3735 /* we always have a NOTIFY_INFO struct */
3739 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3740 OUR_HANDLE(handle
)));
3744 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3747 * We are now using the change value, and
3748 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3749 * I don't have a global notification system, I'm sending back all the
3750 * informations even when _NOTHING_ has changed.
3753 /* We need to keep track of the change value to send back in
3754 RRPCN replies otherwise our updates are ignored. */
3756 Printer
->notify
.fnpcn
= True
;
3758 if (Printer
->notify
.client_connected
) {
3759 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3760 Printer
->notify
.change
= q_u
->change
;
3763 /* just ignore the SPOOL_NOTIFY_OPTION */
3765 switch (Printer
->printer_type
) {
3766 case PRINTER_HANDLE_IS_PRINTSERVER
:
3767 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3770 case PRINTER_HANDLE_IS_PRINTER
:
3771 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3775 Printer
->notify
.fnpcn
= False
;
3781 /********************************************************************
3782 * construct_printer_info_0
3783 * fill a printer_info_0 struct
3784 ********************************************************************/
3786 static BOOL
construct_printer_info_0(PRINTER_INFO_0
*printer
, int snum
)
3790 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3791 counter_printer_0
*session_counter
;
3792 uint32 global_counter
;
3795 print_status_struct status
;
3797 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3800 count
= print_queue_length(snum
, &status
);
3802 /* check if we already have a counter for this printer */
3803 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
3805 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
3806 if (session_counter
->snum
== snum
)
3810 /* it's the first time, add it to the list */
3811 if (session_counter
==NULL
) {
3812 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
3813 free_a_printer(&ntprinter
, 2);
3816 ZERO_STRUCTP(session_counter
);
3817 session_counter
->snum
=snum
;
3818 session_counter
->counter
=0;
3819 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
3823 session_counter
->counter
++;
3826 * the global_counter should be stored in a TDB as it's common to all the clients
3827 * and should be zeroed on samba startup
3829 global_counter
=session_counter
->counter
;
3831 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3833 init_unistr(&printer
->printername
, chaine
);
3835 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_called_name());
3836 init_unistr(&printer
->servername
, chaine
);
3838 printer
->cjobs
= count
;
3839 printer
->total_jobs
= 0;
3840 printer
->total_bytes
= 0;
3842 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3843 t
=gmtime(&setuptime
);
3845 printer
->year
= t
->tm_year
+1900;
3846 printer
->month
= t
->tm_mon
+1;
3847 printer
->dayofweek
= t
->tm_wday
;
3848 printer
->day
= t
->tm_mday
;
3849 printer
->hour
= t
->tm_hour
;
3850 printer
->minute
= t
->tm_min
;
3851 printer
->second
= t
->tm_sec
;
3852 printer
->milliseconds
= 0;
3854 printer
->global_counter
= global_counter
;
3855 printer
->total_pages
= 0;
3857 printer
->major_version
= 0x0005; /* NT 5 */
3858 printer
->build_version
= 0x0893; /* build 2195 */
3860 printer
->major_version
= 0x0004; /* NT 4 */
3861 printer
->build_version
= 0x0565; /* build 1381 */
3863 printer
->unknown7
= 0x1;
3864 printer
->unknown8
= 0x0;
3865 printer
->unknown9
= 0x0;
3866 printer
->session_counter
= session_counter
->counter
;
3867 printer
->unknown11
= 0x0;
3868 printer
->printer_errors
= 0x0; /* number of print failure */
3869 printer
->unknown13
= 0x0;
3870 printer
->unknown14
= 0x1;
3871 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
3872 printer
->unknown16
= 0x0;
3873 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3874 printer
->unknown18
= 0x0;
3875 printer
->status
= nt_printq_status(status
.status
);
3876 printer
->unknown20
= 0x0;
3877 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3878 printer
->unknown22
= 0x0;
3879 printer
->unknown23
= 0x6; /* 6 ???*/
3880 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
3881 printer
->unknown25
= 0;
3882 printer
->unknown26
= 0;
3883 printer
->unknown27
= 0;
3884 printer
->unknown28
= 0;
3885 printer
->unknown29
= 0;
3887 free_a_printer(&ntprinter
,2);
3891 /********************************************************************
3892 * construct_printer_info_1
3893 * fill a printer_info_1 struct
3894 ********************************************************************/
3895 static BOOL
construct_printer_info_1(uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
3899 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3901 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3904 printer
->flags
=flags
;
3906 if (*ntprinter
->info_2
->comment
== '\0') {
3907 init_unistr(&printer
->comment
, lp_comment(snum
));
3908 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3909 ntprinter
->info_2
->drivername
, lp_comment(snum
));
3912 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3913 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3914 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
3917 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
3919 init_unistr(&printer
->description
, chaine
);
3920 init_unistr(&printer
->name
, chaine2
);
3922 free_a_printer(&ntprinter
,2);
3927 /****************************************************************************
3928 Free a DEVMODE struct.
3929 ****************************************************************************/
3931 static void free_dev_mode(DEVICEMODE
*dev
)
3936 SAFE_FREE(dev
->private);
3941 /****************************************************************************
3942 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3943 should be valid upon entry
3944 ****************************************************************************/
3946 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
3948 if ( !devmode
|| !ntdevmode
)
3951 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
3953 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
3955 devmode
->specversion
= ntdevmode
->specversion
;
3956 devmode
->driverversion
= ntdevmode
->driverversion
;
3957 devmode
->size
= ntdevmode
->size
;
3958 devmode
->driverextra
= ntdevmode
->driverextra
;
3959 devmode
->fields
= ntdevmode
->fields
;
3961 devmode
->orientation
= ntdevmode
->orientation
;
3962 devmode
->papersize
= ntdevmode
->papersize
;
3963 devmode
->paperlength
= ntdevmode
->paperlength
;
3964 devmode
->paperwidth
= ntdevmode
->paperwidth
;
3965 devmode
->scale
= ntdevmode
->scale
;
3966 devmode
->copies
= ntdevmode
->copies
;
3967 devmode
->defaultsource
= ntdevmode
->defaultsource
;
3968 devmode
->printquality
= ntdevmode
->printquality
;
3969 devmode
->color
= ntdevmode
->color
;
3970 devmode
->duplex
= ntdevmode
->duplex
;
3971 devmode
->yresolution
= ntdevmode
->yresolution
;
3972 devmode
->ttoption
= ntdevmode
->ttoption
;
3973 devmode
->collate
= ntdevmode
->collate
;
3974 devmode
->icmmethod
= ntdevmode
->icmmethod
;
3975 devmode
->icmintent
= ntdevmode
->icmintent
;
3976 devmode
->mediatype
= ntdevmode
->mediatype
;
3977 devmode
->dithertype
= ntdevmode
->dithertype
;
3979 if (ntdevmode
->private != NULL
) {
3980 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
3987 /****************************************************************************
3988 Create a DEVMODE struct. Returns malloced memory.
3989 ****************************************************************************/
3991 DEVICEMODE
*construct_dev_mode(int snum
)
3993 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3994 DEVICEMODE
*devmode
= NULL
;
3996 DEBUG(7,("construct_dev_mode\n"));
3998 DEBUGADD(8,("getting printer characteristics\n"));
4000 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4003 if ( !printer
->info_2
->devmode
) {
4004 DEBUG(5, ("BONG! There was no device mode!\n"));
4008 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
4009 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4013 ZERO_STRUCTP(devmode
);
4015 DEBUGADD(8,("loading DEVICEMODE\n"));
4017 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
4018 free_dev_mode( devmode
);
4023 free_a_printer(&printer
,2);
4028 /********************************************************************
4029 * construct_printer_info_2
4030 * fill a printer_info_2 struct
4031 ********************************************************************/
4033 static BOOL
construct_printer_info_2(PRINTER_INFO_2
*printer
, int snum
)
4036 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4038 print_status_struct status
;
4040 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4043 count
= print_queue_length(snum
, &status
);
4045 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4046 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4047 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4048 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4049 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4051 if (*ntprinter
->info_2
->comment
== '\0')
4052 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4054 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4056 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4057 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4058 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4059 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4060 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4062 printer
->attributes
= ntprinter
->info_2
->attributes
;
4064 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4065 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4066 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4067 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4068 printer
->status
= nt_printq_status(status
.status
); /* status */
4069 printer
->cjobs
= count
; /* jobs */
4070 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4072 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
4073 DEBUG(8, ("Returning NULL Devicemode!\n"));
4076 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4077 /* steal the printer info sec_desc structure. [badly done]. */
4078 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4079 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
4080 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
4081 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
4084 printer
->secdesc
= NULL
;
4087 free_a_printer(&ntprinter
, 2);
4091 /********************************************************************
4092 * construct_printer_info_3
4093 * fill a printer_info_3 struct
4094 ********************************************************************/
4096 static BOOL
construct_printer_info_3(PRINTER_INFO_3
**pp_printer
, int snum
)
4098 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4099 PRINTER_INFO_3
*printer
= NULL
;
4101 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4105 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
4106 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4110 ZERO_STRUCTP(printer
);
4112 printer
->flags
= 4; /* These are the components of the SD we are returning. */
4113 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4114 /* steal the printer info sec_desc structure. [badly done]. */
4115 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4119 * Set the flags for the components we are returning.
4122 if (printer
->secdesc
->owner_sid
)
4123 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
4125 if (printer
->secdesc
->grp_sid
)
4126 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
4128 if (printer
->secdesc
->dacl
)
4129 printer
->flags
|= DACL_SECURITY_INFORMATION
;
4131 if (printer
->secdesc
->sacl
)
4132 printer
->flags
|= SACL_SECURITY_INFORMATION
;
4135 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
4136 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
4137 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
4140 free_a_printer(&ntprinter
, 2);
4142 *pp_printer
= printer
;
4146 /********************************************************************
4147 * construct_printer_info_4
4148 * fill a printer_info_4 struct
4149 ********************************************************************/
4151 static BOOL
construct_printer_info_4(PRINTER_INFO_4
*printer
, int snum
)
4153 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4155 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4158 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4159 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4160 printer
->attributes
= ntprinter
->info_2
->attributes
;
4162 free_a_printer(&ntprinter
, 2);
4166 /********************************************************************
4167 * construct_printer_info_5
4168 * fill a printer_info_5 struct
4169 ********************************************************************/
4171 static BOOL
construct_printer_info_5(PRINTER_INFO_5
*printer
, int snum
)
4173 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4175 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4178 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
);
4179 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
);
4180 printer
->attributes
= ntprinter
->info_2
->attributes
;
4182 /* these two are not used by NT+ according to MSDN */
4184 printer
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4185 printer
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4187 free_a_printer(&ntprinter
, 2);
4192 /********************************************************************
4193 * construct_printer_info_7
4194 * fill a printer_info_7 struct
4195 ********************************************************************/
4197 static BOOL
construct_printer_info_7(PRINTER_INFO_7
*printer
, int snum
)
4199 char *guid_str
= NULL
;
4202 if (is_printer_published(snum
, &guid
)) {
4203 asprintf(&guid_str
, "{%s}", uuid_string_static(guid
));
4205 init_unistr(&printer
->guid
, guid_str
);
4206 printer
->action
= SPOOL_DS_PUBLISH
;
4208 init_unistr(&printer
->guid
, "");
4209 printer
->action
= SPOOL_DS_UNPUBLISH
;
4215 /********************************************************************
4216 Spoolss_enumprinters.
4217 ********************************************************************/
4219 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4223 int n_services
=lp_numservices();
4224 PRINTER_INFO_1
*tp
, *printers
=NULL
;
4225 PRINTER_INFO_1 current_prt
;
4227 DEBUG(4,("enum_all_printers_info_1\n"));
4229 for (snum
=0; snum
<n_services
; snum
++) {
4230 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4231 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4233 if (construct_printer_info_1(flags
, ¤t_prt
, snum
)) {
4234 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
4235 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4236 SAFE_FREE(printers
);
4241 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4243 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4249 /* check the required size. */
4250 for (i
=0; i
<*returned
; i
++)
4251 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4253 if (!alloc_buffer_size(buffer
, *needed
))
4254 return WERR_INSUFFICIENT_BUFFER
;
4256 /* fill the buffer with the structures */
4257 for (i
=0; i
<*returned
; i
++)
4258 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4261 SAFE_FREE(printers
);
4263 if (*needed
> offered
) {
4265 return WERR_INSUFFICIENT_BUFFER
;
4271 /********************************************************************
4272 enum_all_printers_info_1_local.
4273 *********************************************************************/
4275 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4277 DEBUG(4,("enum_all_printers_info_1_local\n"));
4279 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4282 /********************************************************************
4283 enum_all_printers_info_1_name.
4284 *********************************************************************/
4286 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4290 DEBUG(4,("enum_all_printers_info_1_name\n"));
4292 if ((name
[0] == '\\') && (name
[1] == '\\'))
4295 if (is_myname_or_ipaddr(s
)) {
4296 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4299 return WERR_INVALID_NAME
;
4302 /********************************************************************
4303 enum_all_printers_info_1_remote.
4304 *********************************************************************/
4306 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4308 PRINTER_INFO_1
*printer
;
4309 fstring printername
;
4312 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4314 /* JFM: currently it's more a place holder than anything else.
4315 * In the spooler world there is a notion of server registration.
4316 * the print servers are registring (sp ?) on the PDC (in the same domain)
4318 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4321 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4326 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4327 slprintf(desc
, sizeof(desc
)-1,"%s", get_called_name());
4328 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4330 init_unistr(&printer
->description
, desc
);
4331 init_unistr(&printer
->name
, printername
);
4332 init_unistr(&printer
->comment
, comment
);
4333 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4335 /* check the required size. */
4336 *needed
+= spoolss_size_printer_info_1(printer
);
4338 if (!alloc_buffer_size(buffer
, *needed
)) {
4340 return WERR_INSUFFICIENT_BUFFER
;
4343 /* fill the buffer with the structures */
4344 smb_io_printer_info_1("", buffer
, printer
, 0);
4349 if (*needed
> offered
) {
4351 return WERR_INSUFFICIENT_BUFFER
;
4357 /********************************************************************
4358 enum_all_printers_info_1_network.
4359 *********************************************************************/
4361 static WERROR
enum_all_printers_info_1_network(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4365 DEBUG(4,("enum_all_printers_info_1_network\n"));
4367 /* If we respond to a enum_printers level 1 on our name with flags
4368 set to PRINTER_ENUM_REMOTE with a list of printers then these
4369 printers incorrectly appear in the APW browse list.
4370 Specifically the printers for the server appear at the workgroup
4371 level where all the other servers in the domain are
4372 listed. Windows responds to this call with a
4373 WERR_CAN_NOT_COMPLETE so we should do the same. */
4375 if (name
[0] == '\\' && name
[1] == '\\')
4378 if (is_myname_or_ipaddr(s
))
4379 return WERR_CAN_NOT_COMPLETE
;
4381 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4384 /********************************************************************
4385 * api_spoolss_enumprinters
4387 * called from api_spoolss_enumprinters (see this to understand)
4388 ********************************************************************/
4390 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4394 int n_services
=lp_numservices();
4395 PRINTER_INFO_2
*tp
, *printers
=NULL
;
4396 PRINTER_INFO_2 current_prt
;
4398 for (snum
=0; snum
<n_services
; snum
++) {
4399 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4400 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4402 if (construct_printer_info_2(¤t_prt
, snum
)) {
4403 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
4404 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4405 SAFE_FREE(printers
);
4410 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
4411 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4417 /* check the required size. */
4418 for (i
=0; i
<*returned
; i
++)
4419 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4421 if (!alloc_buffer_size(buffer
, *needed
)) {
4422 for (i
=0; i
<*returned
; i
++) {
4423 free_devmode(printers
[i
].devmode
);
4425 SAFE_FREE(printers
);
4426 return WERR_INSUFFICIENT_BUFFER
;
4429 /* fill the buffer with the structures */
4430 for (i
=0; i
<*returned
; i
++)
4431 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4434 for (i
=0; i
<*returned
; i
++) {
4435 free_devmode(printers
[i
].devmode
);
4437 SAFE_FREE(printers
);
4439 if (*needed
> offered
) {
4441 return WERR_INSUFFICIENT_BUFFER
;
4447 /********************************************************************
4448 * handle enumeration of printers at level 1
4449 ********************************************************************/
4451 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4452 NEW_BUFFER
*buffer
, uint32 offered
,
4453 uint32
*needed
, uint32
*returned
)
4455 /* Not all the flags are equals */
4457 if (flags
& PRINTER_ENUM_LOCAL
)
4458 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4460 if (flags
& PRINTER_ENUM_NAME
)
4461 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4463 if (flags
& PRINTER_ENUM_REMOTE
)
4464 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4466 if (flags
& PRINTER_ENUM_NETWORK
)
4467 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4469 return WERR_OK
; /* NT4sp5 does that */
4472 /********************************************************************
4473 * handle enumeration of printers at level 2
4474 ********************************************************************/
4476 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4477 NEW_BUFFER
*buffer
, uint32 offered
,
4478 uint32
*needed
, uint32
*returned
)
4480 char *s
= servername
;
4482 if (flags
& PRINTER_ENUM_LOCAL
) {
4483 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4486 if (flags
& PRINTER_ENUM_NAME
) {
4487 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4489 if (is_myname_or_ipaddr(s
))
4490 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4492 return WERR_INVALID_NAME
;
4495 if (flags
& PRINTER_ENUM_REMOTE
)
4496 return WERR_UNKNOWN_LEVEL
;
4501 /********************************************************************
4502 * handle enumeration of printers at level 5
4503 ********************************************************************/
4505 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4506 NEW_BUFFER
*buffer
, uint32 offered
,
4507 uint32
*needed
, uint32
*returned
)
4509 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4513 /********************************************************************
4514 * api_spoolss_enumprinters
4516 * called from api_spoolss_enumprinters (see this to understand)
4517 ********************************************************************/
4519 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4521 uint32 flags
= q_u
->flags
;
4522 UNISTR2
*servername
= &q_u
->servername
;
4523 uint32 level
= q_u
->level
;
4524 NEW_BUFFER
*buffer
= NULL
;
4525 uint32 offered
= q_u
->offered
;
4526 uint32
*needed
= &r_u
->needed
;
4527 uint32
*returned
= &r_u
->returned
;
4531 /* that's an [in out] buffer */
4532 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4533 buffer
= r_u
->buffer
;
4535 DEBUG(4,("_spoolss_enumprinters\n"));
4542 * flags==PRINTER_ENUM_NAME
4543 * if name=="" then enumerates all printers
4544 * if name!="" then enumerate the printer
4545 * flags==PRINTER_ENUM_REMOTE
4546 * name is NULL, enumerate printers
4547 * Level 2: name!="" enumerates printers, name can't be NULL
4548 * Level 3: doesn't exist
4549 * Level 4: does a local registry lookup
4550 * Level 5: same as Level 2
4553 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4558 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4560 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4562 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4567 return WERR_UNKNOWN_LEVEL
;
4570 /****************************************************************************
4571 ****************************************************************************/
4573 static WERROR
getprinter_level_0(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4575 PRINTER_INFO_0
*printer
=NULL
;
4577 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
4580 construct_printer_info_0(printer
, snum
);
4582 /* check the required size. */
4583 *needed
+= spoolss_size_printer_info_0(printer
);
4585 if (!alloc_buffer_size(buffer
, *needed
)) {
4587 return WERR_INSUFFICIENT_BUFFER
;
4590 /* fill the buffer with the structures */
4591 smb_io_printer_info_0("", buffer
, printer
, 0);
4596 if (*needed
> offered
) {
4597 return WERR_INSUFFICIENT_BUFFER
;
4603 /****************************************************************************
4604 ****************************************************************************/
4606 static WERROR
getprinter_level_1(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4608 PRINTER_INFO_1
*printer
=NULL
;
4610 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4613 construct_printer_info_1(PRINTER_ENUM_ICON8
, printer
, snum
);
4615 /* check the required size. */
4616 *needed
+= spoolss_size_printer_info_1(printer
);
4618 if (!alloc_buffer_size(buffer
, *needed
)) {
4620 return WERR_INSUFFICIENT_BUFFER
;
4623 /* fill the buffer with the structures */
4624 smb_io_printer_info_1("", buffer
, printer
, 0);
4629 if (*needed
> offered
) {
4630 return WERR_INSUFFICIENT_BUFFER
;
4636 /****************************************************************************
4637 ****************************************************************************/
4639 static WERROR
getprinter_level_2(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4641 PRINTER_INFO_2
*printer
=NULL
;
4643 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
4646 construct_printer_info_2(printer
, snum
);
4648 /* check the required size. */
4649 *needed
+= spoolss_size_printer_info_2(printer
);
4651 if (!alloc_buffer_size(buffer
, *needed
)) {
4652 free_printer_info_2(printer
);
4653 return WERR_INSUFFICIENT_BUFFER
;
4656 /* fill the buffer with the structures */
4657 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
4658 free_printer_info_2(printer
);
4663 free_printer_info_2(printer
);
4665 if (*needed
> offered
) {
4666 return WERR_INSUFFICIENT_BUFFER
;
4672 /****************************************************************************
4673 ****************************************************************************/
4675 static WERROR
getprinter_level_3(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4677 PRINTER_INFO_3
*printer
=NULL
;
4679 if (!construct_printer_info_3(&printer
, snum
))
4682 /* check the required size. */
4683 *needed
+= spoolss_size_printer_info_3(printer
);
4685 if (!alloc_buffer_size(buffer
, *needed
)) {
4686 free_printer_info_3(printer
);
4687 return WERR_INSUFFICIENT_BUFFER
;
4690 /* fill the buffer with the structures */
4691 smb_io_printer_info_3("", buffer
, printer
, 0);
4694 free_printer_info_3(printer
);
4696 if (*needed
> offered
) {
4697 return WERR_INSUFFICIENT_BUFFER
;
4703 /****************************************************************************
4704 ****************************************************************************/
4706 static WERROR
getprinter_level_4(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4708 PRINTER_INFO_4
*printer
=NULL
;
4710 if((printer
=(PRINTER_INFO_4
*)malloc(sizeof(PRINTER_INFO_4
)))==NULL
)
4713 if (!construct_printer_info_4(printer
, snum
))
4716 /* check the required size. */
4717 *needed
+= spoolss_size_printer_info_4(printer
);
4719 if (!alloc_buffer_size(buffer
, *needed
)) {
4720 free_printer_info_4(printer
);
4721 return WERR_INSUFFICIENT_BUFFER
;
4724 /* fill the buffer with the structures */
4725 smb_io_printer_info_4("", buffer
, printer
, 0);
4728 free_printer_info_4(printer
);
4730 if (*needed
> offered
) {
4731 return WERR_INSUFFICIENT_BUFFER
;
4737 /****************************************************************************
4738 ****************************************************************************/
4740 static WERROR
getprinter_level_5(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4742 PRINTER_INFO_5
*printer
=NULL
;
4744 if((printer
=(PRINTER_INFO_5
*)malloc(sizeof(PRINTER_INFO_5
)))==NULL
)
4747 if (!construct_printer_info_5(printer
, snum
))
4750 /* check the required size. */
4751 *needed
+= spoolss_size_printer_info_5(printer
);
4753 if (!alloc_buffer_size(buffer
, *needed
)) {
4754 free_printer_info_5(printer
);
4755 return WERR_INSUFFICIENT_BUFFER
;
4758 /* fill the buffer with the structures */
4759 smb_io_printer_info_5("", buffer
, printer
, 0);
4762 free_printer_info_5(printer
);
4764 if (*needed
> offered
) {
4765 return WERR_INSUFFICIENT_BUFFER
;
4771 static WERROR
getprinter_level_7(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4773 PRINTER_INFO_7
*printer
=NULL
;
4775 if((printer
=(PRINTER_INFO_7
*)malloc(sizeof(PRINTER_INFO_7
)))==NULL
)
4778 if (!construct_printer_info_7(printer
, snum
))
4781 /* check the required size. */
4782 *needed
+= spoolss_size_printer_info_7(printer
);
4784 if (!alloc_buffer_size(buffer
, *needed
)) {
4785 free_printer_info_7(printer
);
4786 return WERR_INSUFFICIENT_BUFFER
;
4789 /* fill the buffer with the structures */
4790 smb_io_printer_info_7("", buffer
, printer
, 0);
4793 free_printer_info_7(printer
);
4795 if (*needed
> offered
) {
4796 return WERR_INSUFFICIENT_BUFFER
;
4802 /****************************************************************************
4803 ****************************************************************************/
4805 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
4807 POLICY_HND
*handle
= &q_u
->handle
;
4808 uint32 level
= q_u
->level
;
4809 NEW_BUFFER
*buffer
= NULL
;
4810 uint32 offered
= q_u
->offered
;
4811 uint32
*needed
= &r_u
->needed
;
4815 /* that's an [in out] buffer */
4816 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4817 buffer
= r_u
->buffer
;
4821 if (!get_printer_snum(p
, handle
, &snum
))
4826 return getprinter_level_0(snum
, buffer
, offered
, needed
);
4828 return getprinter_level_1(snum
, buffer
, offered
, needed
);
4830 return getprinter_level_2(snum
, buffer
, offered
, needed
);
4832 return getprinter_level_3(snum
, buffer
, offered
, needed
);
4834 return getprinter_level_4(snum
, buffer
, offered
, needed
);
4836 return getprinter_level_5(snum
, buffer
, offered
, needed
);
4838 return getprinter_level_7(snum
, buffer
, offered
, needed
);
4840 return WERR_UNKNOWN_LEVEL
;
4843 /********************************************************************
4844 * fill a DRIVER_INFO_1 struct
4845 ********************************************************************/
4847 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
4849 init_unistr( &info
->name
, driver
.info_3
->name
);
4852 /********************************************************************
4853 * construct_printer_driver_info_1
4854 ********************************************************************/
4856 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4858 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4859 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4861 ZERO_STRUCT(driver
);
4863 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4864 return WERR_INVALID_PRINTER_NAME
;
4866 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4867 return WERR_UNKNOWN_PRINTER_DRIVER
;
4869 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
4871 free_a_printer(&printer
,2);
4876 /********************************************************************
4877 * construct_printer_driver_info_2
4878 * fill a printer_info_2 struct
4879 ********************************************************************/
4881 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4885 info
->version
=driver
.info_3
->cversion
;
4887 init_unistr( &info
->name
, driver
.info_3
->name
);
4888 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4891 if (strlen(driver
.info_3
->driverpath
)) {
4892 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4893 init_unistr( &info
->driverpath
, temp
);
4895 init_unistr( &info
->driverpath
, "" );
4897 if (strlen(driver
.info_3
->datafile
)) {
4898 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4899 init_unistr( &info
->datafile
, temp
);
4901 init_unistr( &info
->datafile
, "" );
4903 if (strlen(driver
.info_3
->configfile
)) {
4904 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4905 init_unistr( &info
->configfile
, temp
);
4907 init_unistr( &info
->configfile
, "" );
4910 /********************************************************************
4911 * construct_printer_driver_info_2
4912 * fill a printer_info_2 struct
4913 ********************************************************************/
4915 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4917 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4918 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4920 ZERO_STRUCT(printer
);
4921 ZERO_STRUCT(driver
);
4923 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4924 return WERR_INVALID_PRINTER_NAME
;
4926 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4927 return WERR_UNKNOWN_PRINTER_DRIVER
;
4929 fill_printer_driver_info_2(info
, driver
, servername
);
4931 free_a_printer(&printer
,2);
4936 /********************************************************************
4937 * copy a strings array and convert to UNICODE
4939 * convert an array of ascii string to a UNICODE string
4940 ********************************************************************/
4942 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
4950 DEBUG(6,("init_unistr_array\n"));
4961 v
= ""; /* hack to handle null lists */
4964 /* hack to allow this to be used in places other than when generating
4965 the list of dependent files */
4968 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
4972 DEBUGADD(6,("%d:%s:%d\n", i
, line
, strlen(line
)));
4974 /* add one extra unit16 for the second terminating NULL */
4976 if ( (tuary
=Realloc(*uni_array
, (j
+1+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
4977 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4985 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
4990 /* special case for ""; we need to add both NULL's here */
4992 (*uni_array
)[j
++]=0x0000;
4993 (*uni_array
)[j
]=0x0000;
4996 DEBUGADD(6,("last one:done\n"));
4998 /* return size of array in uint16's */
5003 /********************************************************************
5004 * construct_printer_info_3
5005 * fill a printer_info_3 struct
5006 ********************************************************************/
5008 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5014 info
->version
=driver
.info_3
->cversion
;
5016 init_unistr( &info
->name
, driver
.info_3
->name
);
5017 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5019 if (strlen(driver
.info_3
->driverpath
)) {
5020 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5021 init_unistr( &info
->driverpath
, temp
);
5023 init_unistr( &info
->driverpath
, "" );
5025 if (strlen(driver
.info_3
->datafile
)) {
5026 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5027 init_unistr( &info
->datafile
, temp
);
5029 init_unistr( &info
->datafile
, "" );
5031 if (strlen(driver
.info_3
->configfile
)) {
5032 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5033 init_unistr( &info
->configfile
, temp
);
5035 init_unistr( &info
->configfile
, "" );
5037 if (strlen(driver
.info_3
->helpfile
)) {
5038 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5039 init_unistr( &info
->helpfile
, temp
);
5041 init_unistr( &info
->helpfile
, "" );
5043 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5044 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5046 info
->dependentfiles
=NULL
;
5047 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5050 /********************************************************************
5051 * construct_printer_info_3
5052 * fill a printer_info_3 struct
5053 ********************************************************************/
5055 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5057 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5058 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5060 ZERO_STRUCT(driver
);
5062 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
5063 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5064 if (!W_ERROR_IS_OK(status
))
5065 return WERR_INVALID_PRINTER_NAME
;
5067 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5068 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5073 * I put this code in during testing. Helpful when commenting out the
5074 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5075 * as win2k always queries the driver using an infor level of 6.
5076 * I've left it in (but ifdef'd out) because I'll probably
5077 * use it in experimentation again in the future. --jerry 22/01/2002
5080 if (!W_ERROR_IS_OK(status
)) {
5082 * Is this a W2k client ?
5085 /* Yes - try again with a WinNT driver. */
5087 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5088 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5092 if (!W_ERROR_IS_OK(status
)) {
5093 free_a_printer(&printer
,2);
5094 return WERR_UNKNOWN_PRINTER_DRIVER
;
5102 fill_printer_driver_info_3(info
, driver
, servername
);
5104 free_a_printer(&printer
,2);
5109 /********************************************************************
5110 * construct_printer_info_6
5111 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5112 ********************************************************************/
5114 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5120 memset(&nullstr
, '\0', sizeof(fstring
));
5122 info
->version
=driver
.info_3
->cversion
;
5124 init_unistr( &info
->name
, driver
.info_3
->name
);
5125 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5127 if (strlen(driver
.info_3
->driverpath
)) {
5128 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5129 init_unistr( &info
->driverpath
, temp
);
5131 init_unistr( &info
->driverpath
, "" );
5133 if (strlen(driver
.info_3
->datafile
)) {
5134 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5135 init_unistr( &info
->datafile
, temp
);
5137 init_unistr( &info
->datafile
, "" );
5139 if (strlen(driver
.info_3
->configfile
)) {
5140 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5141 init_unistr( &info
->configfile
, temp
);
5143 init_unistr( &info
->configfile
, "" );
5145 if (strlen(driver
.info_3
->helpfile
)) {
5146 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5147 init_unistr( &info
->helpfile
, temp
);
5149 init_unistr( &info
->helpfile
, "" );
5151 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5152 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5154 info
->dependentfiles
= NULL
;
5155 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5157 info
->previousdrivernames
=NULL
;
5158 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5160 info
->driver_date
.low
=0;
5161 info
->driver_date
.high
=0;
5164 info
->driver_version_low
=0;
5165 info
->driver_version_high
=0;
5167 init_unistr( &info
->mfgname
, "");
5168 init_unistr( &info
->oem_url
, "");
5169 init_unistr( &info
->hardware_id
, "");
5170 init_unistr( &info
->provider
, "");
5173 /********************************************************************
5174 * construct_printer_info_6
5175 * fill a printer_info_6 struct
5176 ********************************************************************/
5178 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5179 fstring servername
, fstring architecture
, uint32 version
)
5181 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5182 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5185 ZERO_STRUCT(driver
);
5187 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
5189 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5191 if (!W_ERROR_IS_OK(status
))
5192 return WERR_INVALID_PRINTER_NAME
;
5194 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5196 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5198 if (!W_ERROR_IS_OK(status
))
5201 * Is this a W2k client ?
5205 free_a_printer(&printer
,2);
5206 return WERR_UNKNOWN_PRINTER_DRIVER
;
5209 /* Yes - try again with a WinNT driver. */
5211 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5212 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5213 if (!W_ERROR_IS_OK(status
)) {
5214 free_a_printer(&printer
,2);
5215 return WERR_UNKNOWN_PRINTER_DRIVER
;
5219 fill_printer_driver_info_6(info
, driver
, servername
);
5221 free_a_printer(&printer
,2);
5222 free_a_printer_driver(driver
, 3);
5227 /****************************************************************************
5228 ****************************************************************************/
5230 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5232 SAFE_FREE(info
->dependentfiles
);
5235 /****************************************************************************
5236 ****************************************************************************/
5238 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5240 SAFE_FREE(info
->dependentfiles
);
5244 /****************************************************************************
5245 ****************************************************************************/
5247 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5249 DRIVER_INFO_1
*info
=NULL
;
5252 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
5255 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5256 if (!W_ERROR_IS_OK(status
)) {
5261 /* check the required size. */
5262 *needed
+= spoolss_size_printer_driver_info_1(info
);
5264 if (!alloc_buffer_size(buffer
, *needed
)) {
5266 return WERR_INSUFFICIENT_BUFFER
;
5269 /* fill the buffer with the structures */
5270 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5275 if (*needed
> offered
)
5276 return WERR_INSUFFICIENT_BUFFER
;
5281 /****************************************************************************
5282 ****************************************************************************/
5284 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5286 DRIVER_INFO_2
*info
=NULL
;
5289 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
5292 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5293 if (!W_ERROR_IS_OK(status
)) {
5298 /* check the required size. */
5299 *needed
+= spoolss_size_printer_driver_info_2(info
);
5301 if (!alloc_buffer_size(buffer
, *needed
)) {
5303 return WERR_INSUFFICIENT_BUFFER
;
5306 /* fill the buffer with the structures */
5307 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5312 if (*needed
> offered
)
5313 return WERR_INSUFFICIENT_BUFFER
;
5318 /****************************************************************************
5319 ****************************************************************************/
5321 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5328 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5329 if (!W_ERROR_IS_OK(status
)) {
5333 /* check the required size. */
5334 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5336 if (!alloc_buffer_size(buffer
, *needed
)) {
5337 free_printer_driver_info_3(&info
);
5338 return WERR_INSUFFICIENT_BUFFER
;
5341 /* fill the buffer with the structures */
5342 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5344 free_printer_driver_info_3(&info
);
5346 if (*needed
> offered
)
5347 return WERR_INSUFFICIENT_BUFFER
;
5352 /****************************************************************************
5353 ****************************************************************************/
5355 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5362 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5363 if (!W_ERROR_IS_OK(status
)) {
5367 /* check the required size. */
5368 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5370 if (!alloc_buffer_size(buffer
, *needed
)) {
5371 free_printer_driver_info_6(&info
);
5372 return WERR_INSUFFICIENT_BUFFER
;
5375 /* fill the buffer with the structures */
5376 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5378 free_printer_driver_info_6(&info
);
5380 if (*needed
> offered
)
5381 return WERR_INSUFFICIENT_BUFFER
;
5386 /****************************************************************************
5387 ****************************************************************************/
5389 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5391 POLICY_HND
*handle
= &q_u
->handle
;
5392 UNISTR2
*uni_arch
= &q_u
->architecture
;
5393 uint32 level
= q_u
->level
;
5394 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5395 NEW_BUFFER
*buffer
= NULL
;
5396 uint32 offered
= q_u
->offered
;
5397 uint32
*needed
= &r_u
->needed
;
5398 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5399 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5402 fstring architecture
;
5405 /* that's an [in out] buffer */
5406 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5407 buffer
= r_u
->buffer
;
5409 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5412 *servermajorversion
= 0;
5413 *serverminorversion
= 0;
5415 fstrcpy(servername
, get_called_name());
5416 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5418 if (!get_printer_snum(p
, handle
, &snum
))
5423 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5425 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5427 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5429 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5432 return WERR_UNKNOWN_LEVEL
;
5435 /****************************************************************************
5436 ****************************************************************************/
5438 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5440 POLICY_HND
*handle
= &q_u
->handle
;
5442 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5445 DEBUG(3,("Error in startpageprinter printer handle\n"));
5449 Printer
->page_started
=True
;
5453 /****************************************************************************
5454 ****************************************************************************/
5456 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5458 POLICY_HND
*handle
= &q_u
->handle
;
5461 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5464 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5468 if (!get_printer_snum(p
, handle
, &snum
))
5471 Printer
->page_started
=False
;
5472 print_job_endpage(snum
, Printer
->jobid
);
5477 /********************************************************************
5478 * api_spoolss_getprinter
5479 * called from the spoolss dispatcher
5481 ********************************************************************/
5483 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5485 POLICY_HND
*handle
= &q_u
->handle
;
5486 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5487 uint32
*jobid
= &r_u
->jobid
;
5489 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5493 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5494 struct current_user user
;
5497 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5501 get_current_user(&user
, p
);
5504 * a nice thing with NT is it doesn't listen to what you tell it.
5505 * when asked to send _only_ RAW datas, it tries to send datas
5508 * So I add checks like in NT Server ...
5511 if (info_1
->p_datatype
!= 0) {
5512 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5513 if (strcmp(datatype
, "RAW") != 0) {
5515 return WERR_INVALID_DATATYPE
;
5519 /* get the share number of the printer */
5520 if (!get_printer_snum(p
, handle
, &snum
)) {
5524 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5526 Printer
->jobid
= print_job_start(&user
, snum
, jobname
, Printer
->nt_devmode
);
5528 /* An error occured in print_job_start() so return an appropriate
5531 if (Printer
->jobid
== -1) {
5532 return map_werror_from_unix(errno
);
5535 Printer
->document_started
=True
;
5536 (*jobid
) = Printer
->jobid
;
5541 /********************************************************************
5542 * api_spoolss_getprinter
5543 * called from the spoolss dispatcher
5545 ********************************************************************/
5547 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5549 POLICY_HND
*handle
= &q_u
->handle
;
5551 return _spoolss_enddocprinter_internal(p
, handle
);
5554 /****************************************************************************
5555 ****************************************************************************/
5557 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5559 POLICY_HND
*handle
= &q_u
->handle
;
5560 uint32 buffer_size
= q_u
->buffer_size
;
5561 uint8
*buffer
= q_u
->buffer
;
5562 uint32
*buffer_written
= &q_u
->buffer_size2
;
5564 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5567 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5568 r_u
->buffer_written
= q_u
->buffer_size2
;
5572 if (!get_printer_snum(p
, handle
, &snum
))
5575 (*buffer_written
) = print_job_write(snum
, Printer
->jobid
, (char *)buffer
, buffer_size
);
5576 if (*buffer_written
== -1) {
5577 r_u
->buffer_written
= 0;
5578 if (errno
== ENOSPC
)
5579 return WERR_NO_SPOOL_SPACE
;
5581 return WERR_ACCESS_DENIED
;
5584 r_u
->buffer_written
= q_u
->buffer_size2
;
5589 /********************************************************************
5590 * api_spoolss_getprinter
5591 * called from the spoolss dispatcher
5593 ********************************************************************/
5595 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5598 struct current_user user
;
5600 WERROR errcode
= WERR_BADFUNC
;
5601 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5603 get_current_user(&user
, p
);
5606 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5610 if (!get_printer_snum(p
, handle
, &snum
))
5614 case PRINTER_CONTROL_PAUSE
:
5615 if (print_queue_pause(&user
, snum
, &errcode
)) {
5619 case PRINTER_CONTROL_RESUME
:
5620 case PRINTER_CONTROL_UNPAUSE
:
5621 if (print_queue_resume(&user
, snum
, &errcode
)) {
5625 case PRINTER_CONTROL_PURGE
:
5626 if (print_queue_purge(&user
, snum
, &errcode
)) {
5631 return WERR_UNKNOWN_LEVEL
;
5637 /********************************************************************
5638 * api_spoolss_abortprinter
5639 * From MSDN: "Deletes printer's spool file if printer is configured
5641 ********************************************************************/
5643 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5645 POLICY_HND
*handle
= &q_u
->handle
;
5646 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5648 struct current_user user
;
5649 WERROR errcode
= WERR_OK
;
5652 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5656 if (!get_printer_snum(p
, handle
, &snum
))
5659 get_current_user( &user
, p
);
5661 print_job_delete( &user
, snum
, Printer
->jobid
, &errcode
);
5666 /********************************************************************
5667 * called by spoolss_api_setprinter
5668 * when updating a printer description
5669 ********************************************************************/
5671 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5672 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5673 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5675 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5676 struct current_user user
;
5680 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5682 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5683 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5684 OUR_HANDLE(handle
)));
5686 result
= WERR_BADFID
;
5690 /* NT seems to like setting the security descriptor even though
5691 nothing may have actually changed. This causes annoying
5692 dialog boxes when the user doesn't have permission to change
5693 the security descriptor. */
5695 nt_printing_getsec(p
->mem_ctx
, Printer
->dev
.handlename
, &old_secdesc_ctr
);
5697 if (DEBUGLEVEL
>= 10) {
5701 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5702 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5703 PRINTERNAME(snum
), the_acl
->num_aces
));
5705 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5708 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5710 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5711 the_acl
->ace
[i
].info
.mask
));
5714 the_acl
= secdesc_ctr
->sec
->dacl
;
5717 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5718 PRINTERNAME(snum
), the_acl
->num_aces
));
5720 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5723 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5725 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5726 the_acl
->ace
[i
].info
.mask
));
5729 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5733 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5735 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5740 /* Work out which user is performing the operation */
5742 get_current_user(&user
, p
);
5744 /* Check the user has permissions to change the security
5745 descriptor. By experimentation with two NT machines, the user
5746 requires Full Access to the printer to change security
5749 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5750 result
= WERR_ACCESS_DENIED
;
5754 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
5761 /********************************************************************
5762 Do Samba sanity checks on a printer info struct.
5763 this has changed purpose: it now "canonicalises" printer
5764 info from a client rather than just checking it is correct
5765 ********************************************************************/
5767 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5769 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5770 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5772 /* we force some elements to "correct" values */
5773 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", get_called_name());
5774 fstrcpy(info
->sharename
, lp_servicename(snum
));
5775 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5776 get_called_name(), info
->sharename
);
5777 info
->attributes
= PRINTER_ATTRIBUTE_SAMBA
;
5783 /****************************************************************************
5784 ****************************************************************************/
5786 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
5788 extern userdom_struct current_user_info
;
5789 char *cmd
= lp_addprinter_cmd();
5795 fstring remote_machine
= "%m";
5797 standard_sub_basic(current_user_info
.smb_name
, remote_machine
,sizeof(remote_machine
));
5799 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5800 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5801 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5802 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
5804 DEBUG(10,("Running [%s]\n", command
));
5805 ret
= smbrun(command
, &fd
);
5806 DEBUGADD(10,("returned [%d]\n", ret
));
5815 /* Get lines and convert them back to dos-codepage */
5816 qlines
= fd_lines_load(fd
, &numlines
);
5817 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5821 /* Set the portname to what the script says the portname should be. */
5822 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5823 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5825 /* Send SIGHUP to process group... is there a better way? */
5828 /* reload our services immediately */
5829 reload_services( False
);
5832 file_lines_free(qlines
);
5836 /********************************************************************
5837 * Called by spoolss_api_setprinter
5838 * when updating a printer description.
5839 ********************************************************************/
5841 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
5842 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5843 DEVICEMODE
*devmode
)
5846 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
5847 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5852 DEBUG(8,("update_printer\n"));
5857 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5858 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5859 result
= WERR_UNKNOWN_LEVEL
;
5864 result
= WERR_BADFID
;
5868 if (!get_printer_snum(p
, handle
, &snum
)) {
5869 result
= WERR_BADFID
;
5873 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))) ||
5874 (!W_ERROR_IS_OK(get_a_printer(&old_printer
, 2, lp_servicename(snum
))))) {
5875 result
= WERR_BADFID
;
5879 DEBUGADD(8,("Converting info_2 struct\n"));
5882 * convert_printer_info converts the incoming
5883 * info from the client and overwrites the info
5884 * just read from the tdb in the pointer 'printer'.
5887 if (!convert_printer_info(info
, printer
, level
)) {
5888 result
= WERR_NOMEM
;
5893 /* we have a valid devmode
5894 convert it and link it*/
5896 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5897 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5898 &printer
->info_2
->devmode
)) {
5899 result
= WERR_NOMEM
;
5904 * make sure we actually reload the services after
5905 * this as smb.conf could have a new section in it
5906 * .... shouldn't .... but could
5908 reload_services(False
);
5911 /* Do sanity check on the requested changes for Samba */
5913 if (!check_printer_ok(printer
->info_2
, snum
)) {
5914 result
= WERR_INVALID_PARAM
;
5918 /* Check calling user has permission to update printer description */
5920 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5921 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5922 result
= WERR_ACCESS_DENIED
;
5926 /* Call addprinter hook */
5927 /* Check changes to see if this is really needed */
5929 if ( *lp_addprinter_cmd()
5930 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
5931 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
5932 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
5933 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
5935 if ( !add_printer_hook(printer
) ) {
5936 result
= WERR_ACCESS_DENIED
;
5941 * make sure we actually reload the services after
5942 * this as smb.conf could have a new section in it
5943 * .... shouldn't .... but could
5945 reload_services(False
);
5949 * When a *new* driver is bound to a printer, the drivername is used to
5950 * lookup previously saved driver initialization info, which is then
5951 * bound to the printer, simulating what happens in the Windows arch.
5953 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
5955 if (!set_driver_init(printer
, 2))
5957 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5958 printer
->info_2
->drivername
));
5961 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5962 printer
->info_2
->drivername
));
5964 notify_printer_driver(snum
, printer
->info_2
->drivername
);
5967 /* Update printer info */
5968 result
= mod_a_printer(*printer
, 2);
5971 * flag which changes actually occured. This is a small subset of
5972 * all the possible changes. We also have to update things in the
5976 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
5977 init_unistr2( &buffer
, printer
->info_2
->comment
, strlen(printer
->info_2
->comment
)+1 );
5978 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
5979 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
5981 notify_printer_comment(snum
, printer
->info_2
->comment
);
5984 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
5985 init_unistr2( &buffer
, printer
->info_2
->sharename
, strlen(printer
->info_2
->sharename
)+1 );
5986 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
5987 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
5988 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
5989 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
5991 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
5994 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
5995 init_unistr2( &buffer
, printer
->info_2
->portname
, strlen(printer
->info_2
->portname
)+1 );
5996 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
5997 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
5999 notify_printer_port(snum
, printer
->info_2
->portname
);
6002 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6003 init_unistr2( &buffer
, printer
->info_2
->location
, strlen(printer
->info_2
->location
)+1 );
6004 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6005 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6007 notify_printer_location(snum
, printer
->info_2
->location
);
6010 /* here we need to update some more DsSpooler keys */
6011 /* uNCName, serverName, shortServerName */
6013 init_unistr2( &buffer
, global_myname(), strlen(global_myname())+1 );
6014 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6015 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6016 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6017 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6019 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6020 global_myname(), printer
->info_2
->sharename
);
6021 init_unistr2( &buffer
, asc_buffer
, strlen(asc_buffer
)+1 );
6022 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6023 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6026 free_a_printer(&printer
, 2);
6027 free_a_printer(&old_printer
, 2);
6033 /****************************************************************************
6034 ****************************************************************************/
6035 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
6036 const SPOOL_PRINTER_INFO_LEVEL
*info
)
6039 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
6041 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6044 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6051 if (!get_printer_snum(p
, handle
, &snum
))
6054 nt_printer_publish(snum
, info7
->action
);
6058 return WERR_UNKNOWN_LEVEL
;
6061 /****************************************************************************
6062 ****************************************************************************/
6064 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
6066 POLICY_HND
*handle
= &q_u
->handle
;
6067 uint32 level
= q_u
->level
;
6068 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6069 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
6070 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
6071 uint32 command
= q_u
->command
;
6073 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6076 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6080 /* check the level */
6083 return control_printer(handle
, command
, p
);
6085 return update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6087 return update_printer_sec(handle
, level
, info
, p
,
6090 return publish_or_unpublish_printer(p
, handle
, info
);
6092 return WERR_UNKNOWN_LEVEL
;
6096 /****************************************************************************
6097 ****************************************************************************/
6099 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6101 POLICY_HND
*handle
= &q_u
->handle
;
6102 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6105 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6109 if (Printer
->notify
.client_connected
==True
) {
6112 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
6114 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
6115 !get_printer_snum(p
, handle
, &snum
) )
6118 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6121 Printer
->notify
.flags
=0;
6122 Printer
->notify
.options
=0;
6123 Printer
->notify
.localmachine
[0]='\0';
6124 Printer
->notify
.printerlocal
=0;
6125 if (Printer
->notify
.option
)
6126 free_spool_notify_option(&Printer
->notify
.option
);
6127 Printer
->notify
.client_connected
=False
;
6132 /****************************************************************************
6133 ****************************************************************************/
6135 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6137 /* that's an [in out] buffer (despite appearences to the contrary) */
6138 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6141 return WERR_INVALID_PARAM
; /* this is what a NT server
6142 returns for AddJob. AddJob
6143 must fail on non-local
6147 /****************************************************************************
6148 ****************************************************************************/
6150 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
6151 int position
, int snum
)
6157 t
=gmtime(&queue
->time
);
6158 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
6160 job_info
->jobid
=queue
->job
;
6161 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6162 init_unistr(&job_info
->machinename
, temp_name
);
6163 init_unistr(&job_info
->username
, queue
->fs_user
);
6164 init_unistr(&job_info
->document
, queue
->fs_file
);
6165 init_unistr(&job_info
->datatype
, "RAW");
6166 init_unistr(&job_info
->text_status
, "");
6167 job_info
->status
=nt_printj_status(queue
->status
);
6168 job_info
->priority
=queue
->priority
;
6169 job_info
->position
=position
;
6170 job_info
->totalpages
=queue
->page_count
;
6171 job_info
->pagesprinted
=0;
6173 make_systemtime(&job_info
->submitted
, t
);
6176 /****************************************************************************
6177 ****************************************************************************/
6179 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
6180 int position
, int snum
,
6181 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6182 DEVICEMODE
*devmode
)
6187 t
=gmtime(&queue
->time
);
6188 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
6190 job_info
->jobid
=queue
->job
;
6192 init_unistr(&job_info
->printername
, ntprinter
->info_2
->printername
);
6194 init_unistr(&job_info
->machinename
, temp_name
);
6195 init_unistr(&job_info
->username
, queue
->fs_user
);
6196 init_unistr(&job_info
->document
, queue
->fs_file
);
6197 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6198 init_unistr(&job_info
->datatype
, "RAW");
6199 init_unistr(&job_info
->printprocessor
, "winprint");
6200 init_unistr(&job_info
->parameters
, "");
6201 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6202 init_unistr(&job_info
->text_status
, "");
6204 /* and here the security descriptor */
6206 job_info
->status
=nt_printj_status(queue
->status
);
6207 job_info
->priority
=queue
->priority
;
6208 job_info
->position
=position
;
6209 job_info
->starttime
=0;
6210 job_info
->untiltime
=0;
6211 job_info
->totalpages
=queue
->page_count
;
6212 job_info
->size
=queue
->size
;
6213 make_systemtime(&(job_info
->submitted
), t
);
6214 job_info
->timeelapsed
=0;
6215 job_info
->pagesprinted
=0;
6217 job_info
->devmode
= devmode
;
6222 /****************************************************************************
6223 Enumjobs at level 1.
6224 ****************************************************************************/
6226 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
6227 NEW_BUFFER
*buffer
, uint32 offered
,
6228 uint32
*needed
, uint32
*returned
)
6233 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
6240 for (i
=0; i
<*returned
; i
++)
6241 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
6245 /* check the required size. */
6246 for (i
=0; i
<*returned
; i
++)
6247 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6249 if (!alloc_buffer_size(buffer
, *needed
)) {
6251 return WERR_INSUFFICIENT_BUFFER
;
6254 /* fill the buffer with the structures */
6255 for (i
=0; i
<*returned
; i
++)
6256 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6261 if (*needed
> offered
) {
6263 return WERR_INSUFFICIENT_BUFFER
;
6269 /****************************************************************************
6270 Enumjobs at level 2.
6271 ****************************************************************************/
6273 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
6274 NEW_BUFFER
*buffer
, uint32 offered
,
6275 uint32
*needed
, uint32
*returned
)
6277 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6278 JOB_INFO_2
*info
= NULL
;
6281 DEVICEMODE
*devmode
= NULL
;
6283 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
6286 result
= WERR_NOMEM
;
6290 result
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
6291 if (!W_ERROR_IS_OK(result
)) {
6296 /* this should not be a failure condition if the devmode is NULL */
6298 devmode
= construct_dev_mode(snum
);
6300 for (i
=0; i
<*returned
; i
++)
6301 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
,
6304 free_a_printer(&ntprinter
, 2);
6307 /* check the required size. */
6308 for (i
=0; i
<*returned
; i
++)
6309 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6311 if (*needed
> offered
) {
6313 result
= WERR_INSUFFICIENT_BUFFER
;
6317 if (!alloc_buffer_size(buffer
, *needed
)) {
6319 result
= WERR_INSUFFICIENT_BUFFER
;
6323 /* fill the buffer with the structures */
6324 for (i
=0; i
<*returned
; i
++)
6325 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6330 free_a_printer(&ntprinter
, 2);
6331 free_devmode(devmode
);
6339 /****************************************************************************
6341 ****************************************************************************/
6343 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6345 POLICY_HND
*handle
= &q_u
->handle
;
6346 uint32 level
= q_u
->level
;
6347 NEW_BUFFER
*buffer
= NULL
;
6348 uint32 offered
= q_u
->offered
;
6349 uint32
*needed
= &r_u
->needed
;
6350 uint32
*returned
= &r_u
->returned
;
6353 print_status_struct prt_status
;
6354 print_queue_struct
*queue
=NULL
;
6356 /* that's an [in out] buffer */
6357 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6358 buffer
= r_u
->buffer
;
6360 DEBUG(4,("_spoolss_enumjobs\n"));
6365 if (!get_printer_snum(p
, handle
, &snum
))
6368 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6369 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6371 if (*returned
== 0) {
6378 return enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
6380 return enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
6384 return WERR_UNKNOWN_LEVEL
;
6388 /****************************************************************************
6389 ****************************************************************************/
6391 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6396 /****************************************************************************
6397 ****************************************************************************/
6399 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6401 POLICY_HND
*handle
= &q_u
->handle
;
6402 uint32 jobid
= q_u
->jobid
;
6403 uint32 command
= q_u
->command
;
6405 struct current_user user
;
6407 WERROR errcode
= WERR_BADFUNC
;
6409 if (!get_printer_snum(p
, handle
, &snum
)) {
6413 if (!print_job_exists(snum
, jobid
)) {
6414 return WERR_INVALID_PRINTER_NAME
;
6417 get_current_user(&user
, p
);
6420 case JOB_CONTROL_CANCEL
:
6421 case JOB_CONTROL_DELETE
:
6422 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
6426 case JOB_CONTROL_PAUSE
:
6427 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
6431 case JOB_CONTROL_RESTART
:
6432 case JOB_CONTROL_RESUME
:
6433 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
6438 return WERR_UNKNOWN_LEVEL
;
6444 /****************************************************************************
6445 Enumerates all printer drivers at level 1.
6446 ****************************************************************************/
6448 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6453 fstring
*list
= NULL
;
6455 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6456 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
6460 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6462 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6463 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6469 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
6470 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6471 SAFE_FREE(driver_info_1
);
6475 else driver_info_1
= tdi1
;
6478 for (i
=0; i
<ndrivers
; i
++) {
6480 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6481 ZERO_STRUCT(driver
);
6482 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6483 architecture
, version
);
6484 if (!W_ERROR_IS_OK(status
)) {
6488 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6489 free_a_printer_driver(driver
, 3);
6492 *returned
+=ndrivers
;
6496 /* check the required size. */
6497 for (i
=0; i
<*returned
; i
++) {
6498 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6499 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6502 if (!alloc_buffer_size(buffer
, *needed
)) {
6503 SAFE_FREE(driver_info_1
);
6504 return WERR_INSUFFICIENT_BUFFER
;
6507 /* fill the buffer with the driver structures */
6508 for (i
=0; i
<*returned
; i
++) {
6509 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6510 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6513 SAFE_FREE(driver_info_1
);
6515 if (*needed
> offered
) {
6517 return WERR_INSUFFICIENT_BUFFER
;
6523 /****************************************************************************
6524 Enumerates all printer drivers at level 2.
6525 ****************************************************************************/
6527 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6532 fstring
*list
= NULL
;
6534 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6535 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
6539 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6541 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6542 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6548 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
6549 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6550 SAFE_FREE(driver_info_2
);
6554 else driver_info_2
= tdi2
;
6557 for (i
=0; i
<ndrivers
; i
++) {
6560 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6561 ZERO_STRUCT(driver
);
6562 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6563 architecture
, version
);
6564 if (!W_ERROR_IS_OK(status
)) {
6568 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6569 free_a_printer_driver(driver
, 3);
6572 *returned
+=ndrivers
;
6576 /* check the required size. */
6577 for (i
=0; i
<*returned
; i
++) {
6578 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6579 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6582 if (!alloc_buffer_size(buffer
, *needed
)) {
6583 SAFE_FREE(driver_info_2
);
6584 return WERR_INSUFFICIENT_BUFFER
;
6587 /* fill the buffer with the form structures */
6588 for (i
=0; i
<*returned
; i
++) {
6589 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6590 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6593 SAFE_FREE(driver_info_2
);
6595 if (*needed
> offered
) {
6597 return WERR_INSUFFICIENT_BUFFER
;
6603 /****************************************************************************
6604 Enumerates all printer drivers at level 3.
6605 ****************************************************************************/
6607 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6612 fstring
*list
= NULL
;
6614 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6615 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
6619 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6621 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6622 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6628 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
6629 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6630 SAFE_FREE(driver_info_3
);
6634 else driver_info_3
= tdi3
;
6637 for (i
=0; i
<ndrivers
; i
++) {
6640 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6641 ZERO_STRUCT(driver
);
6642 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6643 architecture
, version
);
6644 if (!W_ERROR_IS_OK(status
)) {
6648 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6649 free_a_printer_driver(driver
, 3);
6652 *returned
+=ndrivers
;
6656 /* check the required size. */
6657 for (i
=0; i
<*returned
; i
++) {
6658 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6659 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6662 if (!alloc_buffer_size(buffer
, *needed
)) {
6663 SAFE_FREE(driver_info_3
);
6664 return WERR_INSUFFICIENT_BUFFER
;
6667 /* fill the buffer with the driver structures */
6668 for (i
=0; i
<*returned
; i
++) {
6669 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6670 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6673 for (i
=0; i
<*returned
; i
++)
6674 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6676 SAFE_FREE(driver_info_3
);
6678 if (*needed
> offered
) {
6680 return WERR_INSUFFICIENT_BUFFER
;
6686 /****************************************************************************
6687 Enumerates all printer drivers.
6688 ****************************************************************************/
6690 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6692 UNISTR2
*environment
= &q_u
->environment
;
6693 uint32 level
= q_u
->level
;
6694 NEW_BUFFER
*buffer
= NULL
;
6695 uint32 offered
= q_u
->offered
;
6696 uint32
*needed
= &r_u
->needed
;
6697 uint32
*returned
= &r_u
->returned
;
6699 fstring
*list
= NULL
;
6701 fstring architecture
;
6703 /* that's an [in out] buffer */
6704 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6705 buffer
= r_u
->buffer
;
6707 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6708 fstrcpy(servername
, get_called_name());
6712 unistr2_to_ascii(architecture
, environment
, sizeof(architecture
)-1);
6716 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
6718 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
6720 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
6724 return WERR_UNKNOWN_LEVEL
;
6728 /****************************************************************************
6729 ****************************************************************************/
6731 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
6733 form
->flag
=list
->flag
;
6734 init_unistr(&form
->name
, list
->name
);
6735 form
->width
=list
->width
;
6736 form
->length
=list
->length
;
6737 form
->left
=list
->left
;
6738 form
->top
=list
->top
;
6739 form
->right
=list
->right
;
6740 form
->bottom
=list
->bottom
;
6743 /****************************************************************************
6744 ****************************************************************************/
6746 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
6748 uint32 level
= q_u
->level
;
6749 NEW_BUFFER
*buffer
= NULL
;
6750 uint32 offered
= q_u
->offered
;
6751 uint32
*needed
= &r_u
->needed
;
6752 uint32
*numofforms
= &r_u
->numofforms
;
6753 uint32 numbuiltinforms
;
6755 nt_forms_struct
*list
=NULL
;
6756 nt_forms_struct
*builtinlist
=NULL
;
6761 /* that's an [in out] buffer */
6762 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6763 buffer
= r_u
->buffer
;
6765 DEBUG(4,("_spoolss_enumforms\n"));
6766 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6767 DEBUGADD(5,("Info level [%d]\n", level
));
6769 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
6770 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
6771 *numofforms
= get_ntforms(&list
);
6772 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
6773 *numofforms
+= numbuiltinforms
;
6775 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
6779 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
6784 /* construct the list of form structures */
6785 for (i
=0; i
<numbuiltinforms
; i
++) {
6786 DEBUGADD(6,("Filling form number [%d]\n",i
));
6787 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
6790 SAFE_FREE(builtinlist
);
6792 for (; i
<*numofforms
; i
++) {
6793 DEBUGADD(6,("Filling form number [%d]\n",i
));
6794 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
6799 /* check the required size. */
6800 for (i
=0; i
<numbuiltinforms
; i
++) {
6801 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6802 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6804 for (; i
<*numofforms
; i
++) {
6805 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6806 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6809 *needed
=buffer_size
;
6811 if (!alloc_buffer_size(buffer
, buffer_size
)){
6813 return WERR_INSUFFICIENT_BUFFER
;
6816 /* fill the buffer with the form structures */
6817 for (i
=0; i
<numbuiltinforms
; i
++) {
6818 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6819 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6821 for (; i
<*numofforms
; i
++) {
6822 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6823 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6828 if (*needed
> offered
) {
6830 return WERR_INSUFFICIENT_BUFFER
;
6837 SAFE_FREE(builtinlist
);
6838 return WERR_UNKNOWN_LEVEL
;
6843 /****************************************************************************
6844 ****************************************************************************/
6846 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
6848 uint32 level
= q_u
->level
;
6849 UNISTR2
*uni_formname
= &q_u
->formname
;
6850 NEW_BUFFER
*buffer
= NULL
;
6851 uint32 offered
= q_u
->offered
;
6852 uint32
*needed
= &r_u
->needed
;
6854 nt_forms_struct
*list
=NULL
;
6855 nt_forms_struct builtin_form
;
6860 int numofforms
=0, i
=0;
6862 /* that's an [in out] buffer */
6863 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6864 buffer
= r_u
->buffer
;
6866 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
6868 DEBUG(4,("_spoolss_getform\n"));
6869 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6870 DEBUGADD(5,("Info level [%d]\n", level
));
6872 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
6873 if (!foundBuiltin
) {
6874 numofforms
= get_ntforms(&list
);
6875 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
6877 if (numofforms
== 0)
6884 fill_form_1(&form_1
, &builtin_form
);
6887 /* Check if the requested name is in the list of form structures */
6888 for (i
=0; i
<numofforms
; i
++) {
6890 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
6892 if (strequal(form_name
, list
[i
].name
)) {
6893 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
6894 fill_form_1(&form_1
, &list
[i
]);
6900 if (i
== numofforms
) {
6904 /* check the required size. */
6906 *needed
=spoolss_size_form_1(&form_1
);
6908 if (!alloc_buffer_size(buffer
, buffer_size
)){
6909 return WERR_INSUFFICIENT_BUFFER
;
6912 if (*needed
> offered
) {
6913 return WERR_INSUFFICIENT_BUFFER
;
6916 /* fill the buffer with the form structures */
6917 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
6918 smb_io_form_1("", buffer
, &form_1
, 0);
6924 return WERR_UNKNOWN_LEVEL
;
6928 /****************************************************************************
6929 ****************************************************************************/
6931 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
6933 init_unistr(&port
->port_name
, name
);
6936 /****************************************************************************
6937 ****************************************************************************/
6939 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
6941 init_unistr(&port
->port_name
, name
);
6942 init_unistr(&port
->monitor_name
, "Local Monitor");
6943 init_unistr(&port
->description
, "Local Port");
6944 #define PORT_TYPE_WRITE 1
6945 port
->port_type
=PORT_TYPE_WRITE
;
6949 /****************************************************************************
6951 ****************************************************************************/
6953 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6955 PORT_INFO_1
*ports
=NULL
;
6958 if (*lp_enumports_cmd()) {
6959 char *cmd
= lp_enumports_cmd();
6966 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
6968 DEBUG(10,("Running [%s]\n", command
));
6969 ret
= smbrun(command
, &fd
);
6970 DEBUG(10,("Returned [%d]\n", ret
));
6974 /* Is this the best error to return here? */
6975 return WERR_ACCESS_DENIED
;
6979 qlines
= fd_lines_load(fd
, &numlines
);
6980 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6984 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
6985 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6986 dos_errstr(WERR_NOMEM
)));
6987 file_lines_free(qlines
);
6991 for (i
=0; i
<numlines
; i
++) {
6992 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6993 fill_port_1(&ports
[i
], qlines
[i
]);
6996 file_lines_free(qlines
);
6999 *returned
= numlines
;
7002 *returned
= 1; /* Sole Samba port returned. */
7004 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
7007 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7009 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7012 /* check the required size. */
7013 for (i
=0; i
<*returned
; i
++) {
7014 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7015 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
7018 if (!alloc_buffer_size(buffer
, *needed
)) {
7020 return WERR_INSUFFICIENT_BUFFER
;
7023 /* fill the buffer with the ports structures */
7024 for (i
=0; i
<*returned
; i
++) {
7025 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7026 smb_io_port_1("", buffer
, &ports
[i
], 0);
7031 if (*needed
> offered
) {
7033 return WERR_INSUFFICIENT_BUFFER
;
7039 /****************************************************************************
7041 ****************************************************************************/
7043 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7045 PORT_INFO_2
*ports
=NULL
;
7048 if (*lp_enumports_cmd()) {
7049 char *cmd
= lp_enumports_cmd();
7058 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
7059 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
7061 path
= lp_lockdir();
7063 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
7064 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
7067 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
7068 ret
= smbrun(command
, &fd
);
7069 DEBUGADD(10,("returned [%d]\n", ret
));
7073 /* Is this the best error to return here? */
7074 return WERR_ACCESS_DENIED
;
7078 qlines
= fd_lines_load(fd
, &numlines
);
7079 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7083 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
7084 file_lines_free(qlines
);
7088 for (i
=0; i
<numlines
; i
++) {
7089 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7090 fill_port_2(&(ports
[i
]), qlines
[i
]);
7093 file_lines_free(qlines
);
7096 *returned
= numlines
;
7102 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
7105 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7107 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7110 /* check the required size. */
7111 for (i
=0; i
<*returned
; i
++) {
7112 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7113 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7116 if (!alloc_buffer_size(buffer
, *needed
)) {
7118 return WERR_INSUFFICIENT_BUFFER
;
7121 /* fill the buffer with the ports structures */
7122 for (i
=0; i
<*returned
; i
++) {
7123 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7124 smb_io_port_2("", buffer
, &ports
[i
], 0);
7129 if (*needed
> offered
) {
7131 return WERR_INSUFFICIENT_BUFFER
;
7137 /****************************************************************************
7139 ****************************************************************************/
7141 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7143 uint32 level
= q_u
->level
;
7144 NEW_BUFFER
*buffer
= NULL
;
7145 uint32 offered
= q_u
->offered
;
7146 uint32
*needed
= &r_u
->needed
;
7147 uint32
*returned
= &r_u
->returned
;
7149 /* that's an [in out] buffer */
7150 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7151 buffer
= r_u
->buffer
;
7153 DEBUG(4,("_spoolss_enumports\n"));
7160 return enumports_level_1(buffer
, offered
, needed
, returned
);
7162 return enumports_level_2(buffer
, offered
, needed
, returned
);
7164 return WERR_UNKNOWN_LEVEL
;
7168 /****************************************************************************
7169 ****************************************************************************/
7171 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7172 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7173 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7174 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7177 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7180 WERROR err
= WERR_OK
;
7182 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
7183 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7187 ZERO_STRUCTP(printer
);
7189 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7190 if (!convert_printer_info(info
, printer
, 2)) {
7191 free_a_printer(&printer
, 2);
7195 /* check to see if the printer already exists */
7197 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7198 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7199 printer
->info_2
->sharename
));
7200 free_a_printer(&printer
, 2);
7201 return WERR_PRINTER_ALREADY_EXISTS
;
7204 if (*lp_addprinter_cmd() ) {
7205 if ( !add_printer_hook(printer
) ) {
7206 free_a_printer(&printer
,2);
7207 return WERR_ACCESS_DENIED
;
7211 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", get_called_name(),
7212 printer
->info_2
->sharename
);
7215 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7216 free_a_printer(&printer
,2);
7217 return WERR_ACCESS_DENIED
;
7220 /* you must be a printer admin to add a new printer */
7221 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7222 free_a_printer(&printer
,2);
7223 return WERR_ACCESS_DENIED
;
7227 * Do sanity check on the requested changes for Samba.
7230 if (!check_printer_ok(printer
->info_2
, snum
)) {
7231 free_a_printer(&printer
,2);
7232 return WERR_INVALID_PARAM
;
7236 * When a printer is created, the drivername bound to the printer is used
7237 * to lookup previously saved driver initialization info, which is then
7238 * bound to the new printer, simulating what happens in the Windows arch.
7243 set_driver_init(printer
, 2);
7247 /* A valid devmode was included, convert and link it
7249 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7251 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7252 &printer
->info_2
->devmode
))
7256 /* write the ASCII on disk */
7257 err
= mod_a_printer(*printer
, 2);
7258 if (!W_ERROR_IS_OK(err
)) {
7259 free_a_printer(&printer
,2);
7263 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7264 /* Handle open failed - remove addition. */
7265 del_a_printer(printer
->info_2
->sharename
);
7266 free_a_printer(&printer
,2);
7267 return WERR_ACCESS_DENIED
;
7270 update_c_setprinter(False
);
7271 free_a_printer(&printer
,2);
7276 /****************************************************************************
7277 ****************************************************************************/
7279 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7281 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
7282 uint32 level
= q_u
->level
;
7283 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7284 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7285 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7286 uint32 user_switch
= q_u
->user_switch
;
7287 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7288 POLICY_HND
*handle
= &r_u
->handle
;
7292 /* we don't handle yet */
7293 /* but I know what to do ... */
7294 return WERR_UNKNOWN_LEVEL
;
7296 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7298 user_switch
, user
, handle
);
7300 return WERR_UNKNOWN_LEVEL
;
7304 /****************************************************************************
7305 ****************************************************************************/
7307 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7309 uint32 level
= q_u
->level
;
7310 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7311 WERROR err
= WERR_OK
;
7312 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7313 struct current_user user
;
7314 fstring driver_name
;
7317 ZERO_STRUCT(driver
);
7319 get_current_user(&user
, p
);
7321 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7326 DEBUG(5,("Cleaning driver's information\n"));
7327 err
= clean_up_driver_struct(driver
, level
, &user
);
7328 if (!W_ERROR_IS_OK(err
))
7331 DEBUG(5,("Moving driver to final destination\n"));
7332 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
7333 if (W_ERROR_IS_OK(err
))
7334 err
= WERR_ACCESS_DENIED
;
7338 if (add_a_printer_driver(driver
, level
)!=0) {
7339 err
= WERR_ACCESS_DENIED
;
7343 /* BEGIN_ADMIN_LOG */
7346 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7347 driver
.info_3
->name
,drv_ver_to_os
[driver
.info_3
->cversion
],uidtoname(user
.uid
));
7348 fstrcpy(driver_name
, driver
.info_3
->name
);
7351 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7352 driver
.info_6
->name
,drv_ver_to_os
[driver
.info_6
->version
],uidtoname(user
.uid
));
7353 fstrcpy(driver_name
, driver
.info_6
->name
);
7359 * I think this is where he DrvUpgradePrinter() hook would be
7360 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7361 * server. Right now, we just need to send ourselves a message
7362 * to update each printer bound to this driver. --jerry
7365 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7366 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7371 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7372 * decide if the driver init data should be deleted. The rules are:
7373 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7374 * 2) delete init data only if there is no 2k/Xp driver
7375 * 3) always delete init data
7376 * The generalized rule is always use init data from the highest order driver.
7377 * It is necessary to follow the driver install by an initialization step to
7378 * finish off this process.
7381 version
= driver
.info_3
->cversion
;
7382 else if (level
== 6)
7383 version
= driver
.info_6
->version
;
7388 * 9x printer driver - never delete init data
7391 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7396 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7397 * there is no 2k/Xp driver init data for this driver name.
7401 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7403 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7405 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7407 if (!del_driver_init(driver_name
))
7408 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7411 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7413 free_a_printer_driver(driver1
,3);
7414 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7421 * 2k or Xp printer driver - always delete init data
7424 if (!del_driver_init(driver_name
))
7425 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7429 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7435 free_a_printer_driver(driver
, level
);
7439 /********************************************************************
7440 * spoolss_addprinterdriverex
7441 ********************************************************************/
7443 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7445 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7446 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7449 * we only support the semantics of AddPrinterDriver()
7450 * i.e. only copy files that are newer than existing ones
7453 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7454 return WERR_ACCESS_DENIED
;
7456 ZERO_STRUCT(q_u_local
);
7457 ZERO_STRUCT(r_u_local
);
7459 /* just pass the information off to _spoolss_addprinterdriver() */
7460 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7461 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7462 q_u_local
.level
= q_u
->level
;
7463 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7465 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7468 /****************************************************************************
7469 ****************************************************************************/
7471 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7473 init_unistr(&info
->name
, name
);
7476 /****************************************************************************
7477 ****************************************************************************/
7479 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7483 pstring short_archi
;
7484 DRIVER_DIRECTORY_1
*info
=NULL
;
7486 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7488 if (get_short_archi(short_archi
, long_archi
)==False
)
7489 return WERR_INVALID_ENVIRONMENT
;
7491 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
7494 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi
);
7496 DEBUG(4,("printer driver directory: [%s]\n", path
));
7498 fill_driverdir_1(info
, path
);
7500 *needed
+= spoolss_size_driverdir_info_1(info
);
7502 if (!alloc_buffer_size(buffer
, *needed
)) {
7504 return WERR_INSUFFICIENT_BUFFER
;
7507 smb_io_driverdir_1("", buffer
, info
, 0);
7511 if (*needed
> offered
)
7512 return WERR_INSUFFICIENT_BUFFER
;
7517 /****************************************************************************
7518 ****************************************************************************/
7520 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7522 UNISTR2
*name
= &q_u
->name
;
7523 UNISTR2
*uni_environment
= &q_u
->environment
;
7524 uint32 level
= q_u
->level
;
7525 NEW_BUFFER
*buffer
= NULL
;
7526 uint32 offered
= q_u
->offered
;
7527 uint32
*needed
= &r_u
->needed
;
7529 /* that's an [in out] buffer */
7530 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7531 buffer
= r_u
->buffer
;
7533 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7539 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7541 return WERR_UNKNOWN_LEVEL
;
7545 /****************************************************************************
7546 ****************************************************************************/
7548 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7550 POLICY_HND
*handle
= &q_u
->handle
;
7551 uint32 idx
= q_u
->index
;
7552 uint32 in_value_len
= q_u
->valuesize
;
7553 uint32 in_data_len
= q_u
->datasize
;
7554 uint32
*out_max_value_len
= &r_u
->valuesize
;
7555 uint16
**out_value
= &r_u
->value
;
7556 uint32
*out_value_len
= &r_u
->realvaluesize
;
7557 uint32
*out_type
= &r_u
->type
;
7558 uint32
*out_max_data_len
= &r_u
->datasize
;
7559 uint8
**data_out
= &r_u
->data
;
7560 uint32
*out_data_len
= &r_u
->realdatasize
;
7562 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7565 uint32 biggest_valuesize
;
7566 uint32 biggest_datasize
;
7568 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7571 REGISTRY_VALUE
*val
;
7572 NT_PRINTER_DATA
*p_data
;
7573 int i
, key_index
, num_values
;
7576 ZERO_STRUCT( printer
);
7580 *out_max_data_len
= 0;
7584 DEBUG(5,("spoolss_enumprinterdata\n"));
7587 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7591 if (!get_printer_snum(p
,handle
, &snum
))
7594 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7595 if (!W_ERROR_IS_OK(result
))
7598 p_data
= &printer
->info_2
->data
;
7599 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7604 * The NT machine wants to know the biggest size of value and data
7606 * cf: MSDN EnumPrinterData remark section
7609 if ( !in_value_len
&& !in_data_len
)
7611 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7614 biggest_valuesize
= 0;
7615 biggest_datasize
= 0;
7617 num_values
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
7619 for ( i
=0; i
<num_values
; i
++ )
7621 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
7623 name_length
= strlen(val
->valuename
);
7624 if ( strlen(val
->valuename
) > biggest_valuesize
)
7625 biggest_valuesize
= name_length
;
7627 if ( val
->size
> biggest_datasize
)
7628 biggest_datasize
= val
->size
;
7630 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7634 /* the value is an UNICODE string but real_value_size is the length
7635 in bytes including the trailing 0 */
7637 *out_value_len
= 2 * (1+biggest_valuesize
);
7638 *out_data_len
= biggest_datasize
;
7640 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7646 * the value len is wrong in NT sp3
7647 * that's the number of bytes not the number of unicode chars
7650 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, idx
);
7655 /* out_value should default to "" or else NT4 has
7656 problems unmarshalling the response */
7658 *out_max_value_len
= (in_value_len
/sizeof(uint16
));
7660 if ( (*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7662 result
= WERR_NOMEM
;
7666 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
7668 /* the data is counted in bytes */
7670 *out_max_data_len
= in_data_len
;
7671 *out_data_len
= in_data_len
;
7673 /* only allocate when given a non-zero data_len */
7675 if ( in_data_len
&& ((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
7677 result
= WERR_NOMEM
;
7681 result
= WERR_NO_MORE_ITEMS
;
7687 * - counted in bytes in the request
7688 * - counted in UNICODE chars in the max reply
7689 * - counted in bytes in the real size
7691 * take a pause *before* coding not *during* coding
7695 *out_max_value_len
= ( in_value_len
/ sizeof(uint16
) );
7696 if ( (*out_value
= (uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7698 result
= WERR_NOMEM
;
7702 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), in_value_len
, 0);
7706 *out_type
= regval_type( val
);
7708 /* data - counted in bytes */
7710 *out_max_data_len
= in_data_len
;
7711 if ( (*data_out
= (uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
7713 result
= WERR_NOMEM
;
7716 data_len
= (size_t)regval_size(val
);
7717 memcpy( *data_out
, regval_data_p(val
), data_len
);
7718 *out_data_len
= data_len
;
7722 free_a_printer(&printer
, 2);
7726 /****************************************************************************
7727 ****************************************************************************/
7729 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
7731 POLICY_HND
*handle
= &q_u
->handle
;
7732 UNISTR2
*value
= &q_u
->value
;
7733 uint32 type
= q_u
->type
;
7734 uint8
*data
= q_u
->data
;
7735 uint32 real_len
= q_u
->real_len
;
7737 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7739 WERROR status
= WERR_OK
;
7740 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7743 DEBUG(5,("spoolss_setprinterdata\n"));
7746 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7750 if (!get_printer_snum(p
,handle
, &snum
))
7754 * Access check : NT returns "access denied" if you make a
7755 * SetPrinterData call without the necessary privildge.
7756 * we were originally returning OK if nothing changed
7757 * which made Win2k issue **a lot** of SetPrinterData
7758 * when connecting to a printer --jerry
7761 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
7763 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7764 status
= WERR_ACCESS_DENIED
;
7768 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7769 if (!W_ERROR_IS_OK(status
))
7772 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
7775 * When client side code sets a magic printer data key, detect it and save
7776 * the current printer data and the magic key's data (its the DEVMODE) for
7777 * future printer/driver initializations.
7779 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
7781 /* Set devmode and printer initialization info */
7782 status
= save_driver_init( printer
, 2, data
, real_len
);
7784 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
7788 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
7789 type
, data
, real_len
);
7790 if ( W_ERROR_IS_OK(status
) )
7791 status
= mod_a_printer(*printer
, 2);
7795 free_a_printer(&printer
, 2);
7800 /****************************************************************************
7801 ****************************************************************************/
7803 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
7805 POLICY_HND
*handle
= &q_u
->handle
;
7806 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7809 DEBUG(5,("_spoolss_resetprinter\n"));
7812 * All we do is to check to see if the handle and queue is valid.
7813 * This call really doesn't mean anything to us because we only
7814 * support RAW printing. --jerry
7818 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7822 if (!get_printer_snum(p
,handle
, &snum
))
7826 /* blindly return success */
7831 /****************************************************************************
7832 ****************************************************************************/
7834 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
7836 POLICY_HND
*handle
= &q_u
->handle
;
7837 UNISTR2
*value
= &q_u
->valuename
;
7839 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7841 WERROR status
= WERR_OK
;
7842 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7845 DEBUG(5,("spoolss_deleteprinterdata\n"));
7848 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7852 if (!get_printer_snum(p
, handle
, &snum
))
7855 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7856 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7857 return WERR_ACCESS_DENIED
;
7860 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7861 if (!W_ERROR_IS_OK(status
))
7864 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
7866 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
7868 free_a_printer(&printer
, 2);
7873 /****************************************************************************
7874 ****************************************************************************/
7876 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
7878 POLICY_HND
*handle
= &q_u
->handle
;
7879 FORM
*form
= &q_u
->form
;
7880 nt_forms_struct tmpForm
;
7882 WERROR status
= WERR_OK
;
7883 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7886 nt_forms_struct
*list
=NULL
;
7887 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7889 DEBUG(5,("spoolss_addform\n"));
7892 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7897 /* forms can be added on printer of on the print server handle */
7899 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7901 if (!get_printer_snum(p
,handle
, &snum
))
7904 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7905 if (!W_ERROR_IS_OK(status
))
7909 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7910 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7911 status
= WERR_ACCESS_DENIED
;
7915 /* can't add if builtin */
7917 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7918 status
= WERR_ALREADY_EXISTS
;
7922 count
= get_ntforms(&list
);
7924 if(!add_a_form(&list
, form
, &count
)) {
7925 status
= WERR_NOMEM
;
7929 write_ntforms(&list
, count
);
7932 * ChangeID must always be set if this is a printer
7935 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7936 status
= mod_a_printer(*printer
, 2);
7940 free_a_printer(&printer
, 2);
7946 /****************************************************************************
7947 ****************************************************************************/
7949 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
7951 POLICY_HND
*handle
= &q_u
->handle
;
7952 UNISTR2
*form_name
= &q_u
->name
;
7953 nt_forms_struct tmpForm
;
7955 nt_forms_struct
*list
=NULL
;
7956 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7958 WERROR status
= WERR_OK
;
7959 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7961 DEBUG(5,("spoolss_deleteform\n"));
7964 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7968 /* forms can be deleted on printer of on the print server handle */
7970 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7972 if (!get_printer_snum(p
,handle
, &snum
))
7975 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7976 if (!W_ERROR_IS_OK(status
))
7980 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7981 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7982 status
= WERR_ACCESS_DENIED
;
7986 /* can't delete if builtin */
7988 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
7989 status
= WERR_INVALID_PARAM
;
7993 count
= get_ntforms(&list
);
7995 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
7999 * ChangeID must always be set if this is a printer
8002 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8003 status
= mod_a_printer(*printer
, 2);
8007 free_a_printer(&printer
, 2);
8013 /****************************************************************************
8014 ****************************************************************************/
8016 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
8018 POLICY_HND
*handle
= &q_u
->handle
;
8019 FORM
*form
= &q_u
->form
;
8020 nt_forms_struct tmpForm
;
8022 WERROR status
= WERR_OK
;
8023 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8026 nt_forms_struct
*list
=NULL
;
8027 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8029 DEBUG(5,("spoolss_setform\n"));
8032 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8036 /* forms can be modified on printer of on the print server handle */
8038 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8040 if (!get_printer_snum(p
,handle
, &snum
))
8043 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8044 if (!W_ERROR_IS_OK(status
))
8048 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8049 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8050 status
= WERR_ACCESS_DENIED
;
8054 /* can't set if builtin */
8055 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8056 status
= WERR_INVALID_PARAM
;
8060 count
= get_ntforms(&list
);
8061 update_a_form(&list
, form
, count
);
8062 write_ntforms(&list
, count
);
8065 * ChangeID must always be set if this is a printer
8068 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8069 status
= mod_a_printer(*printer
, 2);
8074 free_a_printer(&printer
, 2);
8080 /****************************************************************************
8081 enumprintprocessors level 1.
8082 ****************************************************************************/
8084 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8086 PRINTPROCESSOR_1
*info_1
=NULL
;
8088 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
8093 init_unistr(&info_1
->name
, "winprint");
8095 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8097 if (!alloc_buffer_size(buffer
, *needed
))
8098 return WERR_INSUFFICIENT_BUFFER
;
8100 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8104 if (*needed
> offered
) {
8106 return WERR_INSUFFICIENT_BUFFER
;
8112 /****************************************************************************
8113 ****************************************************************************/
8115 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8117 uint32 level
= q_u
->level
;
8118 NEW_BUFFER
*buffer
= NULL
;
8119 uint32 offered
= q_u
->offered
;
8120 uint32
*needed
= &r_u
->needed
;
8121 uint32
*returned
= &r_u
->returned
;
8123 /* that's an [in out] buffer */
8124 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8125 buffer
= r_u
->buffer
;
8127 DEBUG(5,("spoolss_enumprintprocessors\n"));
8130 * Enumerate the print processors ...
8132 * Just reply with "winprint", to keep NT happy
8133 * and I can use my nice printer checker.
8141 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8143 return WERR_UNKNOWN_LEVEL
;
8147 /****************************************************************************
8148 enumprintprocdatatypes level 1.
8149 ****************************************************************************/
8151 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8153 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8155 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
8160 init_unistr(&info_1
->name
, "RAW");
8162 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8164 if (!alloc_buffer_size(buffer
, *needed
))
8165 return WERR_INSUFFICIENT_BUFFER
;
8167 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8171 if (*needed
> offered
) {
8173 return WERR_INSUFFICIENT_BUFFER
;
8179 /****************************************************************************
8180 ****************************************************************************/
8182 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8184 uint32 level
= q_u
->level
;
8185 NEW_BUFFER
*buffer
= NULL
;
8186 uint32 offered
= q_u
->offered
;
8187 uint32
*needed
= &r_u
->needed
;
8188 uint32
*returned
= &r_u
->returned
;
8190 /* that's an [in out] buffer */
8191 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8192 buffer
= r_u
->buffer
;
8194 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8201 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8203 return WERR_UNKNOWN_LEVEL
;
8207 /****************************************************************************
8208 enumprintmonitors level 1.
8209 ****************************************************************************/
8211 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8213 PRINTMONITOR_1
*info_1
=NULL
;
8215 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
8220 init_unistr(&info_1
->name
, "Local Port");
8222 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
8224 if (!alloc_buffer_size(buffer
, *needed
))
8225 return WERR_INSUFFICIENT_BUFFER
;
8227 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
8231 if (*needed
> offered
) {
8233 return WERR_INSUFFICIENT_BUFFER
;
8239 /****************************************************************************
8240 enumprintmonitors level 2.
8241 ****************************************************************************/
8243 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8245 PRINTMONITOR_2
*info_2
=NULL
;
8247 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
8252 init_unistr(&info_2
->name
, "Local Port");
8253 init_unistr(&info_2
->environment
, "Windows NT X86");
8254 init_unistr(&info_2
->dll_name
, "localmon.dll");
8256 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
8258 if (!alloc_buffer_size(buffer
, *needed
))
8259 return WERR_INSUFFICIENT_BUFFER
;
8261 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
8265 if (*needed
> offered
) {
8267 return WERR_INSUFFICIENT_BUFFER
;
8273 /****************************************************************************
8274 ****************************************************************************/
8276 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8278 uint32 level
= q_u
->level
;
8279 NEW_BUFFER
*buffer
= NULL
;
8280 uint32 offered
= q_u
->offered
;
8281 uint32
*needed
= &r_u
->needed
;
8282 uint32
*returned
= &r_u
->returned
;
8284 /* that's an [in out] buffer */
8285 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8286 buffer
= r_u
->buffer
;
8288 DEBUG(5,("spoolss_enumprintmonitors\n"));
8291 * Enumerate the print monitors ...
8293 * Just reply with "Local Port", to keep NT happy
8294 * and I can use my nice printer checker.
8302 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8304 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8306 return WERR_UNKNOWN_LEVEL
;
8310 /****************************************************************************
8311 ****************************************************************************/
8313 static WERROR
getjob_level_1(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
8317 JOB_INFO_1
*info_1
=NULL
;
8319 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
8321 if (info_1
== NULL
) {
8326 for (i
=0; i
<count
&& found
==False
; i
++) {
8327 if (queue
[i
].job
==(int)jobid
)
8334 /* NT treats not found as bad param... yet another bad choice */
8335 return WERR_INVALID_PARAM
;
8338 fill_job_info_1(info_1
, &(queue
[i
-1]), i
, snum
);
8340 *needed
+= spoolss_size_job_info_1(info_1
);
8342 if (!alloc_buffer_size(buffer
, *needed
)) {
8344 return WERR_INSUFFICIENT_BUFFER
;
8347 smb_io_job_info_1("", buffer
, info_1
, 0);
8351 if (*needed
> offered
)
8352 return WERR_INSUFFICIENT_BUFFER
;
8357 /****************************************************************************
8358 ****************************************************************************/
8360 static WERROR
getjob_level_2(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
8365 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8367 DEVICEMODE
*devmode
= NULL
;
8368 NT_DEVICEMODE
*nt_devmode
= NULL
;
8370 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
8372 ZERO_STRUCTP(info_2
);
8374 if (info_2
== NULL
) {
8379 for ( i
=0; i
<count
&& found
==False
; i
++ )
8381 if (queue
[i
].job
== (int)jobid
)
8387 /* NT treats not found as bad param... yet another bad
8389 ret
= WERR_INVALID_PARAM
;
8393 ret
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
8394 if (!W_ERROR_IS_OK(ret
))
8398 * if the print job does not have a DEVMODE associated with it,
8399 * just use the one for the printer. A NULL devicemode is not
8400 * a failure condition
8403 if ( !(nt_devmode
=print_job_devmode( snum
, jobid
)) )
8404 devmode
= construct_dev_mode(snum
);
8406 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) != NULL
) {
8407 ZERO_STRUCTP( devmode
);
8408 convert_nt_devicemode( devmode
, nt_devmode
);
8412 fill_job_info_2(info_2
, &(queue
[i
-1]), i
, snum
, ntprinter
, devmode
);
8414 *needed
+= spoolss_size_job_info_2(info_2
);
8416 if (!alloc_buffer_size(buffer
, *needed
)) {
8417 ret
= WERR_INSUFFICIENT_BUFFER
;
8421 smb_io_job_info_2("", buffer
, info_2
, 0);
8423 if (*needed
> offered
) {
8424 ret
= WERR_INSUFFICIENT_BUFFER
;
8431 /* Cleanup allocated memory */
8433 free_job_info_2(info_2
); /* Also frees devmode */
8435 free_a_printer(&ntprinter
, 2);
8440 /****************************************************************************
8441 ****************************************************************************/
8443 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8445 POLICY_HND
*handle
= &q_u
->handle
;
8446 uint32 jobid
= q_u
->jobid
;
8447 uint32 level
= q_u
->level
;
8448 NEW_BUFFER
*buffer
= NULL
;
8449 uint32 offered
= q_u
->offered
;
8450 uint32
*needed
= &r_u
->needed
;
8451 WERROR wstatus
= WERR_OK
;
8455 print_queue_struct
*queue
= NULL
;
8456 print_status_struct prt_status
;
8458 /* that's an [in out] buffer */
8459 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8460 buffer
= r_u
->buffer
;
8462 DEBUG(5,("spoolss_getjob\n"));
8466 if (!get_printer_snum(p
, handle
, &snum
))
8469 count
= print_queue_status(snum
, &queue
, &prt_status
);
8471 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8472 count
, prt_status
.status
, prt_status
.message
));
8476 wstatus
= getjob_level_1(queue
, count
, snum
, jobid
,
8477 buffer
, offered
, needed
);
8480 wstatus
= getjob_level_2(queue
, count
, snum
, jobid
,
8481 buffer
, offered
, needed
);
8484 wstatus
= WERR_UNKNOWN_LEVEL
;
8492 /********************************************************************
8493 spoolss_getprinterdataex
8495 From MSDN documentation of GetPrinterDataEx: pass request
8496 to GetPrinterData if key is "PrinterDriverData".
8497 ********************************************************************/
8499 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8501 POLICY_HND
*handle
= &q_u
->handle
;
8502 uint32 in_size
= q_u
->size
;
8503 uint32
*type
= &r_u
->type
;
8504 uint32
*out_size
= &r_u
->size
;
8505 uint8
**data
= &r_u
->data
;
8506 uint32
*needed
= &r_u
->needed
;
8507 fstring keyname
, valuename
;
8509 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8511 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8513 WERROR status
= WERR_OK
;
8515 DEBUG(4,("_spoolss_getprinterdataex\n"));
8517 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8518 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
8520 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8521 keyname
, valuename
));
8523 /* in case of problem, return some default values */
8527 *out_size
= in_size
;
8530 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8531 status
= WERR_BADFID
;
8535 /* Is the handle to a printer or to the server? */
8537 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8538 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8539 status
= WERR_INVALID_PARAM
;
8543 if ( !get_printer_snum(p
,handle
, &snum
) )
8546 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8547 if ( !W_ERROR_IS_OK(status
) )
8550 /* check to see if the keyname is valid */
8551 if ( !strlen(keyname
) ) {
8552 status
= WERR_INVALID_PARAM
;
8556 if ( lookup_printerkey( &printer
->info_2
->data
, keyname
) == -1 ) {
8557 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
8558 free_a_printer( &printer
, 2 );
8559 status
= WERR_BADFILE
;
8563 /* When given a new keyname, we should just create it */
8565 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
8567 if (*needed
> *out_size
)
8568 status
= WERR_MORE_DATA
;
8571 if ( !W_ERROR_IS_OK(status
) )
8573 DEBUG(5, ("error: allocating %d\n", *out_size
));
8575 /* reply this param doesn't exist */
8579 if( (*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
8580 status
= WERR_NOMEM
;
8590 free_a_printer( &printer
, 2 );
8595 /********************************************************************
8596 * spoolss_setprinterdataex
8597 ********************************************************************/
8599 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
8601 POLICY_HND
*handle
= &q_u
->handle
;
8602 uint32 type
= q_u
->type
;
8603 uint8
*data
= q_u
->data
;
8604 uint32 real_len
= q_u
->real_len
;
8606 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8608 WERROR status
= WERR_OK
;
8609 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8614 DEBUG(4,("_spoolss_setprinterdataex\n"));
8616 /* From MSDN documentation of SetPrinterDataEx: pass request to
8617 SetPrinterData if key is "PrinterDriverData" */
8620 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8624 if ( !get_printer_snum(p
,handle
, &snum
) )
8628 * Access check : NT returns "access denied" if you make a
8629 * SetPrinterData call without the necessary privildge.
8630 * we were originally returning OK if nothing changed
8631 * which made Win2k issue **a lot** of SetPrinterData
8632 * when connecting to a printer --jerry
8635 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8637 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8638 return WERR_ACCESS_DENIED
;
8641 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8642 if (!W_ERROR_IS_OK(status
))
8645 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
8646 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
8648 /* check for OID in valuename */
8650 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
8656 /* save the registry data */
8658 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
8660 /* save the OID if one was specified and the previous set call succeeded */
8662 if ( W_ERROR_IS_OK(status
) && oid_string
)
8665 fstrcat( keyname
, "\\" );
8666 fstrcat( keyname
, SPOOL_OID_KEY
);
8669 * I'm not checking the status here on purpose. Don't know
8670 * if this is right, but I'm returning the status from the
8671 * previous set_printer_dataex() call. I have no idea if
8672 * this is right. --jerry
8675 set_printer_dataex( printer
, keyname
, valuename
,
8676 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
8679 free_a_printer(&printer
, 2);
8685 /********************************************************************
8686 * spoolss_deleteprinterdataex
8687 ********************************************************************/
8689 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
8691 POLICY_HND
*handle
= &q_u
->handle
;
8692 UNISTR2
*value
= &q_u
->valuename
;
8693 UNISTR2
*key
= &q_u
->keyname
;
8695 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8697 WERROR status
= WERR_OK
;
8698 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8699 pstring valuename
, keyname
;
8701 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8704 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8708 if (!get_printer_snum(p
, handle
, &snum
))
8711 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8712 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8713 return WERR_ACCESS_DENIED
;
8716 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8717 if (!W_ERROR_IS_OK(status
))
8720 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8721 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
8723 status
= delete_printer_dataex( printer
, keyname
, valuename
);
8725 free_a_printer(&printer
, 2);
8730 /********************************************************************
8731 * spoolss_enumprinterkey
8732 ********************************************************************/
8735 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
8738 fstring
*keynames
= NULL
;
8739 uint16
*enumkeys
= NULL
;
8742 POLICY_HND
*handle
= &q_u
->handle
;
8743 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8744 NT_PRINTER_DATA
*data
;
8745 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8747 WERROR status
= WERR_BADFILE
;
8750 DEBUG(4,("_spoolss_enumprinterkey\n"));
8753 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8757 if ( !get_printer_snum(p
,handle
, &snum
) )
8760 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8761 if (!W_ERROR_IS_OK(status
))
8764 /* get the list of subkey names */
8766 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
8767 data
= &printer
->info_2
->data
;
8769 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
8771 if ( num_keys
== -1 ) {
8772 status
= WERR_BADFILE
;
8776 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
8778 r_u
->needed
= printerkey_len
*2;
8780 if ( q_u
->size
< r_u
->needed
) {
8781 status
= WERR_MORE_DATA
;
8785 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
8786 status
= WERR_NOMEM
;
8792 if ( q_u
->size
< r_u
->needed
)
8793 status
= WERR_MORE_DATA
;
8796 free_a_printer( &printer
, 2 );
8797 SAFE_FREE( keynames
);
8802 /********************************************************************
8803 * spoolss_deleteprinterkey
8804 ********************************************************************/
8806 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
8808 POLICY_HND
*handle
= &q_u
->handle
;
8809 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
8811 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8815 DEBUG(5,("spoolss_deleteprinterkey\n"));
8818 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8822 /* if keyname == NULL, return error */
8824 if ( !q_u
->keyname
.buffer
)
8825 return WERR_INVALID_PARAM
;
8827 if (!get_printer_snum(p
, handle
, &snum
))
8830 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8831 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8832 return WERR_ACCESS_DENIED
;
8835 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8836 if (!W_ERROR_IS_OK(status
))
8839 /* delete the key and all subneys */
8841 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
8843 status
= delete_all_printer_data( printer
->info_2
, key
);
8845 if ( W_ERROR_IS_OK(status
) )
8846 status
= mod_a_printer(*printer
, 2);
8848 free_a_printer( &printer
, 2 );
8854 /********************************************************************
8855 * spoolss_enumprinterdataex
8856 ********************************************************************/
8858 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
8860 POLICY_HND
*handle
= &q_u
->handle
;
8861 uint32 in_size
= q_u
->size
;
8864 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8865 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
8866 NT_PRINTER_DATA
*p_data
;
8868 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8873 REGISTRY_VALUE
*val
;
8878 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8881 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
8886 * first check for a keyname of NULL or "". Win2k seems to send
8887 * this a lot and we should send back WERR_INVALID_PARAM
8888 * no need to spend time looking up the printer in this case.
8892 unistr2_to_dos(key
, &q_u
->key
, sizeof(key
) - 1);
8893 if ( !strlen(key
) ) {
8894 result
= WERR_INVALID_PARAM
;
8898 /* get the printer off of disk */
8900 if (!get_printer_snum(p
,handle
, &snum
))
8903 ZERO_STRUCT(printer
);
8904 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8905 if (!W_ERROR_IS_OK(result
))
8908 /* now look for a match on the key name */
8910 p_data
= &printer
->info_2
->data
;
8912 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
8913 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
8915 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
8916 result
= WERR_INVALID_PARAM
;
8923 /* allocate the memory for the array of pointers -- if necessary */
8925 num_entries
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
8928 if ( (enum_values
=talloc(p
->mem_ctx
, num_entries
*sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
8930 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8931 num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
8932 result
= WERR_NOMEM
;
8936 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
8940 * loop through all params and build the array to pass
8941 * back to the client
8944 for ( i
=0; i
<num_entries
; i
++ )
8946 /* lookup the registry value */
8948 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
8949 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
8953 value_name
= regval_name( val
);
8954 init_unistr( &enum_values
[i
].valuename
, value_name
);
8955 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
8956 enum_values
[i
].type
= regval_type( val
);
8958 data_len
= regval_size( val
);
8960 if ( !(enum_values
[i
].data
= talloc_memdup(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
8962 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8964 result
= WERR_NOMEM
;
8968 enum_values
[i
].data_len
= data_len
;
8970 /* keep track of the size of the array in bytes */
8972 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
8975 /* housekeeping information in the reply */
8977 r_u
->needed
= needed
;
8978 r_u
->returned
= num_entries
;
8980 if (needed
> in_size
) {
8981 result
= WERR_MORE_DATA
;
8985 /* copy data into the reply */
8987 r_u
->ctr
.size
= r_u
->needed
;
8988 r_u
->ctr
.size_of_array
= r_u
->returned
;
8989 r_u
->ctr
.values
= enum_values
;
8995 free_a_printer(&printer
, 2);
9000 /****************************************************************************
9001 ****************************************************************************/
9003 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
9005 init_unistr(&info
->name
, name
);
9008 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
9009 UNISTR2
*environment
,
9016 pstring short_archi
;
9017 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
9019 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
9021 if (get_short_archi(short_archi
, long_archi
)==False
)
9022 return WERR_INVALID_ENVIRONMENT
;
9024 if((info
=(PRINTPROCESSOR_DIRECTORY_1
*)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1
))) == NULL
)
9027 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9029 fill_printprocessordirectory_1(info
, path
);
9031 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
9033 if (!alloc_buffer_size(buffer
, *needed
)) {
9035 return WERR_INSUFFICIENT_BUFFER
;
9038 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
9042 if (*needed
> offered
)
9043 return WERR_INSUFFICIENT_BUFFER
;
9048 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
9050 uint32 level
= q_u
->level
;
9051 NEW_BUFFER
*buffer
= NULL
;
9052 uint32 offered
= q_u
->offered
;
9053 uint32
*needed
= &r_u
->needed
;
9056 /* that's an [in out] buffer */
9057 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
9058 buffer
= r_u
->buffer
;
9060 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9066 result
= getprintprocessordirectory_level_1
9067 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
9070 result
= WERR_UNKNOWN_LEVEL
;
9078 WERROR
_spoolss_replyopenprinter(pipes_struct
*p
, SPOOL_Q_REPLYOPENPRINTER
*q_u
,
9079 SPOOL_R_REPLYOPENPRINTER
*r_u
)
9081 DEBUG(5,("_spoolss_replyopenprinter\n"));
9083 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u
->printer
));
9088 WERROR
_spoolss_replycloseprinter(pipes_struct
*p
, SPOOL_Q_REPLYCLOSEPRINTER
*q_u
,
9089 SPOOL_R_REPLYCLOSEPRINTER
*r_u
)
9091 DEBUG(5,("_spoolss_replycloseprinter\n"));