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 uint32 client_connected
;
90 /* devmode sent in the OpenPrinter() call */
91 NT_DEVICEMODE
*nt_devmode
;
95 static Printer_entry
*printers_list
;
97 typedef struct _counter_printer_0
{
105 static ubi_dlList counter_list
;
107 static struct cli_state notify_cli
; /* print notify back-channel */
108 static uint32 smb_connections
=0;
111 /* in printing/nt_printing.c */
113 extern STANDARD_MAPPING printer_std_mapping
, printserver_std_mapping
;
115 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
116 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
118 /* translate between internal status numbers and NT status numbers */
119 static int nt_printj_status(int v
)
125 return JOB_STATUS_PAUSED
;
127 return JOB_STATUS_SPOOLING
;
129 return JOB_STATUS_PRINTING
;
131 return JOB_STATUS_ERROR
;
133 return JOB_STATUS_DELETING
;
135 return JOB_STATUS_OFFLINE
;
137 return JOB_STATUS_PAPEROUT
;
139 return JOB_STATUS_PRINTED
;
141 return JOB_STATUS_DELETED
;
143 return JOB_STATUS_BLOCKED
;
144 case LPQ_USER_INTERVENTION
:
145 return JOB_STATUS_USER_INTERVENTION
;
150 static int nt_printq_status(int v
)
154 return PRINTER_STATUS_PAUSED
;
163 /****************************************************************************
164 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
165 ****************************************************************************/
167 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
172 SAFE_FREE((*pp
)->ctr
.type
);
176 /***************************************************************************
177 Disconnect from the client
178 ****************************************************************************/
180 static void srv_spoolss_replycloseprinter(int snum
, POLICY_HND
*handle
)
185 * Tell the specific printing tdb we no longer want messages for this printer
186 * by deregistering our PID.
189 if (!print_notify_deregister_pid(snum
))
190 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
192 /* weird if the test succeds !!! */
193 if (smb_connections
==0) {
194 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
198 result
= cli_spoolss_reply_close_printer(¬ify_cli
, notify_cli
.mem_ctx
, handle
);
200 if (!W_ERROR_IS_OK(result
))
201 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
202 dos_errstr(result
)));
204 /* if it's the last connection, deconnect the IPC$ share */
205 if (smb_connections
==1) {
206 cli_nt_session_close(¬ify_cli
);
207 cli_ulogoff(¬ify_cli
);
208 cli_shutdown(¬ify_cli
);
209 message_deregister(MSG_PRINTER_NOTIFY2
);
211 /* Tell the connections db we're no longer interested in
212 * printer notify messages. */
214 register_message_flags( False
, FLAG_MSG_PRINTING
);
220 /****************************************************************************
221 Functions to free a printer entry datastruct.
222 ****************************************************************************/
224 static void free_printer_entry(void *ptr
)
226 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
228 if (Printer
->notify
.client_connected
==True
) {
231 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
233 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
234 } else if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) {
235 snum
= print_queue_snum(Printer
->dev
.handlename
);
237 srv_spoolss_replycloseprinter(snum
,
238 &Printer
->notify
.client_hnd
);
242 Printer
->notify
.flags
=0;
243 Printer
->notify
.options
=0;
244 Printer
->notify
.localmachine
[0]='\0';
245 Printer
->notify
.printerlocal
=0;
246 free_spool_notify_option(&Printer
->notify
.option
);
247 Printer
->notify
.option
=NULL
;
248 Printer
->notify
.client_connected
=False
;
250 free_nt_devicemode( &Printer
->nt_devmode
);
252 /* Remove from the internal list. */
253 DLIST_REMOVE(printers_list
, Printer
);
258 /****************************************************************************
259 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
260 ****************************************************************************/
262 SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
264 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
269 new_sp
= (SPOOL_NOTIFY_OPTION
*)malloc(sizeof(SPOOL_NOTIFY_OPTION
));
276 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
278 if (!new_sp
->ctr
.type
) {
287 /****************************************************************************
288 find printer index by handle
289 ****************************************************************************/
291 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
293 Printer_entry
*find_printer
= NULL
;
295 if(!find_policy_by_hnd(p
,hnd
,(void **)&find_printer
)) {
296 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
303 /****************************************************************************
304 Close printer index by handle.
305 ****************************************************************************/
307 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
309 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
312 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
316 close_policy_hnd(p
, hnd
);
321 /****************************************************************************
322 Delete a printer given a handle.
323 ****************************************************************************/
325 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
327 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
330 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
335 * It turns out that Windows allows delete printer on a handle
336 * opened by an admin user, then used on a pipe handle created
337 * by an anonymous user..... but they're working on security.... riiight !
341 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
342 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
343 return WERR_ACCESS_DENIED
;
347 /* Check calling user has permission to delete printer. Note that
348 since we set the snum parameter to -1 only administrators can
349 delete the printer. This stops people with the Full Control
350 permission from deleting the printer. */
352 if (!print_access_check(NULL
, -1, PRINTER_ACCESS_ADMINISTER
)) {
353 DEBUG(3, ("printer delete denied by security descriptor\n"));
354 return WERR_ACCESS_DENIED
;
358 if (del_a_printer(Printer
->dev
.handlename
) != 0) {
359 DEBUG(3,("Error deleting printer %s\n", Printer
->dev
.handlename
));
363 if (*lp_deleteprinter_cmd()) {
365 char *cmd
= lp_deleteprinter_cmd();
370 /* Printer->dev.handlename equals portname equals sharename */
371 slprintf(command
, sizeof(command
)-1, "%s \"%s\"", cmd
,
372 Printer
->dev
.handlename
);
374 DEBUG(10,("Running [%s]\n", command
));
375 ret
= smbrun(command
, NULL
);
377 return WERR_BADFID
; /* What to return here? */
379 DEBUGADD(10,("returned [%d]\n", ret
));
381 /* Send SIGHUP to process group... is there a better way? */
384 /* go ahead and re-read the services immediately */
385 reload_services( False
);
387 if ( ( i
= lp_servicenumber( Printer
->dev
.handlename
) ) < 0 )
388 return WERR_ACCESS_DENIED
;
394 /****************************************************************************
395 Return the snum of a printer corresponding to an handle.
396 ****************************************************************************/
398 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
400 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
403 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
407 switch (Printer
->printer_type
) {
408 case PRINTER_HANDLE_IS_PRINTER
:
409 DEBUG(4,("short name:%s\n", Printer
->dev
.handlename
));
410 *number
= print_queue_snum(Printer
->dev
.handlename
);
411 return (*number
!= -1);
412 case PRINTER_HANDLE_IS_PRINTSERVER
:
419 /****************************************************************************
420 Set printer handle type.
421 Check if it's \\server or \\server\printer
422 ****************************************************************************/
424 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
426 DEBUG(3,("Setting printer type=%s\n", handlename
));
428 if ( strlen(handlename
) < 3 ) {
429 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
433 /* it's a print server */
434 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
435 DEBUGADD(4,("Printer is a print server\n"));
436 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTSERVER
;
440 DEBUGADD(4,("Printer is a printer\n"));
441 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTER
;
447 /****************************************************************************
448 Set printer handle name.
449 ****************************************************************************/
451 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
454 int n_services
=lp_numservices();
459 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename
, strlen(handlename
)));
461 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTSERVER
) {
462 ZERO_STRUCT(Printer
->dev
.printerservername
);
463 strncpy(Printer
->dev
.printerservername
, handlename
, strlen(handlename
));
467 if (Printer
->printer_type
!=PRINTER_HANDLE_IS_PRINTER
)
470 if (*handlename
=='\\') {
471 aprinter
=strchr_m(handlename
+2, '\\');
478 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter
, strlen(aprinter
)));
481 * The original code allowed smbd to store a printer name that
482 * was different from the share name. This is not possible
483 * anymore, so I've simplified this loop greatly. Here
484 * we are just verifying that the printer name is a valid
485 * printer service defined in smb.conf
486 * --jerry [Fri Feb 15 11:17:46 CST 2002]
489 for (snum
=0; snum
<n_services
; snum
++) {
491 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
494 fstrcpy(sname
, lp_servicename(snum
));
496 DEBUGADD(5,("share:%s\n",sname
));
498 if (! StrCaseCmp(sname
, aprinter
)) {
507 DEBUGADD(4,("Printer not found\n"));
511 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
513 ZERO_STRUCT(Printer
->dev
.handlename
);
514 fstrcpy(Printer
->dev
.handlename
, sname
);
519 /****************************************************************************
520 Find first available printer slot. creates a printer handle for you.
521 ****************************************************************************/
523 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
525 Printer_entry
*new_printer
;
527 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
529 if((new_printer
=(Printer_entry
*)malloc(sizeof(Printer_entry
))) == NULL
)
532 ZERO_STRUCTP(new_printer
);
534 new_printer
->notify
.option
=NULL
;
536 /* Add to the internal list. */
537 DLIST_ADD(printers_list
, new_printer
);
539 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
540 SAFE_FREE(new_printer
);
544 if (!set_printer_hnd_printertype(new_printer
, name
)) {
545 close_printer_handle(p
, hnd
);
549 if (!set_printer_hnd_name(new_printer
, name
)) {
550 close_printer_handle(p
, hnd
);
554 new_printer
->access_granted
= access_granted
;
556 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
561 /****************************************************************************
562 Allocate more memory for a BUFFER.
563 ****************************************************************************/
565 static BOOL
alloc_buffer_size(NEW_BUFFER
*buffer
, uint32 buffer_size
)
573 /* damn, I'm doing the reverse operation of prs_grow() :) */
574 if (buffer_size
< prs_data_size(ps
))
577 extra_space
= buffer_size
- prs_data_size(ps
);
580 * save the offset and move to the end of the buffer
581 * prs_grow() checks the extra_space against the offset
583 old_offset
=prs_offset(ps
);
584 prs_set_offset(ps
, prs_data_size(ps
));
586 if (!prs_grow(ps
, extra_space
))
589 prs_set_offset(ps
, old_offset
);
591 buffer
->string_at_end
=prs_data_size(ps
);
596 /***************************************************************************
597 check to see if the client motify handle is monitoring the notification
598 given by (notify_type, notify_field).
599 **************************************************************************/
601 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
607 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
610 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
614 * Flags should always be zero when the change notify
615 * is registered by the cliebnt's spooler. A user Win32 app
616 * might use the flags though instead of the NOTIFY_OPTION_INFO
621 return is_monitoring_event_flags(
622 p
->notify
.flags
, notify_type
, notify_field
);
624 for (i
= 0; i
< option
->count
; i
++) {
626 /* Check match for notify_type */
628 if (option
->ctr
.type
[i
].type
!= notify_type
)
631 /* Check match for field */
633 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
634 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
640 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
641 (p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) ?
642 p
->dev
.handlename
: p
->dev
.printerservername
,
643 notify_type
, notify_field
));
648 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
650 static void notify_one_value(struct spoolss_notify_msg
*msg
,
651 SPOOL_NOTIFY_INFO_DATA
*data
,
654 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
655 data
->notify_data
.value
[1] = 0;
658 static void notify_string(struct spoolss_notify_msg
*msg
,
659 SPOOL_NOTIFY_INFO_DATA
*data
,
664 /* The length of the message includes the trailing \0 */
666 init_unistr2(&unistr
, msg
->notify
.data
, msg
->len
);
668 data
->notify_data
.data
.length
= msg
->len
* 2;
669 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, msg
->len
* 2);
671 if (!data
->notify_data
.data
.string
) {
672 data
->notify_data
.data
.length
= 0;
676 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
679 static void notify_system_time(struct spoolss_notify_msg
*msg
,
680 SPOOL_NOTIFY_INFO_DATA
*data
,
686 if (msg
->len
!= sizeof(time_t)) {
687 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
692 if (!prs_init(&ps
, MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
693 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
697 if (!make_systemtime(&systime
, gmtime((time_t *)msg
->notify
.data
))) {
698 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
702 if (!spoolss_io_system_time("", &ps
, 0, &systime
))
705 data
->notify_data
.data
.length
= prs_offset(&ps
);
706 data
->notify_data
.data
.string
=
707 talloc(mem_ctx
, prs_offset(&ps
));
709 memcpy(data
->notify_data
.data
.string
, prs_data_p(&ps
), prs_offset(&ps
));
714 struct notify2_message_table
{
716 void (*fn
)(struct spoolss_notify_msg
*msg
,
717 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
720 static struct notify2_message_table printer_notify_table
[] = {
721 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
722 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
723 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
724 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
725 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
726 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
727 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
728 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
729 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
730 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
731 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
732 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
733 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
734 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
735 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
736 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
737 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
738 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
739 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
742 static struct notify2_message_table job_notify_table
[] = {
743 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
744 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
745 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
746 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
747 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
748 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
749 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
750 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
751 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
752 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
753 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
754 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
755 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
756 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
757 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
758 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
759 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
760 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
761 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
762 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
763 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
764 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
765 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
766 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
770 /***********************************************************************
771 Allocate talloc context for container object
772 **********************************************************************/
774 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
779 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
784 /***********************************************************************
785 release all allocated memory and zero out structure
786 **********************************************************************/
788 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
794 talloc_destroy(ctr
->ctx
);
801 /***********************************************************************
802 **********************************************************************/
804 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
812 /***********************************************************************
813 **********************************************************************/
815 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
817 if ( !ctr
|| !ctr
->msg_groups
)
820 if ( idx
>= ctr
->num_groups
)
823 return &ctr
->msg_groups
[idx
];
827 /***********************************************************************
828 How many groups of change messages do we have ?
829 **********************************************************************/
831 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
836 return ctr
->num_groups
;
839 /***********************************************************************
840 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
841 **********************************************************************/
843 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
845 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
846 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
847 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
853 /* loop over all groups looking for a matching printer name */
855 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
856 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
860 /* add a new group? */
862 if ( i
== ctr
->num_groups
)
866 if ( !(groups
= talloc_realloc( ctr
->ctx
, ctr
->msg_groups
, sizeof(SPOOLSS_NOTIFY_MSG_GROUP
)*ctr
->num_groups
)) ) {
867 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
870 ctr
->msg_groups
= groups
;
872 /* clear the new entry and set the printer name */
874 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
875 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
878 /* add the change messages; 'i' is the correct index now regardless */
880 msg_grp
= &ctr
->msg_groups
[i
];
884 if ( !(msg_list
= talloc_realloc( ctr
->ctx
, msg_grp
->msgs
, sizeof(SPOOLSS_NOTIFY_MSG
)*msg_grp
->num_msgs
)) ) {
885 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
888 msg_grp
->msgs
= msg_list
;
890 new_slot
= msg_grp
->num_msgs
-1;
891 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
893 /* need to allocate own copy of data */
896 msg_grp
->msgs
[new_slot
].notify
.data
= talloc_memdup( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
898 return ctr
->num_groups
;
901 /***********************************************************************
902 Send a change notication message on all handles which have a call
904 **********************************************************************/
906 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
909 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
910 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
911 SPOOLSS_NOTIFY_MSG
*messages
;
915 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
919 messages
= msg_group
->msgs
;
922 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
926 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
928 /* loop over all printers */
930 for (p
= printers_list
; p
; p
= p
->next
)
932 SPOOL_NOTIFY_INFO_DATA
*data
;
937 /* Is there notification on this handle? */
939 if ( !p
->notify
.client_connected
)
942 DEBUG(10,("Client connected! [%s]\n", p
->dev
.handlename
));
944 /* For this printer? Print servers always receive
947 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
948 ( !strequal(msg_group
->printername
, p
->dev
.handlename
) ) )
951 DEBUG(10,("Our printer\n"));
953 /* allocate the max entries possible */
955 data
= talloc( mem_ctx
, msg_group
->num_msgs
*sizeof(SPOOL_NOTIFY_INFO_DATA
) );
958 /* build the array of change notifications */
960 for ( i
=0; i
<msg_group
->num_msgs
; i
++ )
962 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
964 /* Are we monitoring this event? */
966 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
970 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
971 msg
->type
, msg
->field
, p
->dev
.handlename
));
974 * if the is a printer notification handle and not a job notification
975 * type, then set the id to 0. Other wise just use what was specified
978 * When registering change notification on a print server handle
979 * we always need to send back the id (snum) matching the printer
980 * for which the change took place. For change notify registered
981 * on a printer handle, this does not matter and the id should be 0.
986 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
992 /* Convert unix jobid to smb jobid */
994 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
)
996 id
= sysjob_to_jobid(msg
->id
);
999 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1004 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1007 case PRINTER_NOTIFY_TYPE
:
1008 if ( !printer_notify_table
[msg
->field
].fn
)
1010 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1014 case JOB_NOTIFY_TYPE
:
1015 if ( !job_notify_table
[msg
->field
].fn
)
1017 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 Send a message to ourself about new driver being installed
1233 so we can upgrade the information for each printer bound to this
1235 ********************************************************************/
1237 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1239 int len
= strlen(drivername
);
1244 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1247 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1252 /**********************************************************************
1253 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1254 over all printers, resetting printer data as neessary
1255 **********************************************************************/
1257 void reset_all_printerdata(int msg_type
, pid_t src
, void *buf
, size_t len
)
1261 int n_services
= lp_numservices();
1263 len
= MIN( len
, sizeof(drivername
)-1 );
1264 strncpy( drivername
, buf
, len
);
1266 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1268 /* Iterate the printer list */
1270 for ( snum
=0; snum
<n_services
; snum
++ )
1272 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1275 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1277 result
= get_a_printer( &printer
, 2, lp_servicename(snum
) );
1278 if ( !W_ERROR_IS_OK(result
) )
1282 * if the printer is bound to the driver,
1283 * then reset to the new driver initdata
1286 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1288 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1290 if ( !set_driver_init(printer
, 2) ) {
1291 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1292 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1295 result
= mod_a_printer( *printer
, 2 );
1296 if ( !W_ERROR_IS_OK(result
) ) {
1297 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1298 get_dos_error_msg(result
)));
1302 free_a_printer( &printer
, 2 );
1311 /********************************************************************
1312 Copy routines used by convert_to_openprinterex()
1313 *******************************************************************/
1315 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1323 DEBUG (8,("dup_devmode\n"));
1325 /* bulk copy first */
1327 d
= talloc_memdup(ctx
, devmode
, sizeof(DEVICEMODE
));
1331 /* dup the pointer members separately */
1333 len
= unistrlen(devmode
->devicename
.buffer
);
1335 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1336 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1341 len
= unistrlen(devmode
->formname
.buffer
);
1343 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1344 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1348 d
->private = talloc_memdup(ctx
, devmode
->private, devmode
->driverextra
);
1353 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1355 if (!new_ctr
|| !ctr
)
1358 DEBUG(8,("copy_devmode_ctr\n"));
1360 new_ctr
->size
= ctr
->size
;
1361 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1363 if(ctr
->devmode_ptr
)
1364 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1367 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1369 if (!new_def
|| !def
)
1372 DEBUG(8,("copy_printer_defaults\n"));
1374 new_def
->datatype_ptr
= def
->datatype_ptr
;
1376 if (def
->datatype_ptr
)
1377 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1379 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1381 new_def
->access_required
= def
->access_required
;
1384 /********************************************************************
1385 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1386 * SPOOL_Q_OPEN_PRINTER_EX structure
1387 ********************************************************************/
1389 static void convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1391 if (!q_u_ex
|| !q_u
)
1394 DEBUG(8,("convert_to_openprinterex\n"));
1396 q_u_ex
->printername_ptr
= q_u
->printername_ptr
;
1398 if (q_u
->printername_ptr
)
1399 copy_unistr2(&q_u_ex
->printername
, &q_u
->printername
);
1401 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1404 /********************************************************************
1405 * spoolss_open_printer
1407 * called from the spoolss dispatcher
1408 ********************************************************************/
1410 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1412 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1413 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1418 ZERO_STRUCT(q_u_ex
);
1419 ZERO_STRUCT(r_u_ex
);
1421 /* convert the OpenPrinter() call to OpenPrinterEx() */
1423 convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1425 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1427 /* convert back to OpenPrinter() */
1429 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1434 /********************************************************************
1435 * spoolss_open_printer
1437 * If the openprinterex rpc call contains a devmode,
1438 * it's a per-user one. This per-user devmode is derivated
1439 * from the global devmode. Openprinterex() contains a per-user
1440 * devmode for when you do EMF printing and spooling.
1441 * In the EMF case, the NT workstation is only doing half the job
1442 * of rendering the page. The other half is done by running the printer
1443 * driver on the server.
1444 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1445 * The EMF file only contains what is to be printed on the page.
1446 * So in order for the server to know how to print, the NT client sends
1447 * a devicemode attached to the openprinterex call.
1448 * But this devicemode is short lived, it's only valid for the current print job.
1450 * If Samba would have supported EMF spooling, this devicemode would
1451 * have been attached to the handle, to sent it to the driver to correctly
1452 * rasterize the EMF file.
1454 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1455 * we just act as a pass-thru between windows and the printer.
1457 * In order to know that Samba supports only RAW spooling, NT has to call
1458 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1459 * and until NT sends a RAW job, we refuse it.
1461 * But to call getprinter() or startdoc(), you first need a valid handle,
1462 * and to get an handle you have to call openprintex(). Hence why you have
1463 * a devicemode in the openprinterex() call.
1466 * Differences between NT4 and NT 2000.
1469 * On NT4, you only have a global devicemode. This global devicemode can be changed
1470 * by the administrator (or by a user with enough privs). Everytime a user
1471 * wants to print, the devicemode is resetted to the default. In Word, everytime
1472 * you print, the printer's characteristics are always reset to the global devicemode.
1476 * In W2K, there is the notion of per-user devicemode. The first time you use
1477 * a printer, a per-user devicemode is build from the global devicemode.
1478 * If you change your per-user devicemode, it is saved in the registry, under the
1479 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1480 * printer preferences available.
1482 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1483 * on the General Tab of the printer properties windows.
1485 * To change the global devicemode: it's the "Printing Defaults..." button
1486 * on the Advanced Tab of the printer properties window.
1489 ********************************************************************/
1491 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1493 UNISTR2
*printername
= NULL
;
1494 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1495 POLICY_HND
*handle
= &r_u
->handle
;
1499 struct current_user user
;
1500 Printer_entry
*Printer
=NULL
;
1502 if (q_u
->printername_ptr
!= 0)
1503 printername
= &q_u
->printername
;
1505 if (printername
== NULL
)
1506 return WERR_INVALID_PRINTER_NAME
;
1508 /* some sanity check because you can open a printer or a print server */
1509 /* aka: \\server\printer or \\server */
1510 unistr2_to_ascii(name
, printername
, sizeof(name
)-1);
1512 DEBUGADD(3,("checking name: %s\n",name
));
1514 if (!open_printer_hnd(p
, handle
, name
, 0))
1515 return WERR_INVALID_PRINTER_NAME
;
1517 Printer
=find_printer_index_by_hnd(p
, handle
);
1519 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1520 Can't find printer handle we created for printer %s\n", name
));
1521 close_printer_handle(p
,handle
);
1522 return WERR_INVALID_PRINTER_NAME
;
1525 get_current_user(&user
, p
);
1528 * First case: the user is opening the print server:
1530 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1531 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1533 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1534 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1535 * or if the user is listed in the smb.conf printer admin parameter.
1537 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1538 * client view printer folder, but does not show the MSAPW.
1540 * Note: this test needs code to check access rights here too. Jeremy
1541 * could you look at this?
1543 * Second case: the user is opening a printer:
1544 * NT doesn't let us connect to a printer if the connecting user
1545 * doesn't have print permission.
1548 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1550 /* Printserver handles use global struct... */
1554 /* Map standard access rights to object specific access rights */
1556 se_map_standard(&printer_default
->access_required
,
1557 &printserver_std_mapping
);
1559 /* Deny any object specific bits that don't apply to print
1560 servers (i.e printer and job specific bits) */
1562 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1564 if (printer_default
->access_required
&
1565 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1566 DEBUG(3, ("access DENIED for non-printserver bits"));
1567 close_printer_handle(p
, handle
);
1568 return WERR_ACCESS_DENIED
;
1571 /* Allow admin access */
1573 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1575 if (!lp_ms_add_printer_wizard()) {
1576 close_printer_handle(p
, handle
);
1577 return WERR_ACCESS_DENIED
;
1580 /* if the user is not root and not a printer admin, then fail */
1583 && !user_in_list(uidtoname(user
.uid
), lp_printer_admin(snum
)) )
1585 close_printer_handle(p
, handle
);
1586 return WERR_ACCESS_DENIED
;
1589 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1593 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1596 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1597 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1599 /* We fall through to return WERR_OK */
1604 /* NT doesn't let us connect to a printer if the connecting user
1605 doesn't have print permission. */
1607 if (!get_printer_snum(p
, handle
, &snum
))
1610 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1612 /* map an empty access mask to the minimum access mask */
1613 if (printer_default
->access_required
== 0x0)
1614 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1617 * If we are not serving the printer driver for this printer,
1618 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1619 * will keep NT clients happy --jerry
1622 if (lp_use_client_driver(snum
)
1623 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1625 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1628 /* check smb.conf parameters and the the sec_desc */
1630 if (!user_ok(uidtoname(user
.uid
), snum
) || !print_access_check(&user
, snum
, printer_default
->access_required
)) {
1631 DEBUG(3, ("access DENIED for printer open\n"));
1632 close_printer_handle(p
, handle
);
1633 return WERR_ACCESS_DENIED
;
1636 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1637 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1638 close_printer_handle(p
, handle
);
1639 return WERR_ACCESS_DENIED
;
1642 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1643 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1645 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1647 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1648 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1652 Printer
->access_granted
= printer_default
->access_required
;
1655 * If the client sent a devmode in the OpenPrinter() call, then
1656 * save it here in case we get a job submission on this handle
1659 if ( (Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTSERVER
)
1660 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1662 convert_devicemode( Printer
->dev
.handlename
, q_u
->printer_default
.devmode_cont
.devmode
,
1663 &Printer
->nt_devmode
);
1669 /****************************************************************************
1670 ****************************************************************************/
1672 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1673 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1679 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
1688 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1689 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1695 printer
->info_3
=NULL
;
1696 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1700 printer
->info_6
=NULL
;
1701 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1711 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1712 NT_DEVICEMODE
**pp_nt_devmode
)
1714 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1717 * Ensure nt_devmode is a valid pointer
1718 * as we will be overwriting it.
1721 if (nt_devmode
== NULL
) {
1722 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1723 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1727 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1728 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1730 nt_devmode
->specversion
=devmode
->specversion
;
1731 nt_devmode
->driverversion
=devmode
->driverversion
;
1732 nt_devmode
->size
=devmode
->size
;
1733 nt_devmode
->fields
=devmode
->fields
;
1734 nt_devmode
->orientation
=devmode
->orientation
;
1735 nt_devmode
->papersize
=devmode
->papersize
;
1736 nt_devmode
->paperlength
=devmode
->paperlength
;
1737 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1738 nt_devmode
->scale
=devmode
->scale
;
1739 nt_devmode
->copies
=devmode
->copies
;
1740 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1741 nt_devmode
->printquality
=devmode
->printquality
;
1742 nt_devmode
->color
=devmode
->color
;
1743 nt_devmode
->duplex
=devmode
->duplex
;
1744 nt_devmode
->yresolution
=devmode
->yresolution
;
1745 nt_devmode
->ttoption
=devmode
->ttoption
;
1746 nt_devmode
->collate
=devmode
->collate
;
1748 nt_devmode
->logpixels
=devmode
->logpixels
;
1749 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1750 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1751 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1752 nt_devmode
->displayflags
=devmode
->displayflags
;
1753 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1754 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1755 nt_devmode
->icmintent
=devmode
->icmintent
;
1756 nt_devmode
->mediatype
=devmode
->mediatype
;
1757 nt_devmode
->dithertype
=devmode
->dithertype
;
1758 nt_devmode
->reserved1
=devmode
->reserved1
;
1759 nt_devmode
->reserved2
=devmode
->reserved2
;
1760 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1761 nt_devmode
->panningheight
=devmode
->panningheight
;
1764 * Only change private and driverextra if the incoming devmode
1765 * has a new one. JRA.
1768 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1769 SAFE_FREE(nt_devmode
->private);
1770 nt_devmode
->driverextra
=devmode
->driverextra
;
1771 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
1773 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1776 *pp_nt_devmode
= nt_devmode
;
1781 /********************************************************************
1782 * _spoolss_enddocprinter_internal.
1783 ********************************************************************/
1785 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1787 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1791 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1795 if (!get_printer_snum(p
, handle
, &snum
))
1798 Printer
->document_started
=False
;
1799 print_job_end(snum
, Printer
->jobid
,True
);
1800 /* error codes unhandled so far ... */
1805 /********************************************************************
1806 * api_spoolss_closeprinter
1807 ********************************************************************/
1809 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1811 POLICY_HND
*handle
= &q_u
->handle
;
1813 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1815 if (Printer
&& Printer
->document_started
)
1816 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1818 if (!close_printer_handle(p
, handle
))
1821 /* clear the returned printer handle. Observed behavior
1822 from Win2k server. Don't think this really matters.
1823 Previous code just copied the value of the closed
1826 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1831 /********************************************************************
1832 * api_spoolss_deleteprinter
1834 ********************************************************************/
1836 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1838 POLICY_HND
*handle
= &q_u
->handle
;
1839 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1842 if (Printer
&& Printer
->document_started
)
1843 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1845 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1847 result
= delete_printer_handle(p
, handle
);
1849 update_c_setprinter(False
);
1854 /*******************************************************************
1855 * static function to lookup the version id corresponding to an
1856 * long architecture string
1857 ******************************************************************/
1859 static int get_version_id (char * arch
)
1862 struct table_node archi_table
[]= {
1864 {"Windows 4.0", "WIN40", 0 },
1865 {"Windows NT x86", "W32X86", 2 },
1866 {"Windows NT R4000", "W32MIPS", 2 },
1867 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1868 {"Windows NT PowerPC", "W32PPC", 2 },
1872 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1874 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1875 return (archi_table
[i
].version
);
1881 /********************************************************************
1882 * _spoolss_deleteprinterdriver
1883 ********************************************************************/
1885 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1889 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1890 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
1892 struct current_user user
;
1894 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1896 get_current_user(&user
, p
);
1898 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1899 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1901 /* check that we have a valid driver name first */
1903 if ((version
=get_version_id(arch
)) == -1)
1904 return WERR_INVALID_ENVIRONMENT
;
1907 ZERO_STRUCT(info_win2k
);
1909 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
1911 /* try for Win2k driver if "Windows NT x86" */
1913 if ( version
== 2 ) {
1915 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
1916 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1920 /* otherwise it was a failure */
1922 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1928 if (printer_driver_in_use(info
.info_3
)) {
1929 status
= WERR_PRINTER_DRIVER_IN_USE
;
1935 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
1937 /* if we get to here, we now have 2 driver info structures to remove */
1938 /* remove the Win2k driver first*/
1940 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, False
);
1941 free_a_printer_driver( info_win2k
, 3 );
1943 /* this should not have failed---if it did, report to client */
1944 if ( !W_ERROR_IS_OK(status_win2k
) )
1949 status
= delete_printer_driver(info
.info_3
, &user
, version
, False
);
1951 /* if at least one of the deletes succeeded return OK */
1953 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
1957 free_a_printer_driver( info
, 3 );
1962 /********************************************************************
1963 * spoolss_deleteprinterdriverex
1964 ********************************************************************/
1966 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
1970 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1971 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
1973 uint32 flags
= q_u
->delete_flags
;
1975 struct current_user user
;
1977 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1979 get_current_user(&user
, p
);
1981 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1982 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1984 /* check that we have a valid driver name first */
1985 if ((version
=get_version_id(arch
)) == -1) {
1986 /* this is what NT returns */
1987 return WERR_INVALID_ENVIRONMENT
;
1990 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
1991 version
= q_u
->version
;
1994 ZERO_STRUCT(info_win2k
);
1996 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
1998 if ( !W_ERROR_IS_OK(status
) )
2001 * if the client asked for a specific version,
2002 * or this is something other than Windows NT x86,
2006 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2009 /* try for Win2k driver if "Windows NT x86" */
2012 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2013 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2018 if ( printer_driver_in_use(info
.info_3
) ) {
2019 status
= WERR_PRINTER_DRIVER_IN_USE
;
2024 * we have a couple of cases to consider.
2025 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2026 * then the delete should fail if **any** files overlap with
2028 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2029 * non-overlapping files
2030 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2031 * is set, the do not delete any files
2032 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2035 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2037 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2039 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2040 /* no idea of the correct error here */
2041 status
= WERR_ACCESS_DENIED
;
2046 /* also check for W32X86/3 if necessary; maybe we already have? */
2048 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2049 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2052 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2053 /* no idea of the correct error here */
2054 free_a_printer_driver( info_win2k
, 3 );
2055 status
= WERR_ACCESS_DENIED
;
2059 /* if we get to here, we now have 2 driver info structures to remove */
2060 /* remove the Win2k driver first*/
2062 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, delete_files
);
2063 free_a_printer_driver( info_win2k
, 3 );
2065 /* this should not have failed---if it did, report to client */
2067 if ( !W_ERROR_IS_OK(status_win2k
) )
2072 status
= delete_printer_driver(info
.info_3
, &user
, version
, delete_files
);
2074 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2077 free_a_printer_driver( info
, 3 );
2083 /****************************************************************************
2084 Internal routine for retreiving printerdata
2085 ***************************************************************************/
2087 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2088 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2089 uint32
*needed
, uint32 in_size
)
2091 REGISTRY_VALUE
*val
;
2094 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2095 return WERR_BADFILE
;
2097 *type
= regval_type( val
);
2099 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2101 size
= regval_size( val
);
2103 /* copy the min(in_size, len) */
2106 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2108 /* special case for 0 length values */
2110 if ( (*data
= (uint8
*)talloc_memdup(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2114 if ( (*data
= (uint8
*)talloc_zero(ctx
, in_size
)) == NULL
)
2123 DEBUG(5,("get_printer_dataex: copy done\n"));
2128 /****************************************************************************
2129 Internal routine for removing printerdata
2130 ***************************************************************************/
2132 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2134 delete_printer_data( printer
->info_2
, key
, value
);
2136 return mod_a_printer(*printer
, 2);
2139 /****************************************************************************
2140 Internal routine for storing printerdata
2141 ***************************************************************************/
2143 static WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2144 uint32 type
, uint8
*data
, int real_len
)
2146 delete_printer_data( printer
->info_2
, key
, value
);
2148 add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2150 return mod_a_printer(*printer
, 2);
2153 /********************************************************************
2154 GetPrinterData on a printer server Handle.
2155 ********************************************************************/
2157 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2161 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2163 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2165 if((*data
= (uint8
*)talloc_zero(ctx
, 4*sizeof(uint8
) )) == NULL
)
2171 if (!StrCaseCmp(value
, "BeepEnabled")) {
2173 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2175 SIVAL(*data
, 0, 0x00);
2180 if (!StrCaseCmp(value
, "EventLog")) {
2182 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2184 /* formally was 0x1b */
2185 SIVAL(*data
, 0, 0x0);
2190 if (!StrCaseCmp(value
, "NetPopup")) {
2192 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2194 SIVAL(*data
, 0, 0x00);
2199 if (!StrCaseCmp(value
, "MajorVersion")) {
2201 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2212 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2215 fstrcpy(string
, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH
));
2217 *needed
= 2*(strlen(string
)+1);
2218 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2220 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2222 /* it's done by hand ready to go on the wire */
2223 for (i
=0; i
<strlen(string
); i
++) {
2224 (*data
)[2*i
]=string
[i
];
2225 (*data
)[2*i
+1]='\0';
2230 if (!StrCaseCmp(value
, "Architecture")) {
2231 pstring string
="Windows NT x86";
2233 *needed
= 2*(strlen(string
)+1);
2234 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2236 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2237 for (i
=0; i
<strlen(string
); i
++) {
2238 (*data
)[2*i
]=string
[i
];
2239 (*data
)[2*i
+1]='\0';
2244 if (!StrCaseCmp(value
, "DsPresent")) {
2246 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2248 SIVAL(*data
, 0, 0x01);
2253 if (!StrCaseCmp(value
, "DNSMachineName")) {
2256 if (!get_myfullname(hostname
))
2257 return WERR_BADFILE
;
2259 *needed
= 2*(strlen(hostname
)+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(hostname
); i
++) {
2264 (*data
)[2*i
]=hostname
[i
];
2265 (*data
)[2*i
+1]='\0';
2271 return WERR_BADFILE
;
2274 /********************************************************************
2275 * spoolss_getprinterdata
2276 ********************************************************************/
2278 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2280 POLICY_HND
*handle
= &q_u
->handle
;
2281 UNISTR2
*valuename
= &q_u
->valuename
;
2282 uint32 in_size
= q_u
->size
;
2283 uint32
*type
= &r_u
->type
;
2284 uint32
*out_size
= &r_u
->size
;
2285 uint8
**data
= &r_u
->data
;
2286 uint32
*needed
= &r_u
->needed
;
2289 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2290 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2294 * Reminder: when it's a string, the length is in BYTES
2295 * even if UNICODE is negociated.
2300 *out_size
= in_size
;
2302 /* in case of problem, return some default values */
2307 DEBUG(4,("_spoolss_getprinterdata\n"));
2310 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2311 status
= WERR_BADFID
;
2315 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2317 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2318 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2321 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2322 status
= WERR_BADFID
;
2326 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
2327 if ( !W_ERROR_IS_OK(status
) )
2330 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2332 if ( strequal(value
, "ChangeId") ) {
2334 *needed
= sizeof(uint32
);
2335 if ( (*data
= (uint8
*)talloc(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2336 status
= WERR_NOMEM
;
2339 **data
= printer
->info_2
->changeid
;
2343 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2346 if (*needed
> *out_size
)
2347 status
= WERR_MORE_DATA
;
2350 if ( !W_ERROR_IS_OK(status
) )
2352 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2354 /* reply this param doesn't exist */
2357 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
2359 free_a_printer( &printer
, 2 );
2368 /* cleanup & exit */
2371 free_a_printer( &printer
, 2 );
2376 /*********************************************************
2377 Connect to the client machine.
2378 **********************************************************/
2380 static BOOL
spoolss_connect_to_client(struct cli_state
*the_cli
, const char *remote_machine
)
2382 ZERO_STRUCTP(the_cli
);
2383 if(cli_initialise(the_cli
) == NULL
) {
2384 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2388 if(!resolve_name( remote_machine
, &the_cli
->dest_ip
, 0x20)) {
2389 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine
));
2390 cli_shutdown(the_cli
);
2394 if (ismyip(the_cli
->dest_ip
)) {
2395 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2396 cli_shutdown(the_cli
);
2400 if (!cli_connect(the_cli
, remote_machine
, &the_cli
->dest_ip
)) {
2401 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2402 cli_shutdown(the_cli
);
2406 if (!attempt_netbios_session_request(the_cli
, global_myname(), remote_machine
, &the_cli
->dest_ip
)) {
2407 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2409 cli_shutdown(the_cli
);
2413 the_cli
->protocol
= PROTOCOL_NT1
;
2415 if (!cli_negprot(the_cli
)) {
2416 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2417 cli_shutdown(the_cli
);
2421 if (the_cli
->protocol
!= PROTOCOL_NT1
) {
2422 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2423 cli_shutdown(the_cli
);
2428 * Do an anonymous session setup.
2431 if (!cli_session_setup(the_cli
, "", "", 0, "", 0, "")) {
2432 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2433 cli_shutdown(the_cli
);
2437 if (!(the_cli
->sec_mode
& 1)) {
2438 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine
));
2439 cli_shutdown(the_cli
);
2443 if (!cli_send_tconX(the_cli
, "IPC$", "IPC", "", 1)) {
2444 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2445 cli_shutdown(the_cli
);
2450 * Ok - we have an anonymous connection to the IPC$ share.
2451 * Now start the NT Domain stuff :-).
2454 if(cli_nt_session_open(the_cli
, PI_SPOOLSS
) == False
) {
2455 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
)));
2456 cli_nt_session_close(the_cli
);
2457 cli_ulogoff(the_cli
);
2458 cli_shutdown(the_cli
);
2465 /***************************************************************************
2466 Connect to the client.
2467 ****************************************************************************/
2469 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
, uint32 localprinter
, uint32 type
, POLICY_HND
*handle
)
2474 * If it's the first connection, contact the client
2475 * and connect to the IPC$ share anonumously
2477 if (smb_connections
==0) {
2478 fstring unix_printer
;
2480 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2482 if(!spoolss_connect_to_client(¬ify_cli
, unix_printer
))
2485 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message_list
);
2486 /* Tell the connections db we're now interested in printer
2487 * notify messages. */
2488 register_message_flags( True
, FLAG_MSG_PRINTING
);
2492 * Tell the specific printing tdb we want messages for this printer
2493 * by registering our PID.
2496 if (!print_notify_register_pid(snum
))
2497 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2501 result
= cli_spoolss_reply_open_printer(¬ify_cli
, notify_cli
.mem_ctx
, printer
, localprinter
,
2504 if (!W_ERROR_IS_OK(result
))
2505 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2506 dos_errstr(result
)));
2508 return (W_ERROR_IS_OK(result
));
2511 /********************************************************************
2513 * ReplyFindFirstPrinterChangeNotifyEx
2515 * before replying OK: status=0 a rpc call is made to the workstation
2516 * asking ReplyOpenPrinter
2518 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2519 * called from api_spoolss_rffpcnex
2520 ********************************************************************/
2522 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2524 POLICY_HND
*handle
= &q_u
->handle
;
2525 uint32 flags
= q_u
->flags
;
2526 uint32 options
= q_u
->options
;
2527 UNISTR2
*localmachine
= &q_u
->localmachine
;
2528 uint32 printerlocal
= q_u
->printerlocal
;
2530 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2532 /* store the notify value in the printer struct */
2534 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2537 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2541 Printer
->notify
.flags
=flags
;
2542 Printer
->notify
.options
=options
;
2543 Printer
->notify
.printerlocal
=printerlocal
;
2545 if (Printer
->notify
.option
)
2546 free_spool_notify_option(&Printer
->notify
.option
);
2548 Printer
->notify
.option
=dup_spool_notify_option(option
);
2550 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2551 sizeof(Printer
->notify
.localmachine
)-1);
2553 /* Connect to the client machine and send a ReplyOpenPrinter */
2555 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2557 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
2558 !get_printer_snum(p
, handle
, &snum
) )
2561 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2562 Printer
->notify
.printerlocal
, 1,
2563 &Printer
->notify
.client_hnd
))
2564 return WERR_SERVER_UNAVAILABLE
;
2566 Printer
->notify
.client_connected
=True
;
2571 /*******************************************************************
2572 * fill a notify_info_data with the servername
2573 ********************************************************************/
2575 void spoolss_notify_server_name(int snum
,
2576 SPOOL_NOTIFY_INFO_DATA
*data
,
2577 print_queue_struct
*queue
,
2578 NT_PRINTER_INFO_LEVEL
*printer
,
2579 TALLOC_CTX
*mem_ctx
)
2581 pstring temp_name
, temp
;
2584 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
2586 len
= rpcstr_push(temp
, temp_name
, sizeof(temp
)-2, STR_TERMINATE
);
2588 data
->notify_data
.data
.length
= len
;
2589 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2591 if (!data
->notify_data
.data
.string
) {
2592 data
->notify_data
.data
.length
= 0;
2596 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2599 /*******************************************************************
2600 * fill a notify_info_data with the printername (not including the servername).
2601 ********************************************************************/
2603 void spoolss_notify_printer_name(int snum
,
2604 SPOOL_NOTIFY_INFO_DATA
*data
,
2605 print_queue_struct
*queue
,
2606 NT_PRINTER_INFO_LEVEL
*printer
,
2607 TALLOC_CTX
*mem_ctx
)
2612 /* the notify name should not contain the \\server\ part */
2613 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2616 p
= printer
->info_2
->printername
;
2621 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2623 data
->notify_data
.data
.length
= len
;
2624 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2626 if (!data
->notify_data
.data
.string
) {
2627 data
->notify_data
.data
.length
= 0;
2631 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2634 /*******************************************************************
2635 * fill a notify_info_data with the servicename
2636 ********************************************************************/
2638 void spoolss_notify_share_name(int snum
,
2639 SPOOL_NOTIFY_INFO_DATA
*data
,
2640 print_queue_struct
*queue
,
2641 NT_PRINTER_INFO_LEVEL
*printer
,
2642 TALLOC_CTX
*mem_ctx
)
2647 len
= rpcstr_push(temp
, lp_servicename(snum
), 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 port name
2662 ********************************************************************/
2664 void spoolss_notify_port_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 /* even if it's strange, that's consistant in all the code */
2675 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2677 data
->notify_data
.data
.length
= len
;
2678 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2680 if (!data
->notify_data
.data
.string
) {
2681 data
->notify_data
.data
.length
= 0;
2685 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2688 /*******************************************************************
2689 * fill a notify_info_data with the printername
2690 * but it doesn't exist, have to see what to do
2691 ********************************************************************/
2693 void spoolss_notify_driver_name(int snum
,
2694 SPOOL_NOTIFY_INFO_DATA
*data
,
2695 print_queue_struct
*queue
,
2696 NT_PRINTER_INFO_LEVEL
*printer
,
2697 TALLOC_CTX
*mem_ctx
)
2702 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2704 data
->notify_data
.data
.length
= len
;
2705 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2707 if (!data
->notify_data
.data
.string
) {
2708 data
->notify_data
.data
.length
= 0;
2712 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2715 /*******************************************************************
2716 * fill a notify_info_data with the comment
2717 ********************************************************************/
2719 void spoolss_notify_comment(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 if (*printer
->info_2
->comment
== '\0')
2729 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2731 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2733 data
->notify_data
.data
.length
= len
;
2734 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2736 if (!data
->notify_data
.data
.string
) {
2737 data
->notify_data
.data
.length
= 0;
2741 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2744 /*******************************************************************
2745 * fill a notify_info_data with the comment
2746 * location = "Room 1, floor 2, building 3"
2747 ********************************************************************/
2749 void spoolss_notify_location(int snum
,
2750 SPOOL_NOTIFY_INFO_DATA
*data
,
2751 print_queue_struct
*queue
,
2752 NT_PRINTER_INFO_LEVEL
*printer
,
2753 TALLOC_CTX
*mem_ctx
)
2758 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2760 data
->notify_data
.data
.length
= len
;
2761 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2763 if (!data
->notify_data
.data
.string
) {
2764 data
->notify_data
.data
.length
= 0;
2768 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2771 /*******************************************************************
2772 * fill a notify_info_data with the device mode
2773 * jfm:xxxx don't to it for know but that's a real problem !!!
2774 ********************************************************************/
2776 static void spoolss_notify_devmode(int snum
,
2777 SPOOL_NOTIFY_INFO_DATA
*data
,
2778 print_queue_struct
*queue
,
2779 NT_PRINTER_INFO_LEVEL
*printer
,
2780 TALLOC_CTX
*mem_ctx
)
2784 /*******************************************************************
2785 * fill a notify_info_data with the separator file name
2786 ********************************************************************/
2788 void spoolss_notify_sepfile(int snum
,
2789 SPOOL_NOTIFY_INFO_DATA
*data
,
2790 print_queue_struct
*queue
,
2791 NT_PRINTER_INFO_LEVEL
*printer
,
2792 TALLOC_CTX
*mem_ctx
)
2797 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2799 data
->notify_data
.data
.length
= len
;
2800 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2802 if (!data
->notify_data
.data
.string
) {
2803 data
->notify_data
.data
.length
= 0;
2807 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2810 /*******************************************************************
2811 * fill a notify_info_data with the print processor
2812 * jfm:xxxx return always winprint to indicate we don't do anything to it
2813 ********************************************************************/
2815 void spoolss_notify_print_processor(int snum
,
2816 SPOOL_NOTIFY_INFO_DATA
*data
,
2817 print_queue_struct
*queue
,
2818 NT_PRINTER_INFO_LEVEL
*printer
,
2819 TALLOC_CTX
*mem_ctx
)
2824 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
2826 data
->notify_data
.data
.length
= len
;
2827 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2829 if (!data
->notify_data
.data
.string
) {
2830 data
->notify_data
.data
.length
= 0;
2834 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2837 /*******************************************************************
2838 * fill a notify_info_data with the print processor options
2839 * jfm:xxxx send an empty string
2840 ********************************************************************/
2842 void spoolss_notify_parameters(int snum
,
2843 SPOOL_NOTIFY_INFO_DATA
*data
,
2844 print_queue_struct
*queue
,
2845 NT_PRINTER_INFO_LEVEL
*printer
,
2846 TALLOC_CTX
*mem_ctx
)
2851 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
2853 data
->notify_data
.data
.length
= len
;
2854 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2856 if (!data
->notify_data
.data
.string
) {
2857 data
->notify_data
.data
.length
= 0;
2861 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2864 /*******************************************************************
2865 * fill a notify_info_data with the data type
2866 * jfm:xxxx always send RAW as data type
2867 ********************************************************************/
2869 void spoolss_notify_datatype(int snum
,
2870 SPOOL_NOTIFY_INFO_DATA
*data
,
2871 print_queue_struct
*queue
,
2872 NT_PRINTER_INFO_LEVEL
*printer
,
2873 TALLOC_CTX
*mem_ctx
)
2878 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
2880 data
->notify_data
.data
.length
= len
;
2881 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2883 if (!data
->notify_data
.data
.string
) {
2884 data
->notify_data
.data
.length
= 0;
2888 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2891 /*******************************************************************
2892 * fill a notify_info_data with the security descriptor
2893 * jfm:xxxx send an null pointer to say no security desc
2894 * have to implement security before !
2895 ********************************************************************/
2897 static void spoolss_notify_security_desc(int snum
,
2898 SPOOL_NOTIFY_INFO_DATA
*data
,
2899 print_queue_struct
*queue
,
2900 NT_PRINTER_INFO_LEVEL
*printer
,
2901 TALLOC_CTX
*mem_ctx
)
2903 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
2904 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
2907 /*******************************************************************
2908 * fill a notify_info_data with the attributes
2909 * jfm:xxxx a samba printer is always shared
2910 ********************************************************************/
2912 void spoolss_notify_attributes(int snum
,
2913 SPOOL_NOTIFY_INFO_DATA
*data
,
2914 print_queue_struct
*queue
,
2915 NT_PRINTER_INFO_LEVEL
*printer
,
2916 TALLOC_CTX
*mem_ctx
)
2918 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
2919 data
->notify_data
.value
[1] = 0;
2922 /*******************************************************************
2923 * fill a notify_info_data with the priority
2924 ********************************************************************/
2926 static void spoolss_notify_priority(int snum
,
2927 SPOOL_NOTIFY_INFO_DATA
*data
,
2928 print_queue_struct
*queue
,
2929 NT_PRINTER_INFO_LEVEL
*printer
,
2930 TALLOC_CTX
*mem_ctx
)
2932 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
2933 data
->notify_data
.value
[1] = 0;
2936 /*******************************************************************
2937 * fill a notify_info_data with the default priority
2938 ********************************************************************/
2940 static void spoolss_notify_default_priority(int snum
,
2941 SPOOL_NOTIFY_INFO_DATA
*data
,
2942 print_queue_struct
*queue
,
2943 NT_PRINTER_INFO_LEVEL
*printer
,
2944 TALLOC_CTX
*mem_ctx
)
2946 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
2947 data
->notify_data
.value
[1] = 0;
2950 /*******************************************************************
2951 * fill a notify_info_data with the start time
2952 ********************************************************************/
2954 static void spoolss_notify_start_time(int snum
,
2955 SPOOL_NOTIFY_INFO_DATA
*data
,
2956 print_queue_struct
*queue
,
2957 NT_PRINTER_INFO_LEVEL
*printer
,
2958 TALLOC_CTX
*mem_ctx
)
2960 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
2961 data
->notify_data
.value
[1] = 0;
2964 /*******************************************************************
2965 * fill a notify_info_data with the until time
2966 ********************************************************************/
2968 static void spoolss_notify_until_time(int snum
,
2969 SPOOL_NOTIFY_INFO_DATA
*data
,
2970 print_queue_struct
*queue
,
2971 NT_PRINTER_INFO_LEVEL
*printer
,
2972 TALLOC_CTX
*mem_ctx
)
2974 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
2975 data
->notify_data
.value
[1] = 0;
2978 /*******************************************************************
2979 * fill a notify_info_data with the status
2980 ********************************************************************/
2982 static void spoolss_notify_status(int snum
,
2983 SPOOL_NOTIFY_INFO_DATA
*data
,
2984 print_queue_struct
*queue
,
2985 NT_PRINTER_INFO_LEVEL
*printer
,
2986 TALLOC_CTX
*mem_ctx
)
2988 print_status_struct status
;
2990 print_queue_length(snum
, &status
);
2991 data
->notify_data
.value
[0]=(uint32
) status
.status
;
2992 data
->notify_data
.value
[1] = 0;
2995 /*******************************************************************
2996 * fill a notify_info_data with the number of jobs queued
2997 ********************************************************************/
2999 void spoolss_notify_cjobs(int snum
,
3000 SPOOL_NOTIFY_INFO_DATA
*data
,
3001 print_queue_struct
*queue
,
3002 NT_PRINTER_INFO_LEVEL
*printer
,
3003 TALLOC_CTX
*mem_ctx
)
3005 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3006 data
->notify_data
.value
[1] = 0;
3009 /*******************************************************************
3010 * fill a notify_info_data with the average ppm
3011 ********************************************************************/
3013 static void spoolss_notify_average_ppm(int snum
,
3014 SPOOL_NOTIFY_INFO_DATA
*data
,
3015 print_queue_struct
*queue
,
3016 NT_PRINTER_INFO_LEVEL
*printer
,
3017 TALLOC_CTX
*mem_ctx
)
3019 /* always respond 8 pages per minutes */
3020 /* a little hard ! */
3021 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3022 data
->notify_data
.value
[1] = 0;
3025 /*******************************************************************
3026 * fill a notify_info_data with username
3027 ********************************************************************/
3029 static void spoolss_notify_username(int snum
,
3030 SPOOL_NOTIFY_INFO_DATA
*data
,
3031 print_queue_struct
*queue
,
3032 NT_PRINTER_INFO_LEVEL
*printer
,
3033 TALLOC_CTX
*mem_ctx
)
3038 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3040 data
->notify_data
.data
.length
= len
;
3041 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3043 if (!data
->notify_data
.data
.string
) {
3044 data
->notify_data
.data
.length
= 0;
3048 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3051 /*******************************************************************
3052 * fill a notify_info_data with job status
3053 ********************************************************************/
3055 static void spoolss_notify_job_status(int snum
,
3056 SPOOL_NOTIFY_INFO_DATA
*data
,
3057 print_queue_struct
*queue
,
3058 NT_PRINTER_INFO_LEVEL
*printer
,
3059 TALLOC_CTX
*mem_ctx
)
3061 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3062 data
->notify_data
.value
[1] = 0;
3065 /*******************************************************************
3066 * fill a notify_info_data with job name
3067 ********************************************************************/
3069 static void spoolss_notify_job_name(int snum
,
3070 SPOOL_NOTIFY_INFO_DATA
*data
,
3071 print_queue_struct
*queue
,
3072 NT_PRINTER_INFO_LEVEL
*printer
,
3073 TALLOC_CTX
*mem_ctx
)
3078 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3080 data
->notify_data
.data
.length
= len
;
3081 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3083 if (!data
->notify_data
.data
.string
) {
3084 data
->notify_data
.data
.length
= 0;
3088 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3091 /*******************************************************************
3092 * fill a notify_info_data with job status
3093 ********************************************************************/
3095 static void spoolss_notify_job_status_string(int snum
,
3096 SPOOL_NOTIFY_INFO_DATA
*data
,
3097 print_queue_struct
*queue
,
3098 NT_PRINTER_INFO_LEVEL
*printer
,
3099 TALLOC_CTX
*mem_ctx
)
3102 * Now we're returning job status codes we just return a "" here. JRA.
3109 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3112 switch (queue
->status
) {
3117 p
= ""; /* NT provides the paused string */
3126 #endif /* NO LONGER NEEDED. */
3128 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3130 data
->notify_data
.data
.length
= len
;
3131 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3133 if (!data
->notify_data
.data
.string
) {
3134 data
->notify_data
.data
.length
= 0;
3138 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3141 /*******************************************************************
3142 * fill a notify_info_data with job time
3143 ********************************************************************/
3145 static void spoolss_notify_job_time(int snum
,
3146 SPOOL_NOTIFY_INFO_DATA
*data
,
3147 print_queue_struct
*queue
,
3148 NT_PRINTER_INFO_LEVEL
*printer
,
3149 TALLOC_CTX
*mem_ctx
)
3151 data
->notify_data
.value
[0]=0x0;
3152 data
->notify_data
.value
[1]=0;
3155 /*******************************************************************
3156 * fill a notify_info_data with job size
3157 ********************************************************************/
3159 static void spoolss_notify_job_size(int snum
,
3160 SPOOL_NOTIFY_INFO_DATA
*data
,
3161 print_queue_struct
*queue
,
3162 NT_PRINTER_INFO_LEVEL
*printer
,
3163 TALLOC_CTX
*mem_ctx
)
3165 data
->notify_data
.value
[0]=queue
->size
;
3166 data
->notify_data
.value
[1]=0;
3169 /*******************************************************************
3170 * fill a notify_info_data with page info
3171 ********************************************************************/
3172 static void spoolss_notify_total_pages(int snum
,
3173 SPOOL_NOTIFY_INFO_DATA
*data
,
3174 print_queue_struct
*queue
,
3175 NT_PRINTER_INFO_LEVEL
*printer
,
3176 TALLOC_CTX
*mem_ctx
)
3178 data
->notify_data
.value
[0]=queue
->page_count
;
3179 data
->notify_data
.value
[1]=0;
3182 /*******************************************************************
3183 * fill a notify_info_data with pages printed info.
3184 ********************************************************************/
3185 static void spoolss_notify_pages_printed(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]=0; /* Add code when back-end tracks this */
3192 data
->notify_data
.value
[1]=0;
3195 /*******************************************************************
3196 Fill a notify_info_data with job position.
3197 ********************************************************************/
3199 static void spoolss_notify_job_position(int snum
,
3200 SPOOL_NOTIFY_INFO_DATA
*data
,
3201 print_queue_struct
*queue
,
3202 NT_PRINTER_INFO_LEVEL
*printer
,
3203 TALLOC_CTX
*mem_ctx
)
3205 data
->notify_data
.value
[0]=queue
->job
;
3206 data
->notify_data
.value
[1]=0;
3209 /*******************************************************************
3210 Fill a notify_info_data with submitted time.
3211 ********************************************************************/
3213 static void spoolss_notify_submitted_time(int snum
,
3214 SPOOL_NOTIFY_INFO_DATA
*data
,
3215 print_queue_struct
*queue
,
3216 NT_PRINTER_INFO_LEVEL
*printer
,
3217 TALLOC_CTX
*mem_ctx
)
3224 t
=gmtime(&queue
->time
);
3226 len
= sizeof(SYSTEMTIME
);
3228 data
->notify_data
.data
.length
= len
;
3229 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3231 if (!data
->notify_data
.data
.string
) {
3232 data
->notify_data
.data
.length
= 0;
3236 make_systemtime(&st
, t
);
3239 * Systemtime must be linearized as a set of UINT16's.
3240 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3243 p
= (char *)data
->notify_data
.data
.string
;
3244 SSVAL(p
, 0, st
.year
);
3245 SSVAL(p
, 2, st
.month
);
3246 SSVAL(p
, 4, st
.dayofweek
);
3247 SSVAL(p
, 6, st
.day
);
3248 SSVAL(p
, 8, st
.hour
);
3249 SSVAL(p
, 10, st
.minute
);
3250 SSVAL(p
, 12, st
.second
);
3251 SSVAL(p
, 14, st
.milliseconds
);
3254 struct s_notify_info_data_table
3260 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3261 print_queue_struct
*queue
,
3262 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3265 /* A table describing the various print notification constants and
3266 whether the notification data is a pointer to a variable sized
3267 buffer, a one value uint32 or a two value uint32. */
3269 static const struct s_notify_info_data_table notify_info_data_table
[] =
3271 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3272 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3273 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3274 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3275 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3276 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3277 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3278 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3279 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3280 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3281 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3282 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3283 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3284 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3285 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3286 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3287 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3288 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3289 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3290 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3291 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3292 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3293 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3294 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3295 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3296 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3297 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3298 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3299 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3300 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3301 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3302 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3303 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3304 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3305 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3306 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3307 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3308 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3309 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3310 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3311 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3312 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3313 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3314 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3315 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3316 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3317 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3318 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3319 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3322 /*******************************************************************
3323 Return the size of info_data structure.
3324 ********************************************************************/
3326 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3330 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++)
3332 if ( (notify_info_data_table
[i
].type
== type
)
3333 && (notify_info_data_table
[i
].field
== field
) )
3335 switch(notify_info_data_table
[i
].size
)
3337 case NOTIFY_ONE_VALUE
:
3338 case NOTIFY_TWO_VALUE
:
3343 /* The only pointer notify data I have seen on
3344 the wire is the submitted time and this has
3345 the notify size set to 4. -tpot */
3347 case NOTIFY_POINTER
:
3350 case NOTIFY_SECDESC
:
3356 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3361 /*******************************************************************
3362 Return the type of notify_info_data.
3363 ********************************************************************/
3365 static int type_of_notify_info_data(uint16 type
, uint16 field
)
3369 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3370 if (notify_info_data_table
[i
].type
== type
&&
3371 notify_info_data_table
[i
].field
== field
)
3372 return notify_info_data_table
[i
].size
;
3378 /****************************************************************************
3379 ****************************************************************************/
3381 static int search_notify(uint16 type
, uint16 field
, int *value
)
3385 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3386 if (notify_info_data_table
[i
].type
== type
&&
3387 notify_info_data_table
[i
].field
== field
&&
3388 notify_info_data_table
[i
].fn
!= NULL
) {
3397 /****************************************************************************
3398 ****************************************************************************/
3400 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3402 info_data
->type
= type
;
3403 info_data
->field
= field
;
3404 info_data
->reserved
= 0;
3406 info_data
->size
= size_of_notify_info_data(type
, field
);
3407 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3414 /*******************************************************************
3416 * fill a notify_info struct with info asked
3418 ********************************************************************/
3420 static BOOL
construct_notify_printer_info(SPOOL_NOTIFY_INFO
*info
, int
3421 snum
, SPOOL_NOTIFY_OPTION_TYPE
3422 *option_type
, uint32 id
,
3423 TALLOC_CTX
*mem_ctx
)
3429 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3430 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3431 print_queue_struct
*queue
=NULL
;
3433 type
=option_type
->type
;
3435 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3436 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3437 option_type
->count
, lp_servicename(snum
)));
3439 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3442 for(field_num
=0; field_num
<option_type
->count
; field_num
++)
3444 field
= option_type
->fields
[field_num
];
3446 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3448 if (!search_notify(type
, field
, &j
) )
3451 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
)
3453 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3459 current_data
= &info
->data
[info
->count
];
3461 construct_info_data(current_data
, type
, field
, id
);
3463 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3464 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3466 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3472 free_a_printer(&printer
, 2);
3476 /*******************************************************************
3478 * fill a notify_info struct with info asked
3480 ********************************************************************/
3482 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3483 SPOOL_NOTIFY_INFO
*info
,
3484 NT_PRINTER_INFO_LEVEL
*printer
,
3485 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3486 *option_type
, uint32 id
,
3487 TALLOC_CTX
*mem_ctx
)
3493 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3495 DEBUG(4,("construct_notify_jobs_info\n"));
3497 type
= option_type
->type
;
3499 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3500 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3501 option_type
->count
));
3503 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3504 field
= option_type
->fields
[field_num
];
3506 if (!search_notify(type
, field
, &j
) )
3509 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
3510 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3513 else info
->data
= tid
;
3515 current_data
=&(info
->data
[info
->count
]);
3517 construct_info_data(current_data
, type
, field
, id
);
3518 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3527 * JFM: The enumeration is not that simple, it's even non obvious.
3529 * let's take an example: I want to monitor the PRINTER SERVER for
3530 * the printer's name and the number of jobs currently queued.
3531 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3532 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3534 * I have 3 printers on the back of my server.
3536 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3539 * 1 printer 1 name 1
3540 * 2 printer 1 cjob 1
3541 * 3 printer 2 name 2
3542 * 4 printer 2 cjob 2
3543 * 5 printer 3 name 3
3544 * 6 printer 3 name 3
3546 * that's the print server case, the printer case is even worse.
3549 /*******************************************************************
3551 * enumerate all printers on the printserver
3552 * fill a notify_info struct with info asked
3554 ********************************************************************/
3556 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3557 SPOOL_NOTIFY_INFO
*info
,
3558 TALLOC_CTX
*mem_ctx
)
3561 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3562 int n_services
=lp_numservices();
3565 SPOOL_NOTIFY_OPTION
*option
;
3566 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3568 DEBUG(4,("printserver_notify_info\n"));
3573 option
=Printer
->notify
.option
;
3579 for (i
=0; i
<option
->count
; i
++) {
3580 option_type
=&(option
->ctr
.type
[i
]);
3582 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3585 for (snum
=0; snum
<n_services
; snum
++)
3587 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3588 construct_notify_printer_info ( info
, snum
, option_type
, snum
, mem_ctx
);
3594 * Debugging information, don't delete.
3597 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3598 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3599 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3601 for (i
=0; i
<info
->count
; i
++) {
3602 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3603 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3604 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3611 /*******************************************************************
3613 * fill a notify_info struct with info asked
3615 ********************************************************************/
3617 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3618 TALLOC_CTX
*mem_ctx
)
3621 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3624 SPOOL_NOTIFY_OPTION
*option
;
3625 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3627 print_queue_struct
*queue
=NULL
;
3628 print_status_struct status
;
3630 DEBUG(4,("printer_notify_info\n"));
3635 option
=Printer
->notify
.option
;
3641 get_printer_snum(p
, hnd
, &snum
);
3643 for (i
=0; i
<option
->count
; i
++) {
3644 option_type
=&option
->ctr
.type
[i
];
3646 switch ( option_type
->type
) {
3647 case PRINTER_NOTIFY_TYPE
:
3648 if(construct_notify_printer_info(info
, snum
,
3654 case JOB_NOTIFY_TYPE
: {
3655 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3657 count
= print_queue_status(snum
, &queue
, &status
);
3659 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2,
3660 lp_servicename(snum
))))
3663 for (j
=0; j
<count
; j
++) {
3664 construct_notify_jobs_info(&queue
[j
], info
,
3671 free_a_printer(&printer
, 2);
3681 * Debugging information, don't delete.
3684 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3685 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3686 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3688 for (i=0; i<info->count; i++) {
3689 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3690 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3691 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3697 /********************************************************************
3699 ********************************************************************/
3701 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3703 POLICY_HND
*handle
= &q_u
->handle
;
3704 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3706 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3707 WERROR result
= WERR_BADFID
;
3709 /* we always have a NOTIFY_INFO struct */
3713 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3714 OUR_HANDLE(handle
)));
3718 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3721 * We are now using the change value, and
3722 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3723 * I don't have a global notification system, I'm sending back all the
3724 * informations even when _NOTHING_ has changed.
3727 /* We need to keep track of the change value to send back in
3728 RRPCN replies otherwise our updates are ignored. */
3730 if (Printer
->notify
.client_connected
) {
3731 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3732 Printer
->notify
.change
= q_u
->change
;
3735 /* just ignore the SPOOL_NOTIFY_OPTION */
3737 switch (Printer
->printer_type
) {
3738 case PRINTER_HANDLE_IS_PRINTSERVER
:
3739 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3742 case PRINTER_HANDLE_IS_PRINTER
:
3743 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3751 /********************************************************************
3752 * construct_printer_info_0
3753 * fill a printer_info_0 struct
3754 ********************************************************************/
3756 static BOOL
construct_printer_info_0(PRINTER_INFO_0
*printer
, int snum
)
3760 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3761 counter_printer_0
*session_counter
;
3762 uint32 global_counter
;
3765 print_status_struct status
;
3767 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3770 count
= print_queue_length(snum
, &status
);
3772 /* check if we already have a counter for this printer */
3773 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
3775 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
3776 if (session_counter
->snum
== snum
)
3780 /* it's the first time, add it to the list */
3781 if (session_counter
==NULL
) {
3782 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
3783 free_a_printer(&ntprinter
, 2);
3786 ZERO_STRUCTP(session_counter
);
3787 session_counter
->snum
=snum
;
3788 session_counter
->counter
=0;
3789 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
3793 session_counter
->counter
++;
3796 * the global_counter should be stored in a TDB as it's common to all the clients
3797 * and should be zeroed on samba startup
3799 global_counter
=session_counter
->counter
;
3801 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3803 init_unistr(&printer
->printername
, chaine
);
3805 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_called_name());
3806 init_unistr(&printer
->servername
, chaine
);
3808 printer
->cjobs
= count
;
3809 printer
->total_jobs
= 0;
3810 printer
->total_bytes
= 0;
3812 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3813 t
=gmtime(&setuptime
);
3815 printer
->year
= t
->tm_year
+1900;
3816 printer
->month
= t
->tm_mon
+1;
3817 printer
->dayofweek
= t
->tm_wday
;
3818 printer
->day
= t
->tm_mday
;
3819 printer
->hour
= t
->tm_hour
;
3820 printer
->minute
= t
->tm_min
;
3821 printer
->second
= t
->tm_sec
;
3822 printer
->milliseconds
= 0;
3824 printer
->global_counter
= global_counter
;
3825 printer
->total_pages
= 0;
3827 printer
->major_version
= 0x0005; /* NT 5 */
3828 printer
->build_version
= 0x0893; /* build 2195 */
3830 printer
->major_version
= 0x0004; /* NT 4 */
3831 printer
->build_version
= 0x0565; /* build 1381 */
3833 printer
->unknown7
= 0x1;
3834 printer
->unknown8
= 0x0;
3835 printer
->unknown9
= 0x0;
3836 printer
->session_counter
= session_counter
->counter
;
3837 printer
->unknown11
= 0x0;
3838 printer
->printer_errors
= 0x0; /* number of print failure */
3839 printer
->unknown13
= 0x0;
3840 printer
->unknown14
= 0x1;
3841 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
3842 printer
->unknown16
= 0x0;
3843 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3844 printer
->unknown18
= 0x0;
3845 printer
->status
= nt_printq_status(status
.status
);
3846 printer
->unknown20
= 0x0;
3847 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3848 printer
->unknown22
= 0x0;
3849 printer
->unknown23
= 0x6; /* 6 ???*/
3850 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
3851 printer
->unknown25
= 0;
3852 printer
->unknown26
= 0;
3853 printer
->unknown27
= 0;
3854 printer
->unknown28
= 0;
3855 printer
->unknown29
= 0;
3857 free_a_printer(&ntprinter
,2);
3861 /********************************************************************
3862 * construct_printer_info_1
3863 * fill a printer_info_1 struct
3864 ********************************************************************/
3865 static BOOL
construct_printer_info_1(uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
3869 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3871 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3874 printer
->flags
=flags
;
3876 if (*ntprinter
->info_2
->comment
== '\0') {
3877 init_unistr(&printer
->comment
, lp_comment(snum
));
3878 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3879 ntprinter
->info_2
->drivername
, lp_comment(snum
));
3882 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3883 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3884 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
3887 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
3889 init_unistr(&printer
->description
, chaine
);
3890 init_unistr(&printer
->name
, chaine2
);
3892 free_a_printer(&ntprinter
,2);
3897 /****************************************************************************
3898 Free a DEVMODE struct.
3899 ****************************************************************************/
3901 static void free_dev_mode(DEVICEMODE
*dev
)
3906 SAFE_FREE(dev
->private);
3911 /****************************************************************************
3912 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3913 should be valid upon entry
3914 ****************************************************************************/
3916 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
3918 if ( !devmode
|| !ntdevmode
)
3921 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
3923 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
3925 devmode
->specversion
= ntdevmode
->specversion
;
3926 devmode
->driverversion
= ntdevmode
->driverversion
;
3927 devmode
->size
= ntdevmode
->size
;
3928 devmode
->driverextra
= ntdevmode
->driverextra
;
3929 devmode
->fields
= ntdevmode
->fields
;
3931 devmode
->orientation
= ntdevmode
->orientation
;
3932 devmode
->papersize
= ntdevmode
->papersize
;
3933 devmode
->paperlength
= ntdevmode
->paperlength
;
3934 devmode
->paperwidth
= ntdevmode
->paperwidth
;
3935 devmode
->scale
= ntdevmode
->scale
;
3936 devmode
->copies
= ntdevmode
->copies
;
3937 devmode
->defaultsource
= ntdevmode
->defaultsource
;
3938 devmode
->printquality
= ntdevmode
->printquality
;
3939 devmode
->color
= ntdevmode
->color
;
3940 devmode
->duplex
= ntdevmode
->duplex
;
3941 devmode
->yresolution
= ntdevmode
->yresolution
;
3942 devmode
->ttoption
= ntdevmode
->ttoption
;
3943 devmode
->collate
= ntdevmode
->collate
;
3944 devmode
->icmmethod
= ntdevmode
->icmmethod
;
3945 devmode
->icmintent
= ntdevmode
->icmintent
;
3946 devmode
->mediatype
= ntdevmode
->mediatype
;
3947 devmode
->dithertype
= ntdevmode
->dithertype
;
3949 if (ntdevmode
->private != NULL
) {
3950 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
3957 /****************************************************************************
3958 Create a DEVMODE struct. Returns malloced memory.
3959 ****************************************************************************/
3961 DEVICEMODE
*construct_dev_mode(int snum
)
3963 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3964 DEVICEMODE
*devmode
= NULL
;
3966 DEBUG(7,("construct_dev_mode\n"));
3968 DEBUGADD(8,("getting printer characteristics\n"));
3970 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3973 if ( !printer
->info_2
->devmode
) {
3974 DEBUG(5, ("BONG! There was no device mode!\n"));
3978 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
3979 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3983 ZERO_STRUCTP(devmode
);
3985 DEBUGADD(8,("loading DEVICEMODE\n"));
3987 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
3988 free_dev_mode( devmode
);
3993 free_a_printer(&printer
,2);
3998 /********************************************************************
3999 * construct_printer_info_2
4000 * fill a printer_info_2 struct
4001 ********************************************************************/
4003 static BOOL
construct_printer_info_2(PRINTER_INFO_2
*printer
, int snum
)
4006 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4008 print_status_struct status
;
4010 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4013 count
= print_queue_length(snum
, &status
);
4015 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4016 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4017 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4018 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4019 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4021 if (*ntprinter
->info_2
->comment
== '\0')
4022 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4024 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4026 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4027 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4028 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4029 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4030 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4032 printer
->attributes
= ntprinter
->info_2
->attributes
;
4034 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4035 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4036 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4037 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4038 printer
->status
= nt_printq_status(status
.status
); /* status */
4039 printer
->cjobs
= count
; /* jobs */
4040 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4042 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
4043 DEBUG(8, ("Returning NULL Devicemode!\n"));
4046 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4047 /* steal the printer info sec_desc structure. [badly done]. */
4048 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4049 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
4050 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
4051 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
4054 printer
->secdesc
= NULL
;
4057 free_a_printer(&ntprinter
, 2);
4061 /********************************************************************
4062 * construct_printer_info_3
4063 * fill a printer_info_3 struct
4064 ********************************************************************/
4066 static BOOL
construct_printer_info_3(PRINTER_INFO_3
**pp_printer
, int snum
)
4068 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4069 PRINTER_INFO_3
*printer
= NULL
;
4071 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4075 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
4076 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4080 ZERO_STRUCTP(printer
);
4082 printer
->flags
= 4; /* These are the components of the SD we are returning. */
4083 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4084 /* steal the printer info sec_desc structure. [badly done]. */
4085 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4089 * Set the flags for the components we are returning.
4092 if (printer
->secdesc
->owner_sid
)
4093 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
4095 if (printer
->secdesc
->grp_sid
)
4096 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
4098 if (printer
->secdesc
->dacl
)
4099 printer
->flags
|= DACL_SECURITY_INFORMATION
;
4101 if (printer
->secdesc
->sacl
)
4102 printer
->flags
|= SACL_SECURITY_INFORMATION
;
4105 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
4106 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
4107 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
4110 free_a_printer(&ntprinter
, 2);
4112 *pp_printer
= printer
;
4116 /********************************************************************
4117 * construct_printer_info_4
4118 * fill a printer_info_4 struct
4119 ********************************************************************/
4121 static BOOL
construct_printer_info_4(PRINTER_INFO_4
*printer
, int snum
)
4123 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4125 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4128 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4129 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4130 printer
->attributes
= ntprinter
->info_2
->attributes
;
4132 free_a_printer(&ntprinter
, 2);
4136 /********************************************************************
4137 * construct_printer_info_5
4138 * fill a printer_info_5 struct
4139 ********************************************************************/
4141 static BOOL
construct_printer_info_5(PRINTER_INFO_5
*printer
, int snum
)
4143 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4145 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4148 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4149 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* portname */
4150 printer
->attributes
= ntprinter
->info_2
->attributes
;
4151 printer
->device_not_selected_timeout
= 0x3a98;
4152 printer
->transmission_retry_timeout
= 0xafc8;
4154 free_a_printer(&ntprinter
, 2);
4158 /********************************************************************
4159 * construct_printer_info_7
4160 * fill a printer_info_7 struct
4161 ********************************************************************/
4163 static BOOL
construct_printer_info_7(PRINTER_INFO_7
*printer
, int snum
)
4165 char *guid_str
= NULL
;
4168 if (is_printer_published(snum
, &guid
)) {
4169 asprintf(&guid_str
, "{%s}", uuid_string_static(guid
));
4171 init_unistr(&printer
->guid
, guid_str
);
4172 printer
->action
= SPOOL_DS_PUBLISH
;
4174 init_unistr(&printer
->guid
, "");
4175 printer
->action
= SPOOL_DS_UNPUBLISH
;
4181 /********************************************************************
4182 Spoolss_enumprinters.
4183 ********************************************************************/
4185 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4189 int n_services
=lp_numservices();
4190 PRINTER_INFO_1
*tp
, *printers
=NULL
;
4191 PRINTER_INFO_1 current_prt
;
4193 DEBUG(4,("enum_all_printers_info_1\n"));
4195 for (snum
=0; snum
<n_services
; snum
++) {
4196 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4197 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4199 if (construct_printer_info_1(flags
, ¤t_prt
, snum
)) {
4200 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
4201 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4202 SAFE_FREE(printers
);
4207 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4209 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4215 /* check the required size. */
4216 for (i
=0; i
<*returned
; i
++)
4217 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4219 if (!alloc_buffer_size(buffer
, *needed
))
4220 return WERR_INSUFFICIENT_BUFFER
;
4222 /* fill the buffer with the structures */
4223 for (i
=0; i
<*returned
; i
++)
4224 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4227 SAFE_FREE(printers
);
4229 if (*needed
> offered
) {
4231 return WERR_INSUFFICIENT_BUFFER
;
4237 /********************************************************************
4238 enum_all_printers_info_1_local.
4239 *********************************************************************/
4241 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4243 DEBUG(4,("enum_all_printers_info_1_local\n"));
4245 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4248 /********************************************************************
4249 enum_all_printers_info_1_name.
4250 *********************************************************************/
4252 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4256 DEBUG(4,("enum_all_printers_info_1_name\n"));
4258 if ((name
[0] == '\\') && (name
[1] == '\\'))
4261 if (is_myname_or_ipaddr(s
)) {
4262 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4265 return WERR_INVALID_NAME
;
4268 /********************************************************************
4269 enum_all_printers_info_1_remote.
4270 *********************************************************************/
4272 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4274 PRINTER_INFO_1
*printer
;
4275 fstring printername
;
4278 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4280 /* JFM: currently it's more a place holder than anything else.
4281 * In the spooler world there is a notion of server registration.
4282 * the print servers are registring (sp ?) on the PDC (in the same domain)
4284 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4287 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4292 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4293 slprintf(desc
, sizeof(desc
)-1,"%s", get_called_name());
4294 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4296 init_unistr(&printer
->description
, desc
);
4297 init_unistr(&printer
->name
, printername
);
4298 init_unistr(&printer
->comment
, comment
);
4299 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4301 /* check the required size. */
4302 *needed
+= spoolss_size_printer_info_1(printer
);
4304 if (!alloc_buffer_size(buffer
, *needed
)) {
4306 return WERR_INSUFFICIENT_BUFFER
;
4309 /* fill the buffer with the structures */
4310 smb_io_printer_info_1("", buffer
, printer
, 0);
4315 if (*needed
> offered
) {
4317 return WERR_INSUFFICIENT_BUFFER
;
4323 /********************************************************************
4324 enum_all_printers_info_1_network.
4325 *********************************************************************/
4327 static WERROR
enum_all_printers_info_1_network(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4331 DEBUG(4,("enum_all_printers_info_1_network\n"));
4333 /* If we respond to a enum_printers level 1 on our name with flags
4334 set to PRINTER_ENUM_REMOTE with a list of printers then these
4335 printers incorrectly appear in the APW browse list.
4336 Specifically the printers for the server appear at the workgroup
4337 level where all the other servers in the domain are
4338 listed. Windows responds to this call with a
4339 WERR_CAN_NOT_COMPLETE so we should do the same. */
4341 if (name
[0] == '\\' && name
[1] == '\\')
4344 if (is_myname_or_ipaddr(s
))
4345 return WERR_CAN_NOT_COMPLETE
;
4347 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4350 /********************************************************************
4351 * api_spoolss_enumprinters
4353 * called from api_spoolss_enumprinters (see this to understand)
4354 ********************************************************************/
4356 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4360 int n_services
=lp_numservices();
4361 PRINTER_INFO_2
*tp
, *printers
=NULL
;
4362 PRINTER_INFO_2 current_prt
;
4364 for (snum
=0; snum
<n_services
; snum
++) {
4365 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4366 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4368 if (construct_printer_info_2(¤t_prt
, snum
)) {
4369 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
4370 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4371 SAFE_FREE(printers
);
4376 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
4377 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4383 /* check the required size. */
4384 for (i
=0; i
<*returned
; i
++)
4385 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4387 if (!alloc_buffer_size(buffer
, *needed
)) {
4388 for (i
=0; i
<*returned
; i
++) {
4389 free_devmode(printers
[i
].devmode
);
4391 SAFE_FREE(printers
);
4392 return WERR_INSUFFICIENT_BUFFER
;
4395 /* fill the buffer with the structures */
4396 for (i
=0; i
<*returned
; i
++)
4397 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4400 for (i
=0; i
<*returned
; i
++) {
4401 free_devmode(printers
[i
].devmode
);
4403 SAFE_FREE(printers
);
4405 if (*needed
> offered
) {
4407 return WERR_INSUFFICIENT_BUFFER
;
4413 /********************************************************************
4414 * handle enumeration of printers at level 1
4415 ********************************************************************/
4417 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4418 NEW_BUFFER
*buffer
, uint32 offered
,
4419 uint32
*needed
, uint32
*returned
)
4421 /* Not all the flags are equals */
4423 if (flags
& PRINTER_ENUM_LOCAL
)
4424 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4426 if (flags
& PRINTER_ENUM_NAME
)
4427 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4429 if (flags
& PRINTER_ENUM_REMOTE
)
4430 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4432 if (flags
& PRINTER_ENUM_NETWORK
)
4433 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4435 return WERR_OK
; /* NT4sp5 does that */
4438 /********************************************************************
4439 * handle enumeration of printers at level 2
4440 ********************************************************************/
4442 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4443 NEW_BUFFER
*buffer
, uint32 offered
,
4444 uint32
*needed
, uint32
*returned
)
4446 char *s
= servername
;
4448 if (flags
& PRINTER_ENUM_LOCAL
) {
4449 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4452 if (flags
& PRINTER_ENUM_NAME
) {
4453 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4455 if (is_myname_or_ipaddr(s
))
4456 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4458 return WERR_INVALID_NAME
;
4461 if (flags
& PRINTER_ENUM_REMOTE
)
4462 return WERR_UNKNOWN_LEVEL
;
4467 /********************************************************************
4468 * handle enumeration of printers at level 5
4469 ********************************************************************/
4471 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4472 NEW_BUFFER
*buffer
, uint32 offered
,
4473 uint32
*needed
, uint32
*returned
)
4475 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4479 /********************************************************************
4480 * api_spoolss_enumprinters
4482 * called from api_spoolss_enumprinters (see this to understand)
4483 ********************************************************************/
4485 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4487 uint32 flags
= q_u
->flags
;
4488 UNISTR2
*servername
= &q_u
->servername
;
4489 uint32 level
= q_u
->level
;
4490 NEW_BUFFER
*buffer
= NULL
;
4491 uint32 offered
= q_u
->offered
;
4492 uint32
*needed
= &r_u
->needed
;
4493 uint32
*returned
= &r_u
->returned
;
4497 /* that's an [in out] buffer */
4498 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4499 buffer
= r_u
->buffer
;
4501 DEBUG(4,("_spoolss_enumprinters\n"));
4508 * flags==PRINTER_ENUM_NAME
4509 * if name=="" then enumerates all printers
4510 * if name!="" then enumerate the printer
4511 * flags==PRINTER_ENUM_REMOTE
4512 * name is NULL, enumerate printers
4513 * Level 2: name!="" enumerates printers, name can't be NULL
4514 * Level 3: doesn't exist
4515 * Level 4: does a local registry lookup
4516 * Level 5: same as Level 2
4519 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4524 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4526 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4528 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4533 return WERR_UNKNOWN_LEVEL
;
4536 /****************************************************************************
4537 ****************************************************************************/
4539 static WERROR
getprinter_level_0(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4541 PRINTER_INFO_0
*printer
=NULL
;
4543 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
4546 construct_printer_info_0(printer
, snum
);
4548 /* check the required size. */
4549 *needed
+= spoolss_size_printer_info_0(printer
);
4551 if (!alloc_buffer_size(buffer
, *needed
)) {
4553 return WERR_INSUFFICIENT_BUFFER
;
4556 /* fill the buffer with the structures */
4557 smb_io_printer_info_0("", buffer
, printer
, 0);
4562 if (*needed
> offered
) {
4563 return WERR_INSUFFICIENT_BUFFER
;
4569 /****************************************************************************
4570 ****************************************************************************/
4572 static WERROR
getprinter_level_1(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4574 PRINTER_INFO_1
*printer
=NULL
;
4576 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4579 construct_printer_info_1(PRINTER_ENUM_ICON8
, printer
, snum
);
4581 /* check the required size. */
4582 *needed
+= spoolss_size_printer_info_1(printer
);
4584 if (!alloc_buffer_size(buffer
, *needed
)) {
4586 return WERR_INSUFFICIENT_BUFFER
;
4589 /* fill the buffer with the structures */
4590 smb_io_printer_info_1("", buffer
, printer
, 0);
4595 if (*needed
> offered
) {
4596 return WERR_INSUFFICIENT_BUFFER
;
4602 /****************************************************************************
4603 ****************************************************************************/
4605 static WERROR
getprinter_level_2(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4607 PRINTER_INFO_2
*printer
=NULL
;
4609 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
4612 construct_printer_info_2(printer
, snum
);
4614 /* check the required size. */
4615 *needed
+= spoolss_size_printer_info_2(printer
);
4617 if (!alloc_buffer_size(buffer
, *needed
)) {
4618 free_printer_info_2(printer
);
4619 return WERR_INSUFFICIENT_BUFFER
;
4622 /* fill the buffer with the structures */
4623 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
4624 free_printer_info_2(printer
);
4629 free_printer_info_2(printer
);
4631 if (*needed
> offered
) {
4632 return WERR_INSUFFICIENT_BUFFER
;
4638 /****************************************************************************
4639 ****************************************************************************/
4641 static WERROR
getprinter_level_3(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4643 PRINTER_INFO_3
*printer
=NULL
;
4645 if (!construct_printer_info_3(&printer
, snum
))
4648 /* check the required size. */
4649 *needed
+= spoolss_size_printer_info_3(printer
);
4651 if (!alloc_buffer_size(buffer
, *needed
)) {
4652 free_printer_info_3(printer
);
4653 return WERR_INSUFFICIENT_BUFFER
;
4656 /* fill the buffer with the structures */
4657 smb_io_printer_info_3("", buffer
, printer
, 0);
4660 free_printer_info_3(printer
);
4662 if (*needed
> offered
) {
4663 return WERR_INSUFFICIENT_BUFFER
;
4669 /****************************************************************************
4670 ****************************************************************************/
4672 static WERROR
getprinter_level_4(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4674 PRINTER_INFO_4
*printer
=NULL
;
4676 if((printer
=(PRINTER_INFO_4
*)malloc(sizeof(PRINTER_INFO_4
)))==NULL
)
4679 if (!construct_printer_info_4(printer
, snum
))
4682 /* check the required size. */
4683 *needed
+= spoolss_size_printer_info_4(printer
);
4685 if (!alloc_buffer_size(buffer
, *needed
)) {
4686 free_printer_info_4(printer
);
4687 return WERR_INSUFFICIENT_BUFFER
;
4690 /* fill the buffer with the structures */
4691 smb_io_printer_info_4("", buffer
, printer
, 0);
4694 free_printer_info_4(printer
);
4696 if (*needed
> offered
) {
4697 return WERR_INSUFFICIENT_BUFFER
;
4703 /****************************************************************************
4704 ****************************************************************************/
4706 static WERROR
getprinter_level_5(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4708 PRINTER_INFO_5
*printer
=NULL
;
4710 if((printer
=(PRINTER_INFO_5
*)malloc(sizeof(PRINTER_INFO_5
)))==NULL
)
4713 if (!construct_printer_info_5(printer
, snum
))
4716 /* check the required size. */
4717 *needed
+= spoolss_size_printer_info_5(printer
);
4719 if (!alloc_buffer_size(buffer
, *needed
)) {
4720 free_printer_info_5(printer
);
4721 return WERR_INSUFFICIENT_BUFFER
;
4724 /* fill the buffer with the structures */
4725 smb_io_printer_info_5("", buffer
, printer
, 0);
4728 free_printer_info_5(printer
);
4730 if (*needed
> offered
) {
4731 return WERR_INSUFFICIENT_BUFFER
;
4737 static WERROR
getprinter_level_7(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4739 PRINTER_INFO_7
*printer
=NULL
;
4741 if((printer
=(PRINTER_INFO_7
*)malloc(sizeof(PRINTER_INFO_7
)))==NULL
)
4744 if (!construct_printer_info_7(printer
, snum
))
4747 /* check the required size. */
4748 *needed
+= spoolss_size_printer_info_7(printer
);
4750 if (!alloc_buffer_size(buffer
, *needed
)) {
4751 free_printer_info_7(printer
);
4752 return WERR_INSUFFICIENT_BUFFER
;
4755 /* fill the buffer with the structures */
4756 smb_io_printer_info_7("", buffer
, printer
, 0);
4759 free_printer_info_7(printer
);
4761 if (*needed
> offered
) {
4762 return WERR_INSUFFICIENT_BUFFER
;
4768 /****************************************************************************
4769 ****************************************************************************/
4771 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
4773 POLICY_HND
*handle
= &q_u
->handle
;
4774 uint32 level
= q_u
->level
;
4775 NEW_BUFFER
*buffer
= NULL
;
4776 uint32 offered
= q_u
->offered
;
4777 uint32
*needed
= &r_u
->needed
;
4781 /* that's an [in out] buffer */
4782 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4783 buffer
= r_u
->buffer
;
4787 if (!get_printer_snum(p
, handle
, &snum
))
4792 return getprinter_level_0(snum
, buffer
, offered
, needed
);
4794 return getprinter_level_1(snum
, buffer
, offered
, needed
);
4796 return getprinter_level_2(snum
, buffer
, offered
, needed
);
4798 return getprinter_level_3(snum
, buffer
, offered
, needed
);
4800 return getprinter_level_4(snum
, buffer
, offered
, needed
);
4802 return getprinter_level_5(snum
, buffer
, offered
, needed
);
4804 return getprinter_level_7(snum
, buffer
, offered
, needed
);
4806 return WERR_UNKNOWN_LEVEL
;
4809 /********************************************************************
4810 * fill a DRIVER_INFO_1 struct
4811 ********************************************************************/
4813 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
4815 init_unistr( &info
->name
, driver
.info_3
->name
);
4818 /********************************************************************
4819 * construct_printer_driver_info_1
4820 ********************************************************************/
4822 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4824 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4825 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4827 ZERO_STRUCT(driver
);
4829 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4830 return WERR_INVALID_PRINTER_NAME
;
4832 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4833 return WERR_UNKNOWN_PRINTER_DRIVER
;
4835 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
4837 free_a_printer(&printer
,2);
4842 /********************************************************************
4843 * construct_printer_driver_info_2
4844 * fill a printer_info_2 struct
4845 ********************************************************************/
4847 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4851 info
->version
=driver
.info_3
->cversion
;
4853 init_unistr( &info
->name
, driver
.info_3
->name
);
4854 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4857 if (strlen(driver
.info_3
->driverpath
)) {
4858 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4859 init_unistr( &info
->driverpath
, temp
);
4861 init_unistr( &info
->driverpath
, "" );
4863 if (strlen(driver
.info_3
->datafile
)) {
4864 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4865 init_unistr( &info
->datafile
, temp
);
4867 init_unistr( &info
->datafile
, "" );
4869 if (strlen(driver
.info_3
->configfile
)) {
4870 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4871 init_unistr( &info
->configfile
, temp
);
4873 init_unistr( &info
->configfile
, "" );
4876 /********************************************************************
4877 * construct_printer_driver_info_2
4878 * fill a printer_info_2 struct
4879 ********************************************************************/
4881 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4883 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4884 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4886 ZERO_STRUCT(printer
);
4887 ZERO_STRUCT(driver
);
4889 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4890 return WERR_INVALID_PRINTER_NAME
;
4892 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4893 return WERR_UNKNOWN_PRINTER_DRIVER
;
4895 fill_printer_driver_info_2(info
, driver
, servername
);
4897 free_a_printer(&printer
,2);
4902 /********************************************************************
4903 * copy a strings array and convert to UNICODE
4905 * convert an array of ascii string to a UNICODE string
4906 ********************************************************************/
4908 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
4916 DEBUG(6,("init_unistr_array\n"));
4927 v
= ""; /* hack to handle null lists */
4930 /* hack to allow this to be used in places other than when generating
4931 the list of dependent files */
4934 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
4938 DEBUGADD(6,("%d:%s:%d\n", i
, line
, strlen(line
)));
4940 /* add one extra unit16 for the second terminating NULL */
4942 if ( (tuary
=Realloc(*uni_array
, (j
+1+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
4943 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4951 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
4956 /* special case for ""; we need to add both NULL's here */
4958 (*uni_array
)[j
++]=0x0000;
4959 (*uni_array
)[j
]=0x0000;
4962 DEBUGADD(6,("last one:done\n"));
4964 /* return size of array in uint16's */
4969 /********************************************************************
4970 * construct_printer_info_3
4971 * fill a printer_info_3 struct
4972 ********************************************************************/
4974 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4980 info
->version
=driver
.info_3
->cversion
;
4982 init_unistr( &info
->name
, driver
.info_3
->name
);
4983 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4985 if (strlen(driver
.info_3
->driverpath
)) {
4986 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4987 init_unistr( &info
->driverpath
, temp
);
4989 init_unistr( &info
->driverpath
, "" );
4991 if (strlen(driver
.info_3
->datafile
)) {
4992 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4993 init_unistr( &info
->datafile
, temp
);
4995 init_unistr( &info
->datafile
, "" );
4997 if (strlen(driver
.info_3
->configfile
)) {
4998 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4999 init_unistr( &info
->configfile
, temp
);
5001 init_unistr( &info
->configfile
, "" );
5003 if (strlen(driver
.info_3
->helpfile
)) {
5004 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5005 init_unistr( &info
->helpfile
, temp
);
5007 init_unistr( &info
->helpfile
, "" );
5009 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5010 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5012 info
->dependentfiles
=NULL
;
5013 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5016 /********************************************************************
5017 * construct_printer_info_3
5018 * fill a printer_info_3 struct
5019 ********************************************************************/
5021 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5023 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5024 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5026 ZERO_STRUCT(driver
);
5028 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
5029 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5030 if (!W_ERROR_IS_OK(status
))
5031 return WERR_INVALID_PRINTER_NAME
;
5033 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5034 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5039 * I put this code in during testing. Helpful when commenting out the
5040 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5041 * as win2k always queries the driver using an infor level of 6.
5042 * I've left it in (but ifdef'd out) because I'll probably
5043 * use it in experimentation again in the future. --jerry 22/01/2002
5046 if (!W_ERROR_IS_OK(status
)) {
5048 * Is this a W2k client ?
5051 /* Yes - try again with a WinNT driver. */
5053 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5054 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5058 if (!W_ERROR_IS_OK(status
)) {
5059 free_a_printer(&printer
,2);
5060 return WERR_UNKNOWN_PRINTER_DRIVER
;
5068 fill_printer_driver_info_3(info
, driver
, servername
);
5070 free_a_printer(&printer
,2);
5075 /********************************************************************
5076 * construct_printer_info_6
5077 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5078 ********************************************************************/
5080 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5086 memset(&nullstr
, '\0', sizeof(fstring
));
5088 info
->version
=driver
.info_3
->cversion
;
5090 init_unistr( &info
->name
, driver
.info_3
->name
);
5091 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5093 if (strlen(driver
.info_3
->driverpath
)) {
5094 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5095 init_unistr( &info
->driverpath
, temp
);
5097 init_unistr( &info
->driverpath
, "" );
5099 if (strlen(driver
.info_3
->datafile
)) {
5100 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5101 init_unistr( &info
->datafile
, temp
);
5103 init_unistr( &info
->datafile
, "" );
5105 if (strlen(driver
.info_3
->configfile
)) {
5106 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5107 init_unistr( &info
->configfile
, temp
);
5109 init_unistr( &info
->configfile
, "" );
5111 if (strlen(driver
.info_3
->helpfile
)) {
5112 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5113 init_unistr( &info
->helpfile
, temp
);
5115 init_unistr( &info
->helpfile
, "" );
5117 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5118 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5120 info
->dependentfiles
= NULL
;
5121 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5123 info
->previousdrivernames
=NULL
;
5124 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5126 info
->driver_date
.low
=0;
5127 info
->driver_date
.high
=0;
5130 info
->driver_version_low
=0;
5131 info
->driver_version_high
=0;
5133 init_unistr( &info
->mfgname
, "");
5134 init_unistr( &info
->oem_url
, "");
5135 init_unistr( &info
->hardware_id
, "");
5136 init_unistr( &info
->provider
, "");
5139 /********************************************************************
5140 * construct_printer_info_6
5141 * fill a printer_info_6 struct
5142 ********************************************************************/
5144 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5145 fstring servername
, fstring architecture
, uint32 version
)
5147 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5148 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5151 ZERO_STRUCT(driver
);
5153 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
5155 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5157 if (!W_ERROR_IS_OK(status
))
5158 return WERR_INVALID_PRINTER_NAME
;
5160 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5162 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5164 if (!W_ERROR_IS_OK(status
))
5167 * Is this a W2k client ?
5171 free_a_printer(&printer
,2);
5172 return WERR_UNKNOWN_PRINTER_DRIVER
;
5175 /* Yes - try again with a WinNT driver. */
5177 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5178 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5179 if (!W_ERROR_IS_OK(status
)) {
5180 free_a_printer(&printer
,2);
5181 return WERR_UNKNOWN_PRINTER_DRIVER
;
5185 fill_printer_driver_info_6(info
, driver
, servername
);
5187 free_a_printer(&printer
,2);
5188 free_a_printer_driver(driver
, 3);
5193 /****************************************************************************
5194 ****************************************************************************/
5196 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5198 SAFE_FREE(info
->dependentfiles
);
5201 /****************************************************************************
5202 ****************************************************************************/
5204 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5206 SAFE_FREE(info
->dependentfiles
);
5210 /****************************************************************************
5211 ****************************************************************************/
5213 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5215 DRIVER_INFO_1
*info
=NULL
;
5218 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
5221 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5222 if (!W_ERROR_IS_OK(status
)) {
5227 /* check the required size. */
5228 *needed
+= spoolss_size_printer_driver_info_1(info
);
5230 if (!alloc_buffer_size(buffer
, *needed
)) {
5232 return WERR_INSUFFICIENT_BUFFER
;
5235 /* fill the buffer with the structures */
5236 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5241 if (*needed
> offered
)
5242 return WERR_INSUFFICIENT_BUFFER
;
5247 /****************************************************************************
5248 ****************************************************************************/
5250 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5252 DRIVER_INFO_2
*info
=NULL
;
5255 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
5258 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5259 if (!W_ERROR_IS_OK(status
)) {
5264 /* check the required size. */
5265 *needed
+= spoolss_size_printer_driver_info_2(info
);
5267 if (!alloc_buffer_size(buffer
, *needed
)) {
5269 return WERR_INSUFFICIENT_BUFFER
;
5272 /* fill the buffer with the structures */
5273 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5278 if (*needed
> offered
)
5279 return WERR_INSUFFICIENT_BUFFER
;
5284 /****************************************************************************
5285 ****************************************************************************/
5287 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5294 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5295 if (!W_ERROR_IS_OK(status
)) {
5299 /* check the required size. */
5300 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5302 if (!alloc_buffer_size(buffer
, *needed
)) {
5303 free_printer_driver_info_3(&info
);
5304 return WERR_INSUFFICIENT_BUFFER
;
5307 /* fill the buffer with the structures */
5308 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5310 free_printer_driver_info_3(&info
);
5312 if (*needed
> offered
)
5313 return WERR_INSUFFICIENT_BUFFER
;
5318 /****************************************************************************
5319 ****************************************************************************/
5321 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5328 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5329 if (!W_ERROR_IS_OK(status
)) {
5333 /* check the required size. */
5334 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5336 if (!alloc_buffer_size(buffer
, *needed
)) {
5337 free_printer_driver_info_6(&info
);
5338 return WERR_INSUFFICIENT_BUFFER
;
5341 /* fill the buffer with the structures */
5342 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5344 free_printer_driver_info_6(&info
);
5346 if (*needed
> offered
)
5347 return WERR_INSUFFICIENT_BUFFER
;
5352 /****************************************************************************
5353 ****************************************************************************/
5355 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5357 POLICY_HND
*handle
= &q_u
->handle
;
5358 UNISTR2
*uni_arch
= &q_u
->architecture
;
5359 uint32 level
= q_u
->level
;
5360 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5361 NEW_BUFFER
*buffer
= NULL
;
5362 uint32 offered
= q_u
->offered
;
5363 uint32
*needed
= &r_u
->needed
;
5364 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5365 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5368 fstring architecture
;
5371 /* that's an [in out] buffer */
5372 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5373 buffer
= r_u
->buffer
;
5375 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5378 *servermajorversion
= 0;
5379 *serverminorversion
= 0;
5381 pstrcpy(servername
, get_called_name());
5382 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5384 if (!get_printer_snum(p
, handle
, &snum
))
5389 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5391 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5393 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5395 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5398 return WERR_UNKNOWN_LEVEL
;
5401 /****************************************************************************
5402 ****************************************************************************/
5404 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5406 POLICY_HND
*handle
= &q_u
->handle
;
5408 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5411 DEBUG(3,("Error in startpageprinter printer handle\n"));
5415 Printer
->page_started
=True
;
5419 /****************************************************************************
5420 ****************************************************************************/
5422 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5424 POLICY_HND
*handle
= &q_u
->handle
;
5427 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5430 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5434 if (!get_printer_snum(p
, handle
, &snum
))
5437 Printer
->page_started
=False
;
5438 print_job_endpage(snum
, Printer
->jobid
);
5443 /********************************************************************
5444 * api_spoolss_getprinter
5445 * called from the spoolss dispatcher
5447 ********************************************************************/
5449 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5451 POLICY_HND
*handle
= &q_u
->handle
;
5452 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5453 uint32
*jobid
= &r_u
->jobid
;
5455 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5459 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5460 struct current_user user
;
5463 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5467 get_current_user(&user
, p
);
5470 * a nice thing with NT is it doesn't listen to what you tell it.
5471 * when asked to send _only_ RAW datas, it tries to send datas
5474 * So I add checks like in NT Server ...
5477 if (info_1
->p_datatype
!= 0) {
5478 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5479 if (strcmp(datatype
, "RAW") != 0) {
5481 return WERR_INVALID_DATATYPE
;
5485 /* get the share number of the printer */
5486 if (!get_printer_snum(p
, handle
, &snum
)) {
5490 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5492 Printer
->jobid
= print_job_start(&user
, snum
, jobname
, Printer
->nt_devmode
);
5494 /* An error occured in print_job_start() so return an appropriate
5497 if (Printer
->jobid
== -1) {
5498 return map_werror_from_unix(errno
);
5501 Printer
->document_started
=True
;
5502 (*jobid
) = Printer
->jobid
;
5507 /********************************************************************
5508 * api_spoolss_getprinter
5509 * called from the spoolss dispatcher
5511 ********************************************************************/
5513 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5515 POLICY_HND
*handle
= &q_u
->handle
;
5517 return _spoolss_enddocprinter_internal(p
, handle
);
5520 /****************************************************************************
5521 ****************************************************************************/
5523 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5525 POLICY_HND
*handle
= &q_u
->handle
;
5526 uint32 buffer_size
= q_u
->buffer_size
;
5527 uint8
*buffer
= q_u
->buffer
;
5528 uint32
*buffer_written
= &q_u
->buffer_size2
;
5530 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5533 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5534 r_u
->buffer_written
= q_u
->buffer_size2
;
5538 if (!get_printer_snum(p
, handle
, &snum
))
5541 (*buffer_written
) = print_job_write(snum
, Printer
->jobid
, (char *)buffer
, buffer_size
);
5542 if (*buffer_written
== -1) {
5543 r_u
->buffer_written
= 0;
5544 if (errno
== ENOSPC
)
5545 return WERR_NO_SPOOL_SPACE
;
5547 return WERR_ACCESS_DENIED
;
5550 r_u
->buffer_written
= q_u
->buffer_size2
;
5555 /********************************************************************
5556 * api_spoolss_getprinter
5557 * called from the spoolss dispatcher
5559 ********************************************************************/
5561 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5564 struct current_user user
;
5566 WERROR errcode
= WERR_BADFUNC
;
5567 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5569 get_current_user(&user
, p
);
5572 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5576 if (!get_printer_snum(p
, handle
, &snum
))
5580 case PRINTER_CONTROL_PAUSE
:
5581 if (print_queue_pause(&user
, snum
, &errcode
)) {
5585 case PRINTER_CONTROL_RESUME
:
5586 case PRINTER_CONTROL_UNPAUSE
:
5587 if (print_queue_resume(&user
, snum
, &errcode
)) {
5591 case PRINTER_CONTROL_PURGE
:
5592 if (print_queue_purge(&user
, snum
, &errcode
)) {
5597 return WERR_UNKNOWN_LEVEL
;
5603 /********************************************************************
5604 * api_spoolss_abortprinter
5605 * From MSDN: "Deletes printer's spool file if printer is configured
5607 ********************************************************************/
5609 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5611 POLICY_HND
*handle
= &q_u
->handle
;
5612 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5614 struct current_user user
;
5615 WERROR errcode
= WERR_OK
;
5618 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5622 if (!get_printer_snum(p
, handle
, &snum
))
5625 get_current_user( &user
, p
);
5627 print_job_delete( &user
, snum
, Printer
->jobid
, &errcode
);
5632 /********************************************************************
5633 * called by spoolss_api_setprinter
5634 * when updating a printer description
5635 ********************************************************************/
5637 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5638 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5639 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5641 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5642 struct current_user user
;
5646 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5648 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5649 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5650 OUR_HANDLE(handle
)));
5652 result
= WERR_BADFID
;
5656 /* NT seems to like setting the security descriptor even though
5657 nothing may have actually changed. This causes annoying
5658 dialog boxes when the user doesn't have permission to change
5659 the security descriptor. */
5661 nt_printing_getsec(p
->mem_ctx
, Printer
->dev
.handlename
, &old_secdesc_ctr
);
5663 if (DEBUGLEVEL
>= 10) {
5667 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5668 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5669 PRINTERNAME(snum
), the_acl
->num_aces
));
5671 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5674 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5676 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5677 the_acl
->ace
[i
].info
.mask
));
5680 the_acl
= secdesc_ctr
->sec
->dacl
;
5683 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5684 PRINTERNAME(snum
), the_acl
->num_aces
));
5686 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5689 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5691 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5692 the_acl
->ace
[i
].info
.mask
));
5695 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5699 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5701 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5706 /* Work out which user is performing the operation */
5708 get_current_user(&user
, p
);
5710 /* Check the user has permissions to change the security
5711 descriptor. By experimentation with two NT machines, the user
5712 requires Full Access to the printer to change security
5715 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5716 result
= WERR_ACCESS_DENIED
;
5720 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
5727 /********************************************************************
5728 Do Samba sanity checks on a printer info struct.
5729 this has changed purpose: it now "canonicalises" printer
5730 info from a client rather than just checking it is correct
5731 ********************************************************************/
5733 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5735 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5736 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5738 /* we force some elements to "correct" values */
5739 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", get_called_name());
5740 fstrcpy(info
->sharename
, lp_servicename(snum
));
5741 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5742 get_called_name(), info
->sharename
);
5743 info
->attributes
= PRINTER_ATTRIBUTE_SHARED
| PRINTER_ATTRIBUTE_NETWORK
;
5748 /****************************************************************************
5749 ****************************************************************************/
5751 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
5753 extern userdom_struct current_user_info
;
5754 char *cmd
= lp_addprinter_cmd();
5760 fstring remote_machine
= "%m";
5762 standard_sub_basic(current_user_info
.smb_name
, remote_machine
,sizeof(remote_machine
));
5764 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5765 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5766 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5767 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
5769 DEBUG(10,("Running [%s]\n", command
));
5770 ret
= smbrun(command
, &fd
);
5771 DEBUGADD(10,("returned [%d]\n", ret
));
5780 /* Get lines and convert them back to dos-codepage */
5781 qlines
= fd_lines_load(fd
, &numlines
);
5782 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5786 /* Set the portname to what the script says the portname should be. */
5787 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5788 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5790 /* Send SIGHUP to process group... is there a better way? */
5793 /* reload our services immediately */
5794 reload_services( False
);
5797 file_lines_free(qlines
);
5801 /********************************************************************
5802 * Called by spoolss_api_setprinter
5803 * when updating a printer description.
5804 ********************************************************************/
5806 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
5807 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5808 DEVICEMODE
*devmode
)
5811 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
5812 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5815 DEBUG(8,("update_printer\n"));
5820 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5821 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5822 result
= WERR_UNKNOWN_LEVEL
;
5827 result
= WERR_BADFID
;
5831 if (!get_printer_snum(p
, handle
, &snum
)) {
5832 result
= WERR_BADFID
;
5836 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))) ||
5837 (!W_ERROR_IS_OK(get_a_printer(&old_printer
, 2, lp_servicename(snum
))))) {
5838 result
= WERR_BADFID
;
5842 DEBUGADD(8,("Converting info_2 struct\n"));
5845 * convert_printer_info converts the incoming
5846 * info from the client and overwrites the info
5847 * just read from the tdb in the pointer 'printer'.
5850 if (!convert_printer_info(info
, printer
, level
)) {
5851 result
= WERR_NOMEM
;
5856 /* we have a valid devmode
5857 convert it and link it*/
5859 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5860 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5861 &printer
->info_2
->devmode
)) {
5862 result
= WERR_NOMEM
;
5867 * make sure we actually reload the services after
5868 * this as smb.conf could have a new section in it
5869 * .... shouldn't .... but could
5871 reload_services(False
);
5874 /* Do sanity check on the requested changes for Samba */
5876 if (!check_printer_ok(printer
->info_2
, snum
)) {
5877 result
= WERR_INVALID_PARAM
;
5881 /* Check calling user has permission to update printer description */
5883 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5884 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5885 result
= WERR_ACCESS_DENIED
;
5889 /* Call addprinter hook */
5890 /* Check changes to see if this is really needed */
5892 if ( *lp_addprinter_cmd()
5893 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
5894 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
5895 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
5896 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
5898 if ( !add_printer_hook(printer
) ) {
5899 result
= WERR_ACCESS_DENIED
;
5905 * When a *new* driver is bound to a printer, the drivername is used to
5906 * lookup previously saved driver initialization info, which is then
5907 * bound to the printer, simulating what happens in the Windows arch.
5909 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
5911 if (!set_driver_init(printer
, 2))
5913 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5914 printer
->info_2
->drivername
));
5917 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5918 printer
->info_2
->drivername
));
5920 notify_printer_driver(snum
, printer
->info_2
->drivername
);
5923 /* Update printer info */
5924 result
= mod_a_printer(*printer
, 2);
5926 /* flag which changes actually occured. This is a small subset of
5927 all the possible changes */
5929 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
))
5930 notify_printer_comment(snum
, printer
->info_2
->comment
);
5932 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
))
5933 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
5935 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
))
5936 notify_printer_port(snum
, printer
->info_2
->portname
);
5938 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
))
5939 notify_printer_location(snum
, printer
->info_2
->location
);
5942 free_a_printer(&printer
, 2);
5943 free_a_printer(&old_printer
, 2);
5949 /****************************************************************************
5950 ****************************************************************************/
5951 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
5952 const SPOOL_PRINTER_INFO_LEVEL
*info
)
5955 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
5957 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5960 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
5967 if (!get_printer_snum(p
, handle
, &snum
))
5970 nt_printer_publish(snum
, info7
->action
);
5974 return WERR_UNKNOWN_LEVEL
;
5977 /****************************************************************************
5978 ****************************************************************************/
5980 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
5982 POLICY_HND
*handle
= &q_u
->handle
;
5983 uint32 level
= q_u
->level
;
5984 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
5985 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
5986 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
5987 uint32 command
= q_u
->command
;
5989 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5992 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5996 /* check the level */
5999 return control_printer(handle
, command
, p
);
6001 return update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6003 return update_printer_sec(handle
, level
, info
, p
,
6006 return publish_or_unpublish_printer(p
, handle
, info
);
6008 return WERR_UNKNOWN_LEVEL
;
6012 /****************************************************************************
6013 ****************************************************************************/
6015 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6017 POLICY_HND
*handle
= &q_u
->handle
;
6018 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6021 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6025 if (Printer
->notify
.client_connected
==True
) {
6028 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
6030 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
6031 !get_printer_snum(p
, handle
, &snum
) )
6034 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6037 Printer
->notify
.flags
=0;
6038 Printer
->notify
.options
=0;
6039 Printer
->notify
.localmachine
[0]='\0';
6040 Printer
->notify
.printerlocal
=0;
6041 if (Printer
->notify
.option
)
6042 free_spool_notify_option(&Printer
->notify
.option
);
6043 Printer
->notify
.client_connected
=False
;
6048 /****************************************************************************
6049 ****************************************************************************/
6051 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6053 /* that's an [in out] buffer (despite appearences to the contrary) */
6054 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6057 return WERR_INVALID_PARAM
; /* this is what a NT server
6058 returns for AddJob. AddJob
6059 must fail on non-local
6063 /****************************************************************************
6064 ****************************************************************************/
6066 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
6067 int position
, int snum
)
6073 t
=gmtime(&queue
->time
);
6074 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
6076 job_info
->jobid
=queue
->job
;
6077 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6078 init_unistr(&job_info
->machinename
, temp_name
);
6079 init_unistr(&job_info
->username
, queue
->fs_user
);
6080 init_unistr(&job_info
->document
, queue
->fs_file
);
6081 init_unistr(&job_info
->datatype
, "RAW");
6082 init_unistr(&job_info
->text_status
, "");
6083 job_info
->status
=nt_printj_status(queue
->status
);
6084 job_info
->priority
=queue
->priority
;
6085 job_info
->position
=position
;
6086 job_info
->totalpages
=queue
->page_count
;
6087 job_info
->pagesprinted
=0;
6089 make_systemtime(&job_info
->submitted
, t
);
6092 /****************************************************************************
6093 ****************************************************************************/
6095 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
6096 int position
, int snum
,
6097 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6098 DEVICEMODE
*devmode
)
6104 t
=gmtime(&queue
->time
);
6105 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
6107 job_info
->jobid
=queue
->job
;
6109 slprintf(chaine
, sizeof(chaine
)-1, "\\\\%s\\%s", get_called_name(), ntprinter
->info_2
->printername
);
6111 init_unistr(&job_info
->printername
, chaine
);
6113 init_unistr(&job_info
->machinename
, temp_name
);
6114 init_unistr(&job_info
->username
, queue
->fs_user
);
6115 init_unistr(&job_info
->document
, queue
->fs_file
);
6116 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6117 init_unistr(&job_info
->datatype
, "RAW");
6118 init_unistr(&job_info
->printprocessor
, "winprint");
6119 init_unistr(&job_info
->parameters
, "");
6120 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6121 init_unistr(&job_info
->text_status
, "");
6123 /* and here the security descriptor */
6125 job_info
->status
=nt_printj_status(queue
->status
);
6126 job_info
->priority
=queue
->priority
;
6127 job_info
->position
=position
;
6128 job_info
->starttime
=0;
6129 job_info
->untiltime
=0;
6130 job_info
->totalpages
=queue
->page_count
;
6131 job_info
->size
=queue
->size
;
6132 make_systemtime(&(job_info
->submitted
), t
);
6133 job_info
->timeelapsed
=0;
6134 job_info
->pagesprinted
=0;
6136 job_info
->devmode
= devmode
;
6141 /****************************************************************************
6142 Enumjobs at level 1.
6143 ****************************************************************************/
6145 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
6146 NEW_BUFFER
*buffer
, uint32 offered
,
6147 uint32
*needed
, uint32
*returned
)
6152 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
6159 for (i
=0; i
<*returned
; i
++)
6160 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
6164 /* check the required size. */
6165 for (i
=0; i
<*returned
; i
++)
6166 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6168 if (!alloc_buffer_size(buffer
, *needed
)) {
6170 return WERR_INSUFFICIENT_BUFFER
;
6173 /* fill the buffer with the structures */
6174 for (i
=0; i
<*returned
; i
++)
6175 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6180 if (*needed
> offered
) {
6182 return WERR_INSUFFICIENT_BUFFER
;
6188 /****************************************************************************
6189 Enumjobs at level 2.
6190 ****************************************************************************/
6192 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
6193 NEW_BUFFER
*buffer
, uint32 offered
,
6194 uint32
*needed
, uint32
*returned
)
6196 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6197 JOB_INFO_2
*info
= NULL
;
6200 DEVICEMODE
*devmode
= NULL
;
6202 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
6205 result
= WERR_NOMEM
;
6209 result
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
6210 if (!W_ERROR_IS_OK(result
)) {
6215 /* this should not be a failure condition if the devmode is NULL */
6217 devmode
= construct_dev_mode(snum
);
6219 for (i
=0; i
<*returned
; i
++)
6220 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
,
6223 free_a_printer(&ntprinter
, 2);
6226 /* check the required size. */
6227 for (i
=0; i
<*returned
; i
++)
6228 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6230 if (*needed
> offered
) {
6232 result
= WERR_INSUFFICIENT_BUFFER
;
6236 if (!alloc_buffer_size(buffer
, *needed
)) {
6238 result
= WERR_INSUFFICIENT_BUFFER
;
6242 /* fill the buffer with the structures */
6243 for (i
=0; i
<*returned
; i
++)
6244 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6249 free_a_printer(&ntprinter
, 2);
6250 free_devmode(devmode
);
6258 /****************************************************************************
6260 ****************************************************************************/
6262 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6264 POLICY_HND
*handle
= &q_u
->handle
;
6265 uint32 level
= q_u
->level
;
6266 NEW_BUFFER
*buffer
= NULL
;
6267 uint32 offered
= q_u
->offered
;
6268 uint32
*needed
= &r_u
->needed
;
6269 uint32
*returned
= &r_u
->returned
;
6272 print_status_struct prt_status
;
6273 print_queue_struct
*queue
=NULL
;
6275 /* that's an [in out] buffer */
6276 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6277 buffer
= r_u
->buffer
;
6279 DEBUG(4,("_spoolss_enumjobs\n"));
6284 if (!get_printer_snum(p
, handle
, &snum
))
6287 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6288 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6290 if (*returned
== 0) {
6297 return enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
6299 return enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
6303 return WERR_UNKNOWN_LEVEL
;
6307 /****************************************************************************
6308 ****************************************************************************/
6310 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6315 /****************************************************************************
6316 ****************************************************************************/
6318 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6320 POLICY_HND
*handle
= &q_u
->handle
;
6321 uint32 jobid
= q_u
->jobid
;
6322 uint32 command
= q_u
->command
;
6324 struct current_user user
;
6326 WERROR errcode
= WERR_BADFUNC
;
6328 if (!get_printer_snum(p
, handle
, &snum
)) {
6332 if (!print_job_exists(snum
, jobid
)) {
6333 return WERR_INVALID_PRINTER_NAME
;
6336 get_current_user(&user
, p
);
6339 case JOB_CONTROL_CANCEL
:
6340 case JOB_CONTROL_DELETE
:
6341 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
6345 case JOB_CONTROL_PAUSE
:
6346 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
6350 case JOB_CONTROL_RESTART
:
6351 case JOB_CONTROL_RESUME
:
6352 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
6357 return WERR_UNKNOWN_LEVEL
;
6363 /****************************************************************************
6364 Enumerates all printer drivers at level 1.
6365 ****************************************************************************/
6367 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6372 fstring
*list
= NULL
;
6374 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6375 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
6379 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6381 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6382 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6388 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
6389 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6390 SAFE_FREE(driver_info_1
);
6394 else driver_info_1
= tdi1
;
6397 for (i
=0; i
<ndrivers
; i
++) {
6399 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6400 ZERO_STRUCT(driver
);
6401 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6402 architecture
, version
);
6403 if (!W_ERROR_IS_OK(status
)) {
6407 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6408 free_a_printer_driver(driver
, 3);
6411 *returned
+=ndrivers
;
6415 /* check the required size. */
6416 for (i
=0; i
<*returned
; i
++) {
6417 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6418 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6421 if (!alloc_buffer_size(buffer
, *needed
)) {
6422 SAFE_FREE(driver_info_1
);
6423 return WERR_INSUFFICIENT_BUFFER
;
6426 /* fill the buffer with the driver structures */
6427 for (i
=0; i
<*returned
; i
++) {
6428 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6429 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6432 SAFE_FREE(driver_info_1
);
6434 if (*needed
> offered
) {
6436 return WERR_INSUFFICIENT_BUFFER
;
6442 /****************************************************************************
6443 Enumerates all printer drivers at level 2.
6444 ****************************************************************************/
6446 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6451 fstring
*list
= NULL
;
6453 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6454 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
6458 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6460 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6461 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6467 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
6468 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6469 SAFE_FREE(driver_info_2
);
6473 else driver_info_2
= tdi2
;
6476 for (i
=0; i
<ndrivers
; i
++) {
6479 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6480 ZERO_STRUCT(driver
);
6481 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6482 architecture
, version
);
6483 if (!W_ERROR_IS_OK(status
)) {
6487 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6488 free_a_printer_driver(driver
, 3);
6491 *returned
+=ndrivers
;
6495 /* check the required size. */
6496 for (i
=0; i
<*returned
; i
++) {
6497 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6498 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6501 if (!alloc_buffer_size(buffer
, *needed
)) {
6502 SAFE_FREE(driver_info_2
);
6503 return WERR_INSUFFICIENT_BUFFER
;
6506 /* fill the buffer with the form structures */
6507 for (i
=0; i
<*returned
; i
++) {
6508 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6509 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6512 SAFE_FREE(driver_info_2
);
6514 if (*needed
> offered
) {
6516 return WERR_INSUFFICIENT_BUFFER
;
6522 /****************************************************************************
6523 Enumerates all printer drivers at level 3.
6524 ****************************************************************************/
6526 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6531 fstring
*list
= NULL
;
6533 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6534 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
6538 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6540 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6541 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6547 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
6548 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6549 SAFE_FREE(driver_info_3
);
6553 else driver_info_3
= tdi3
;
6556 for (i
=0; i
<ndrivers
; i
++) {
6559 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6560 ZERO_STRUCT(driver
);
6561 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6562 architecture
, version
);
6563 if (!W_ERROR_IS_OK(status
)) {
6567 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6568 free_a_printer_driver(driver
, 3);
6571 *returned
+=ndrivers
;
6575 /* check the required size. */
6576 for (i
=0; i
<*returned
; i
++) {
6577 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6578 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6581 if (!alloc_buffer_size(buffer
, *needed
)) {
6582 SAFE_FREE(driver_info_3
);
6583 return WERR_INSUFFICIENT_BUFFER
;
6586 /* fill the buffer with the driver structures */
6587 for (i
=0; i
<*returned
; i
++) {
6588 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6589 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6592 for (i
=0; i
<*returned
; i
++)
6593 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6595 SAFE_FREE(driver_info_3
);
6597 if (*needed
> offered
) {
6599 return WERR_INSUFFICIENT_BUFFER
;
6605 /****************************************************************************
6606 Enumerates all printer drivers.
6607 ****************************************************************************/
6609 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6611 UNISTR2
*environment
= &q_u
->environment
;
6612 uint32 level
= q_u
->level
;
6613 NEW_BUFFER
*buffer
= NULL
;
6614 uint32 offered
= q_u
->offered
;
6615 uint32
*needed
= &r_u
->needed
;
6616 uint32
*returned
= &r_u
->returned
;
6618 fstring
*list
= NULL
;
6620 fstring architecture
;
6622 /* that's an [in out] buffer */
6623 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6624 buffer
= r_u
->buffer
;
6626 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6627 fstrcpy(servername
, get_called_name());
6631 unistr2_to_ascii(architecture
, environment
, sizeof(architecture
)-1);
6635 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
6637 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
6639 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
6643 return WERR_UNKNOWN_LEVEL
;
6647 /****************************************************************************
6648 ****************************************************************************/
6650 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
6652 form
->flag
=list
->flag
;
6653 init_unistr(&form
->name
, list
->name
);
6654 form
->width
=list
->width
;
6655 form
->length
=list
->length
;
6656 form
->left
=list
->left
;
6657 form
->top
=list
->top
;
6658 form
->right
=list
->right
;
6659 form
->bottom
=list
->bottom
;
6662 /****************************************************************************
6663 ****************************************************************************/
6665 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
6667 uint32 level
= q_u
->level
;
6668 NEW_BUFFER
*buffer
= NULL
;
6669 uint32 offered
= q_u
->offered
;
6670 uint32
*needed
= &r_u
->needed
;
6671 uint32
*numofforms
= &r_u
->numofforms
;
6672 uint32 numbuiltinforms
;
6674 nt_forms_struct
*list
=NULL
;
6675 nt_forms_struct
*builtinlist
=NULL
;
6680 /* that's an [in out] buffer */
6681 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6682 buffer
= r_u
->buffer
;
6684 DEBUG(4,("_spoolss_enumforms\n"));
6685 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6686 DEBUGADD(5,("Info level [%d]\n", level
));
6688 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
6689 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
6690 *numofforms
= get_ntforms(&list
);
6691 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
6692 *numofforms
+= numbuiltinforms
;
6694 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
6698 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
6703 /* construct the list of form structures */
6704 for (i
=0; i
<numbuiltinforms
; i
++) {
6705 DEBUGADD(6,("Filling form number [%d]\n",i
));
6706 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
6709 SAFE_FREE(builtinlist
);
6711 for (; i
<*numofforms
; i
++) {
6712 DEBUGADD(6,("Filling form number [%d]\n",i
));
6713 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
6718 /* check the required size. */
6719 for (i
=0; i
<numbuiltinforms
; i
++) {
6720 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6721 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6723 for (; i
<*numofforms
; i
++) {
6724 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6725 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6728 *needed
=buffer_size
;
6730 if (!alloc_buffer_size(buffer
, buffer_size
)){
6732 return WERR_INSUFFICIENT_BUFFER
;
6735 /* fill the buffer with the form structures */
6736 for (i
=0; i
<numbuiltinforms
; i
++) {
6737 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6738 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6740 for (; i
<*numofforms
; i
++) {
6741 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6742 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6747 if (*needed
> offered
) {
6749 return WERR_INSUFFICIENT_BUFFER
;
6756 SAFE_FREE(builtinlist
);
6757 return WERR_UNKNOWN_LEVEL
;
6762 /****************************************************************************
6763 ****************************************************************************/
6765 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
6767 uint32 level
= q_u
->level
;
6768 UNISTR2
*uni_formname
= &q_u
->formname
;
6769 NEW_BUFFER
*buffer
= NULL
;
6770 uint32 offered
= q_u
->offered
;
6771 uint32
*needed
= &r_u
->needed
;
6773 nt_forms_struct
*list
=NULL
;
6774 nt_forms_struct builtin_form
;
6779 int numofforms
=0, i
=0;
6781 /* that's an [in out] buffer */
6782 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6783 buffer
= r_u
->buffer
;
6785 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
6787 DEBUG(4,("_spoolss_getform\n"));
6788 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6789 DEBUGADD(5,("Info level [%d]\n", level
));
6791 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
6792 if (!foundBuiltin
) {
6793 numofforms
= get_ntforms(&list
);
6794 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
6796 if (numofforms
== 0)
6803 fill_form_1(&form_1
, &builtin_form
);
6806 /* Check if the requested name is in the list of form structures */
6807 for (i
=0; i
<numofforms
; i
++) {
6809 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
6811 if (strequal(form_name
, list
[i
].name
)) {
6812 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
6813 fill_form_1(&form_1
, &list
[i
]);
6819 if (i
== numofforms
) {
6823 /* check the required size. */
6825 *needed
=spoolss_size_form_1(&form_1
);
6827 if (!alloc_buffer_size(buffer
, buffer_size
)){
6828 return WERR_INSUFFICIENT_BUFFER
;
6831 if (*needed
> offered
) {
6832 return WERR_INSUFFICIENT_BUFFER
;
6835 /* fill the buffer with the form structures */
6836 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
6837 smb_io_form_1("", buffer
, &form_1
, 0);
6843 return WERR_UNKNOWN_LEVEL
;
6847 /****************************************************************************
6848 ****************************************************************************/
6850 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
6852 init_unistr(&port
->port_name
, name
);
6855 /****************************************************************************
6856 ****************************************************************************/
6858 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
6860 init_unistr(&port
->port_name
, name
);
6861 init_unistr(&port
->monitor_name
, "Local Monitor");
6862 init_unistr(&port
->description
, "Local Port");
6863 #define PORT_TYPE_WRITE 1
6864 port
->port_type
=PORT_TYPE_WRITE
;
6868 /****************************************************************************
6870 ****************************************************************************/
6872 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6874 PORT_INFO_1
*ports
=NULL
;
6877 if (*lp_enumports_cmd()) {
6878 char *cmd
= lp_enumports_cmd();
6885 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
6887 DEBUG(10,("Running [%s]\n", command
));
6888 ret
= smbrun(command
, &fd
);
6889 DEBUG(10,("Returned [%d]\n", ret
));
6893 /* Is this the best error to return here? */
6894 return WERR_ACCESS_DENIED
;
6898 qlines
= fd_lines_load(fd
, &numlines
);
6899 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6903 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
6904 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6905 dos_errstr(WERR_NOMEM
)));
6906 file_lines_free(qlines
);
6910 for (i
=0; i
<numlines
; i
++) {
6911 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6912 fill_port_1(&ports
[i
], qlines
[i
]);
6915 file_lines_free(qlines
);
6918 *returned
= numlines
;
6921 *returned
= 1; /* Sole Samba port returned. */
6923 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
6926 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
6928 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
6931 /* check the required size. */
6932 for (i
=0; i
<*returned
; i
++) {
6933 DEBUGADD(6,("adding port [%d]'s size\n", i
));
6934 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
6937 if (!alloc_buffer_size(buffer
, *needed
)) {
6939 return WERR_INSUFFICIENT_BUFFER
;
6942 /* fill the buffer with the ports structures */
6943 for (i
=0; i
<*returned
; i
++) {
6944 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
6945 smb_io_port_1("", buffer
, &ports
[i
], 0);
6950 if (*needed
> offered
) {
6952 return WERR_INSUFFICIENT_BUFFER
;
6958 /****************************************************************************
6960 ****************************************************************************/
6962 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6964 PORT_INFO_2
*ports
=NULL
;
6967 if (*lp_enumports_cmd()) {
6968 char *cmd
= lp_enumports_cmd();
6977 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
6978 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
6980 path
= lp_lockdir();
6982 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
6983 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
6986 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
6987 ret
= smbrun(command
, &fd
);
6988 DEBUGADD(10,("returned [%d]\n", ret
));
6992 /* Is this the best error to return here? */
6993 return WERR_ACCESS_DENIED
;
6997 qlines
= fd_lines_load(fd
, &numlines
);
6998 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7002 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
7003 file_lines_free(qlines
);
7007 for (i
=0; i
<numlines
; i
++) {
7008 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7009 fill_port_2(&(ports
[i
]), qlines
[i
]);
7012 file_lines_free(qlines
);
7015 *returned
= numlines
;
7021 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
7024 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7026 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7029 /* check the required size. */
7030 for (i
=0; i
<*returned
; i
++) {
7031 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7032 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7035 if (!alloc_buffer_size(buffer
, *needed
)) {
7037 return WERR_INSUFFICIENT_BUFFER
;
7040 /* fill the buffer with the ports structures */
7041 for (i
=0; i
<*returned
; i
++) {
7042 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7043 smb_io_port_2("", buffer
, &ports
[i
], 0);
7048 if (*needed
> offered
) {
7050 return WERR_INSUFFICIENT_BUFFER
;
7056 /****************************************************************************
7058 ****************************************************************************/
7060 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7062 uint32 level
= q_u
->level
;
7063 NEW_BUFFER
*buffer
= NULL
;
7064 uint32 offered
= q_u
->offered
;
7065 uint32
*needed
= &r_u
->needed
;
7066 uint32
*returned
= &r_u
->returned
;
7068 /* that's an [in out] buffer */
7069 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7070 buffer
= r_u
->buffer
;
7072 DEBUG(4,("_spoolss_enumports\n"));
7079 return enumports_level_1(buffer
, offered
, needed
, returned
);
7081 return enumports_level_2(buffer
, offered
, needed
, returned
);
7083 return WERR_UNKNOWN_LEVEL
;
7087 /****************************************************************************
7088 ****************************************************************************/
7090 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7091 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7092 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7093 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7096 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7099 WERROR err
= WERR_OK
;
7101 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
7102 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7106 ZERO_STRUCTP(printer
);
7108 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7109 if (!convert_printer_info(info
, printer
, 2)) {
7110 free_a_printer(&printer
, 2);
7114 /* check to see if the printer already exists */
7116 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7117 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7118 printer
->info_2
->sharename
));
7119 free_a_printer(&printer
, 2);
7120 return WERR_PRINTER_ALREADY_EXISTS
;
7123 if (*lp_addprinter_cmd() ) {
7124 if ( !add_printer_hook(printer
) ) {
7125 free_a_printer(&printer
,2);
7126 return WERR_ACCESS_DENIED
;
7130 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", get_called_name(),
7131 printer
->info_2
->sharename
);
7134 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7135 free_a_printer(&printer
,2);
7136 return WERR_ACCESS_DENIED
;
7139 /* you must be a printer admin to add a new printer */
7140 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7141 free_a_printer(&printer
,2);
7142 return WERR_ACCESS_DENIED
;
7146 * Do sanity check on the requested changes for Samba.
7149 if (!check_printer_ok(printer
->info_2
, snum
)) {
7150 free_a_printer(&printer
,2);
7151 return WERR_INVALID_PARAM
;
7155 * When a printer is created, the drivername bound to the printer is used
7156 * to lookup previously saved driver initialization info, which is then
7157 * bound to the new printer, simulating what happens in the Windows arch.
7162 set_driver_init(printer
, 2);
7166 /* A valid devmode was included, convert and link it
7168 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7170 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7171 &printer
->info_2
->devmode
))
7175 /* write the ASCII on disk */
7176 err
= mod_a_printer(*printer
, 2);
7177 if (!W_ERROR_IS_OK(err
)) {
7178 free_a_printer(&printer
,2);
7182 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7183 /* Handle open failed - remove addition. */
7184 del_a_printer(printer
->info_2
->sharename
);
7185 free_a_printer(&printer
,2);
7186 return WERR_ACCESS_DENIED
;
7189 update_c_setprinter(False
);
7190 free_a_printer(&printer
,2);
7195 /****************************************************************************
7196 ****************************************************************************/
7198 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7200 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
7201 uint32 level
= q_u
->level
;
7202 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7203 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7204 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7205 uint32 user_switch
= q_u
->user_switch
;
7206 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7207 POLICY_HND
*handle
= &r_u
->handle
;
7211 /* we don't handle yet */
7212 /* but I know what to do ... */
7213 return WERR_UNKNOWN_LEVEL
;
7215 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7217 user_switch
, user
, handle
);
7219 return WERR_UNKNOWN_LEVEL
;
7223 /****************************************************************************
7224 ****************************************************************************/
7226 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7228 uint32 level
= q_u
->level
;
7229 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7230 WERROR err
= WERR_OK
;
7231 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7232 struct current_user user
;
7233 fstring driver_name
;
7236 ZERO_STRUCT(driver
);
7238 get_current_user(&user
, p
);
7240 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7245 DEBUG(5,("Cleaning driver's information\n"));
7246 err
= clean_up_driver_struct(driver
, level
, &user
);
7247 if (!W_ERROR_IS_OK(err
))
7250 DEBUG(5,("Moving driver to final destination\n"));
7251 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
7252 if (W_ERROR_IS_OK(err
))
7253 err
= WERR_ACCESS_DENIED
;
7257 if (add_a_printer_driver(driver
, level
)!=0) {
7258 err
= WERR_ACCESS_DENIED
;
7262 /* BEGIN_ADMIN_LOG */
7265 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7266 driver
.info_3
->name
,drv_ver_to_os
[driver
.info_3
->cversion
],uidtoname(user
.uid
));
7267 fstrcpy(driver_name
, driver
.info_3
->name
);
7270 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7271 driver
.info_6
->name
,drv_ver_to_os
[driver
.info_6
->version
],uidtoname(user
.uid
));
7272 fstrcpy(driver_name
, driver
.info_6
->name
);
7278 * I think this is where he DrvUpgradePrinter() hook would be
7279 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7280 * server. Right now, we just need to send ourselves a message
7281 * to update each printer bound to this driver. --jerry
7284 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7285 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7290 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7291 * decide if the driver init data should be deleted. The rules are:
7292 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7293 * 2) delete init data only if there is no 2k/Xp driver
7294 * 3) always delete init data
7295 * The generalized rule is always use init data from the highest order driver.
7296 * It is necessary to follow the driver install by an initialization step to
7297 * finish off this process.
7300 version
= driver
.info_3
->cversion
;
7301 else if (level
== 6)
7302 version
= driver
.info_6
->version
;
7307 * 9x printer driver - never delete init data
7310 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7315 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7316 * there is no 2k/Xp driver init data for this driver name.
7320 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7322 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7324 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7326 if (!del_driver_init(driver_name
))
7327 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7330 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7332 free_a_printer_driver(driver1
,3);
7333 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7340 * 2k or Xp printer driver - always delete init data
7343 if (!del_driver_init(driver_name
))
7344 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7348 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7354 free_a_printer_driver(driver
, level
);
7358 /********************************************************************
7359 * spoolss_addprinterdriverex
7360 ********************************************************************/
7362 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7364 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7365 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7368 * we only support the semantics of AddPrinterDriver()
7369 * i.e. only copy files that are newer than existing ones
7372 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7373 return WERR_ACCESS_DENIED
;
7375 ZERO_STRUCT(q_u_local
);
7376 ZERO_STRUCT(r_u_local
);
7378 /* just pass the information off to _spoolss_addprinterdriver() */
7379 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7380 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7381 q_u_local
.level
= q_u
->level
;
7382 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7384 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7387 /****************************************************************************
7388 ****************************************************************************/
7390 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7392 init_unistr(&info
->name
, name
);
7395 /****************************************************************************
7396 ****************************************************************************/
7398 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7402 pstring short_archi
;
7403 DRIVER_DIRECTORY_1
*info
=NULL
;
7405 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7407 if (get_short_archi(short_archi
, long_archi
)==False
)
7408 return WERR_INVALID_ENVIRONMENT
;
7410 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
7413 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi
);
7415 DEBUG(4,("printer driver directory: [%s]\n", path
));
7417 fill_driverdir_1(info
, path
);
7419 *needed
+= spoolss_size_driverdir_info_1(info
);
7421 if (!alloc_buffer_size(buffer
, *needed
)) {
7423 return WERR_INSUFFICIENT_BUFFER
;
7426 smb_io_driverdir_1("", buffer
, info
, 0);
7430 if (*needed
> offered
)
7431 return WERR_INSUFFICIENT_BUFFER
;
7436 /****************************************************************************
7437 ****************************************************************************/
7439 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7441 UNISTR2
*name
= &q_u
->name
;
7442 UNISTR2
*uni_environment
= &q_u
->environment
;
7443 uint32 level
= q_u
->level
;
7444 NEW_BUFFER
*buffer
= NULL
;
7445 uint32 offered
= q_u
->offered
;
7446 uint32
*needed
= &r_u
->needed
;
7448 /* that's an [in out] buffer */
7449 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7450 buffer
= r_u
->buffer
;
7452 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7458 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7460 return WERR_UNKNOWN_LEVEL
;
7464 /****************************************************************************
7465 ****************************************************************************/
7467 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7469 POLICY_HND
*handle
= &q_u
->handle
;
7470 uint32 idx
= q_u
->index
;
7471 uint32 in_value_len
= q_u
->valuesize
;
7472 uint32 in_data_len
= q_u
->datasize
;
7473 uint32
*out_max_value_len
= &r_u
->valuesize
;
7474 uint16
**out_value
= &r_u
->value
;
7475 uint32
*out_value_len
= &r_u
->realvaluesize
;
7476 uint32
*out_type
= &r_u
->type
;
7477 uint32
*out_max_data_len
= &r_u
->datasize
;
7478 uint8
**data_out
= &r_u
->data
;
7479 uint32
*out_data_len
= &r_u
->realdatasize
;
7481 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7484 uint32 biggest_valuesize
;
7485 uint32 biggest_datasize
;
7487 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7490 REGISTRY_VALUE
*val
;
7491 NT_PRINTER_DATA
*p_data
;
7492 int i
, key_index
, num_values
;
7495 ZERO_STRUCT( printer
);
7499 *out_max_data_len
= 0;
7503 DEBUG(5,("spoolss_enumprinterdata\n"));
7506 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7510 if (!get_printer_snum(p
,handle
, &snum
))
7513 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7514 if (!W_ERROR_IS_OK(result
))
7517 p_data
= &printer
->info_2
->data
;
7518 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7523 * The NT machine wants to know the biggest size of value and data
7525 * cf: MSDN EnumPrinterData remark section
7528 if ( !in_value_len
&& !in_data_len
)
7530 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7533 biggest_valuesize
= 0;
7534 biggest_datasize
= 0;
7536 num_values
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
7538 for ( i
=0; i
<num_values
; i
++ )
7540 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
7542 name_length
= strlen(val
->valuename
);
7543 if ( strlen(val
->valuename
) > biggest_valuesize
)
7544 biggest_valuesize
= name_length
;
7546 if ( val
->size
> biggest_datasize
)
7547 biggest_datasize
= val
->size
;
7549 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7553 /* the value is an UNICODE string but real_value_size is the length
7554 in bytes including the trailing 0 */
7556 *out_value_len
= 2 * (1+biggest_valuesize
);
7557 *out_data_len
= biggest_datasize
;
7559 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7565 * the value len is wrong in NT sp3
7566 * that's the number of bytes not the number of unicode chars
7569 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, idx
);
7574 /* out_value should default to "" or else NT4 has
7575 problems unmarshalling the response */
7577 *out_max_value_len
= (in_value_len
/sizeof(uint16
));
7579 if ( (*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7581 result
= WERR_NOMEM
;
7585 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
7587 /* the data is counted in bytes */
7589 *out_max_data_len
= in_data_len
;
7590 *out_data_len
= in_data_len
;
7592 /* only allocate when given a non-zero data_len */
7594 if ( in_data_len
&& ((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
7596 result
= WERR_NOMEM
;
7600 result
= WERR_NO_MORE_ITEMS
;
7606 * - counted in bytes in the request
7607 * - counted in UNICODE chars in the max reply
7608 * - counted in bytes in the real size
7610 * take a pause *before* coding not *during* coding
7614 *out_max_value_len
= ( in_value_len
/ sizeof(uint16
) );
7615 if ( (*out_value
= (uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7617 result
= WERR_NOMEM
;
7621 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), in_value_len
, 0);
7625 *out_type
= regval_type( val
);
7627 /* data - counted in bytes */
7629 *out_max_data_len
= in_data_len
;
7630 if ( (*data_out
= (uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
7632 result
= WERR_NOMEM
;
7635 data_len
= (size_t)regval_size(val
);
7636 memcpy( *data_out
, regval_data_p(val
), data_len
);
7637 *out_data_len
= data_len
;
7641 free_a_printer(&printer
, 2);
7645 /****************************************************************************
7646 ****************************************************************************/
7648 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
7650 POLICY_HND
*handle
= &q_u
->handle
;
7651 UNISTR2
*value
= &q_u
->value
;
7652 uint32 type
= q_u
->type
;
7653 uint8
*data
= q_u
->data
;
7654 uint32 real_len
= q_u
->real_len
;
7656 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7658 WERROR status
= WERR_OK
;
7659 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7662 DEBUG(5,("spoolss_setprinterdata\n"));
7665 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7669 if (!get_printer_snum(p
,handle
, &snum
))
7673 * Access check : NT returns "access denied" if you make a
7674 * SetPrinterData call without the necessary privildge.
7675 * we were originally returning OK if nothing changed
7676 * which made Win2k issue **a lot** of SetPrinterData
7677 * when connecting to a printer --jerry
7680 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
7682 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7683 status
= WERR_ACCESS_DENIED
;
7687 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7688 if (!W_ERROR_IS_OK(status
))
7691 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
7694 * When client side code sets a magic printer data key, detect it and save
7695 * the current printer data and the magic key's data (its the DEVMODE) for
7696 * future printer/driver initializations.
7698 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
7700 /* Set devmode and printer initialization info */
7701 status
= save_driver_init( printer
, 2, data
, real_len
);
7703 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
7707 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
7708 type
, data
, real_len
);
7709 if ( W_ERROR_IS_OK(status
) )
7710 status
= mod_a_printer(*printer
, 2);
7714 free_a_printer(&printer
, 2);
7719 /****************************************************************************
7720 ****************************************************************************/
7722 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
7724 POLICY_HND
*handle
= &q_u
->handle
;
7725 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7728 DEBUG(5,("_spoolss_resetprinter\n"));
7731 * All we do is to check to see if the handle and queue is valid.
7732 * This call really doesn't mean anything to us because we only
7733 * support RAW printing. --jerry
7737 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7741 if (!get_printer_snum(p
,handle
, &snum
))
7745 /* blindly return success */
7750 /****************************************************************************
7751 ****************************************************************************/
7753 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
7755 POLICY_HND
*handle
= &q_u
->handle
;
7756 UNISTR2
*value
= &q_u
->valuename
;
7758 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7760 WERROR status
= WERR_OK
;
7761 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7764 DEBUG(5,("spoolss_deleteprinterdata\n"));
7767 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7771 if (!get_printer_snum(p
, handle
, &snum
))
7774 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7775 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7776 return WERR_ACCESS_DENIED
;
7779 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7780 if (!W_ERROR_IS_OK(status
))
7783 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
7785 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
7787 free_a_printer(&printer
, 2);
7792 /****************************************************************************
7793 ****************************************************************************/
7795 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
7797 POLICY_HND
*handle
= &q_u
->handle
;
7798 FORM
*form
= &q_u
->form
;
7799 nt_forms_struct tmpForm
;
7801 WERROR status
= WERR_OK
;
7802 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7805 nt_forms_struct
*list
=NULL
;
7806 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7808 DEBUG(5,("spoolss_addform\n"));
7811 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7816 /* forms can be added on printer of on the print server handle */
7818 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7820 if (!get_printer_snum(p
,handle
, &snum
))
7823 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7824 if (!W_ERROR_IS_OK(status
))
7828 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7829 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7830 status
= WERR_ACCESS_DENIED
;
7834 /* can't add if builtin */
7836 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7837 status
= WERR_ALREADY_EXISTS
;
7841 count
= get_ntforms(&list
);
7843 if(!add_a_form(&list
, form
, &count
)) {
7844 status
= WERR_NOMEM
;
7848 write_ntforms(&list
, count
);
7851 * ChangeID must always be set if this is a printer
7854 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7855 status
= mod_a_printer(*printer
, 2);
7859 free_a_printer(&printer
, 2);
7865 /****************************************************************************
7866 ****************************************************************************/
7868 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
7870 POLICY_HND
*handle
= &q_u
->handle
;
7871 UNISTR2
*form_name
= &q_u
->name
;
7872 nt_forms_struct tmpForm
;
7874 nt_forms_struct
*list
=NULL
;
7875 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7877 WERROR status
= WERR_OK
;
7878 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7880 DEBUG(5,("spoolss_deleteform\n"));
7883 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7887 /* forms can be deleted on printer of on the print server handle */
7889 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7891 if (!get_printer_snum(p
,handle
, &snum
))
7894 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7895 if (!W_ERROR_IS_OK(status
))
7899 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7900 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7901 status
= WERR_ACCESS_DENIED
;
7905 /* can't delete if builtin */
7907 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
7908 status
= WERR_INVALID_PARAM
;
7912 count
= get_ntforms(&list
);
7914 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
7918 * ChangeID must always be set if this is a printer
7921 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7922 status
= mod_a_printer(*printer
, 2);
7926 free_a_printer(&printer
, 2);
7932 /****************************************************************************
7933 ****************************************************************************/
7935 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
7937 POLICY_HND
*handle
= &q_u
->handle
;
7938 FORM
*form
= &q_u
->form
;
7939 nt_forms_struct tmpForm
;
7941 WERROR status
= WERR_OK
;
7942 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7945 nt_forms_struct
*list
=NULL
;
7946 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7948 DEBUG(5,("spoolss_setform\n"));
7951 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7955 /* forms can be modified on printer of on the print server handle */
7957 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7959 if (!get_printer_snum(p
,handle
, &snum
))
7962 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7963 if (!W_ERROR_IS_OK(status
))
7967 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7968 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7969 status
= WERR_ACCESS_DENIED
;
7973 /* can't set if builtin */
7974 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7975 status
= WERR_INVALID_PARAM
;
7979 count
= get_ntforms(&list
);
7980 update_a_form(&list
, form
, count
);
7981 write_ntforms(&list
, count
);
7984 * ChangeID must always be set if this is a printer
7987 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7988 status
= mod_a_printer(*printer
, 2);
7993 free_a_printer(&printer
, 2);
7999 /****************************************************************************
8000 enumprintprocessors level 1.
8001 ****************************************************************************/
8003 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8005 PRINTPROCESSOR_1
*info_1
=NULL
;
8007 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
8012 init_unistr(&info_1
->name
, "winprint");
8014 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8016 if (!alloc_buffer_size(buffer
, *needed
))
8017 return WERR_INSUFFICIENT_BUFFER
;
8019 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8023 if (*needed
> offered
) {
8025 return WERR_INSUFFICIENT_BUFFER
;
8031 /****************************************************************************
8032 ****************************************************************************/
8034 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8036 uint32 level
= q_u
->level
;
8037 NEW_BUFFER
*buffer
= NULL
;
8038 uint32 offered
= q_u
->offered
;
8039 uint32
*needed
= &r_u
->needed
;
8040 uint32
*returned
= &r_u
->returned
;
8042 /* that's an [in out] buffer */
8043 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8044 buffer
= r_u
->buffer
;
8046 DEBUG(5,("spoolss_enumprintprocessors\n"));
8049 * Enumerate the print processors ...
8051 * Just reply with "winprint", to keep NT happy
8052 * and I can use my nice printer checker.
8060 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8062 return WERR_UNKNOWN_LEVEL
;
8066 /****************************************************************************
8067 enumprintprocdatatypes level 1.
8068 ****************************************************************************/
8070 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8072 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8074 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
8079 init_unistr(&info_1
->name
, "RAW");
8081 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8083 if (!alloc_buffer_size(buffer
, *needed
))
8084 return WERR_INSUFFICIENT_BUFFER
;
8086 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8090 if (*needed
> offered
) {
8092 return WERR_INSUFFICIENT_BUFFER
;
8098 /****************************************************************************
8099 ****************************************************************************/
8101 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8103 uint32 level
= q_u
->level
;
8104 NEW_BUFFER
*buffer
= NULL
;
8105 uint32 offered
= q_u
->offered
;
8106 uint32
*needed
= &r_u
->needed
;
8107 uint32
*returned
= &r_u
->returned
;
8109 /* that's an [in out] buffer */
8110 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8111 buffer
= r_u
->buffer
;
8113 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8120 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8122 return WERR_UNKNOWN_LEVEL
;
8126 /****************************************************************************
8127 enumprintmonitors level 1.
8128 ****************************************************************************/
8130 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8132 PRINTMONITOR_1
*info_1
=NULL
;
8134 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
8139 init_unistr(&info_1
->name
, "Local Port");
8141 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
8143 if (!alloc_buffer_size(buffer
, *needed
))
8144 return WERR_INSUFFICIENT_BUFFER
;
8146 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
8150 if (*needed
> offered
) {
8152 return WERR_INSUFFICIENT_BUFFER
;
8158 /****************************************************************************
8159 enumprintmonitors level 2.
8160 ****************************************************************************/
8162 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8164 PRINTMONITOR_2
*info_2
=NULL
;
8166 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
8171 init_unistr(&info_2
->name
, "Local Port");
8172 init_unistr(&info_2
->environment
, "Windows NT X86");
8173 init_unistr(&info_2
->dll_name
, "localmon.dll");
8175 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
8177 if (!alloc_buffer_size(buffer
, *needed
))
8178 return WERR_INSUFFICIENT_BUFFER
;
8180 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
8184 if (*needed
> offered
) {
8186 return WERR_INSUFFICIENT_BUFFER
;
8192 /****************************************************************************
8193 ****************************************************************************/
8195 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8197 uint32 level
= q_u
->level
;
8198 NEW_BUFFER
*buffer
= NULL
;
8199 uint32 offered
= q_u
->offered
;
8200 uint32
*needed
= &r_u
->needed
;
8201 uint32
*returned
= &r_u
->returned
;
8203 /* that's an [in out] buffer */
8204 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8205 buffer
= r_u
->buffer
;
8207 DEBUG(5,("spoolss_enumprintmonitors\n"));
8210 * Enumerate the print monitors ...
8212 * Just reply with "Local Port", to keep NT happy
8213 * and I can use my nice printer checker.
8221 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8223 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8225 return WERR_UNKNOWN_LEVEL
;
8229 /****************************************************************************
8230 ****************************************************************************/
8232 static WERROR
getjob_level_1(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
8236 JOB_INFO_1
*info_1
=NULL
;
8238 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
8240 if (info_1
== NULL
) {
8245 for (i
=0; i
<count
&& found
==False
; i
++) {
8246 if (queue
[i
].job
==(int)jobid
)
8253 /* NT treats not found as bad param... yet another bad choice */
8254 return WERR_INVALID_PARAM
;
8257 fill_job_info_1(info_1
, &(queue
[i
-1]), i
, snum
);
8259 *needed
+= spoolss_size_job_info_1(info_1
);
8261 if (!alloc_buffer_size(buffer
, *needed
)) {
8263 return WERR_INSUFFICIENT_BUFFER
;
8266 smb_io_job_info_1("", buffer
, info_1
, 0);
8270 if (*needed
> offered
)
8271 return WERR_INSUFFICIENT_BUFFER
;
8276 /****************************************************************************
8277 ****************************************************************************/
8279 static WERROR
getjob_level_2(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
8284 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8286 DEVICEMODE
*devmode
= NULL
;
8287 NT_DEVICEMODE
*nt_devmode
= NULL
;
8289 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
8291 ZERO_STRUCTP(info_2
);
8293 if (info_2
== NULL
) {
8298 for ( i
=0; i
<count
&& found
==False
; i
++ )
8300 if (queue
[i
].job
== (int)jobid
)
8306 /* NT treats not found as bad param... yet another bad
8308 ret
= WERR_INVALID_PARAM
;
8312 ret
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
8313 if (!W_ERROR_IS_OK(ret
))
8317 * if the print job does not have a DEVMODE associated with it,
8318 * just use the one for the printer. A NULL devicemode is not
8319 * a failure condition
8322 if ( !(nt_devmode
=print_job_devmode( snum
, jobid
)) )
8323 devmode
= construct_dev_mode(snum
);
8325 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) != NULL
) {
8326 ZERO_STRUCTP( devmode
);
8327 convert_nt_devicemode( devmode
, nt_devmode
);
8331 fill_job_info_2(info_2
, &(queue
[i
-1]), i
, snum
, ntprinter
, devmode
);
8333 *needed
+= spoolss_size_job_info_2(info_2
);
8335 if (!alloc_buffer_size(buffer
, *needed
)) {
8336 ret
= WERR_INSUFFICIENT_BUFFER
;
8340 smb_io_job_info_2("", buffer
, info_2
, 0);
8342 if (*needed
> offered
) {
8343 ret
= WERR_INSUFFICIENT_BUFFER
;
8350 /* Cleanup allocated memory */
8352 free_job_info_2(info_2
); /* Also frees devmode */
8354 free_a_printer(&ntprinter
, 2);
8359 /****************************************************************************
8360 ****************************************************************************/
8362 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8364 POLICY_HND
*handle
= &q_u
->handle
;
8365 uint32 jobid
= q_u
->jobid
;
8366 uint32 level
= q_u
->level
;
8367 NEW_BUFFER
*buffer
= NULL
;
8368 uint32 offered
= q_u
->offered
;
8369 uint32
*needed
= &r_u
->needed
;
8370 WERROR wstatus
= WERR_OK
;
8374 print_queue_struct
*queue
= NULL
;
8375 print_status_struct prt_status
;
8377 /* that's an [in out] buffer */
8378 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8379 buffer
= r_u
->buffer
;
8381 DEBUG(5,("spoolss_getjob\n"));
8385 if (!get_printer_snum(p
, handle
, &snum
))
8388 count
= print_queue_status(snum
, &queue
, &prt_status
);
8390 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8391 count
, prt_status
.status
, prt_status
.message
));
8395 wstatus
= getjob_level_1(queue
, count
, snum
, jobid
,
8396 buffer
, offered
, needed
);
8399 wstatus
= getjob_level_2(queue
, count
, snum
, jobid
,
8400 buffer
, offered
, needed
);
8403 wstatus
= WERR_UNKNOWN_LEVEL
;
8411 /********************************************************************
8412 spoolss_getprinterdataex
8414 From MSDN documentation of GetPrinterDataEx: pass request
8415 to GetPrinterData if key is "PrinterDriverData".
8416 ********************************************************************/
8418 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8420 POLICY_HND
*handle
= &q_u
->handle
;
8421 uint32 in_size
= q_u
->size
;
8422 uint32
*type
= &r_u
->type
;
8423 uint32
*out_size
= &r_u
->size
;
8424 uint8
**data
= &r_u
->data
;
8425 uint32
*needed
= &r_u
->needed
;
8426 fstring keyname
, valuename
;
8428 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8430 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8432 WERROR status
= WERR_OK
;
8434 DEBUG(4,("_spoolss_getprinterdataex\n"));
8436 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8437 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
8439 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8440 keyname
, valuename
));
8442 /* in case of problem, return some default values */
8446 *out_size
= in_size
;
8449 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8450 status
= WERR_BADFID
;
8454 /* Is the handle to a printer or to the server? */
8456 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8457 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8458 status
= WERR_INVALID_PARAM
;
8462 if ( !get_printer_snum(p
,handle
, &snum
) )
8465 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8466 if ( !W_ERROR_IS_OK(status
) )
8469 /* check to see if the keyname is valid */
8470 if ( !strlen(keyname
) ) {
8471 status
= WERR_INVALID_PARAM
;
8475 if ( lookup_printerkey( &printer
->info_2
->data
, keyname
) == -1 ) {
8476 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
8477 free_a_printer( &printer
, 2 );
8478 status
= WERR_BADFILE
;
8482 /* When given a new keyname, we should just create it */
8484 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
8486 if (*needed
> *out_size
)
8487 status
= WERR_MORE_DATA
;
8490 if ( !W_ERROR_IS_OK(status
) )
8492 DEBUG(5, ("error: allocating %d\n", *out_size
));
8494 /* reply this param doesn't exist */
8498 if( (*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
8499 status
= WERR_NOMEM
;
8509 free_a_printer( &printer
, 2 );
8514 /********************************************************************
8515 * spoolss_setprinterdataex
8516 ********************************************************************/
8518 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
8520 POLICY_HND
*handle
= &q_u
->handle
;
8521 uint32 type
= q_u
->type
;
8522 uint8
*data
= q_u
->data
;
8523 uint32 real_len
= q_u
->real_len
;
8525 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8527 WERROR status
= WERR_OK
;
8528 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8533 DEBUG(4,("_spoolss_setprinterdataex\n"));
8535 /* From MSDN documentation of SetPrinterDataEx: pass request to
8536 SetPrinterData if key is "PrinterDriverData" */
8539 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8543 if ( !get_printer_snum(p
,handle
, &snum
) )
8547 * Access check : NT returns "access denied" if you make a
8548 * SetPrinterData call without the necessary privildge.
8549 * we were originally returning OK if nothing changed
8550 * which made Win2k issue **a lot** of SetPrinterData
8551 * when connecting to a printer --jerry
8554 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8556 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8557 return WERR_ACCESS_DENIED
;
8560 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8561 if (!W_ERROR_IS_OK(status
))
8564 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
8565 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
8567 /* check for OID in valuename */
8569 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
8575 /* save the registry data */
8577 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
8579 /* save the OID if one was specified and the previous set call succeeded */
8581 if ( W_ERROR_IS_OK(status
) && oid_string
)
8584 fstrcat( keyname
, "\\" );
8585 fstrcat( keyname
, SPOOL_OID_KEY
);
8588 * I'm not checking the status here on purpose. Don't know
8589 * if this is right, but I'm returning the status from the
8590 * previous set_printer_dataex() call. I have no idea if
8591 * this is right. --jerry
8594 set_printer_dataex( printer
, keyname
, valuename
,
8595 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
8598 free_a_printer(&printer
, 2);
8604 /********************************************************************
8605 * spoolss_deleteprinterdataex
8606 ********************************************************************/
8608 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
8610 POLICY_HND
*handle
= &q_u
->handle
;
8611 UNISTR2
*value
= &q_u
->valuename
;
8612 UNISTR2
*key
= &q_u
->keyname
;
8614 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8616 WERROR status
= WERR_OK
;
8617 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8618 pstring valuename
, keyname
;
8620 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8623 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8627 if (!get_printer_snum(p
, handle
, &snum
))
8630 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8631 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8632 return WERR_ACCESS_DENIED
;
8635 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8636 if (!W_ERROR_IS_OK(status
))
8639 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8640 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
8642 status
= delete_printer_dataex( printer
, keyname
, valuename
);
8644 free_a_printer(&printer
, 2);
8649 /********************************************************************
8650 * spoolss_enumprinterkey
8651 ********************************************************************/
8654 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
8657 fstring
*keynames
= NULL
;
8658 uint16
*enumkeys
= NULL
;
8661 POLICY_HND
*handle
= &q_u
->handle
;
8662 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8663 NT_PRINTER_DATA
*data
;
8664 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8666 WERROR status
= WERR_BADFILE
;
8669 DEBUG(4,("_spoolss_enumprinterkey\n"));
8672 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8676 if ( !get_printer_snum(p
,handle
, &snum
) )
8679 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8680 if (!W_ERROR_IS_OK(status
))
8683 /* get the list of subkey names */
8685 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
8686 data
= &printer
->info_2
->data
;
8688 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
8690 if ( num_keys
== -1 ) {
8691 status
= WERR_BADFILE
;
8695 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
8697 r_u
->needed
= printerkey_len
*2;
8699 if ( q_u
->size
< r_u
->needed
) {
8700 status
= WERR_MORE_DATA
;
8704 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
8705 status
= WERR_NOMEM
;
8711 if ( q_u
->size
< r_u
->needed
)
8712 status
= WERR_MORE_DATA
;
8715 free_a_printer( &printer
, 2 );
8716 SAFE_FREE( keynames
);
8721 /********************************************************************
8722 * spoolss_deleteprinterkey
8723 ********************************************************************/
8725 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
8727 POLICY_HND
*handle
= &q_u
->handle
;
8728 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
8730 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8734 DEBUG(5,("spoolss_deleteprinterkey\n"));
8737 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8741 /* if keyname == NULL, return error */
8743 if ( !q_u
->keyname
.buffer
)
8744 return WERR_INVALID_PARAM
;
8746 if (!get_printer_snum(p
, handle
, &snum
))
8749 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8750 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8751 return WERR_ACCESS_DENIED
;
8754 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8755 if (!W_ERROR_IS_OK(status
))
8758 /* delete the key and all subneys */
8760 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
8762 status
= delete_all_printer_data( printer
->info_2
, key
);
8764 if ( W_ERROR_IS_OK(status
) )
8765 status
= mod_a_printer(*printer
, 2);
8767 free_a_printer( &printer
, 2 );
8773 /********************************************************************
8774 * spoolss_enumprinterdataex
8775 ********************************************************************/
8777 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
8779 POLICY_HND
*handle
= &q_u
->handle
;
8780 uint32 in_size
= q_u
->size
;
8783 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8784 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
8785 NT_PRINTER_DATA
*p_data
;
8787 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8792 REGISTRY_VALUE
*val
;
8797 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8800 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
8804 /* first get the printer off of disk */
8806 if (!get_printer_snum(p
,handle
, &snum
))
8809 ZERO_STRUCT(printer
);
8810 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8811 if (!W_ERROR_IS_OK(result
))
8814 /* now look for a match on the key name */
8816 p_data
= &printer
->info_2
->data
;
8818 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
8819 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
8821 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
8822 result
= WERR_INVALID_PARAM
;
8829 /* allocate the memory for the array of pointers -- if necessary */
8831 num_entries
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
8834 if ( (enum_values
=talloc(p
->mem_ctx
, num_entries
*sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
8836 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8837 num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
8838 result
= WERR_NOMEM
;
8842 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
8846 * loop through all params and build the array to pass
8847 * back to the client
8850 for ( i
=0; i
<num_entries
; i
++ )
8852 /* lookup the registry value */
8854 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
8855 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
8859 value_name
= regval_name( val
);
8860 init_unistr( &enum_values
[i
].valuename
, value_name
);
8861 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
8862 enum_values
[i
].type
= regval_type( val
);
8864 data_len
= regval_size( val
);
8866 if ( !(enum_values
[i
].data
= talloc_memdup(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
8868 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8870 result
= WERR_NOMEM
;
8874 enum_values
[i
].data_len
= data_len
;
8876 /* keep track of the size of the array in bytes */
8878 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
8881 /* housekeeping information in the reply */
8883 r_u
->needed
= needed
;
8884 r_u
->returned
= num_entries
;
8886 if (needed
> in_size
) {
8887 result
= WERR_MORE_DATA
;
8891 /* copy data into the reply */
8893 r_u
->ctr
.size
= r_u
->needed
;
8894 r_u
->ctr
.size_of_array
= r_u
->returned
;
8895 r_u
->ctr
.values
= enum_values
;
8900 free_a_printer(&printer
, 2);
8905 /****************************************************************************
8906 ****************************************************************************/
8908 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
8910 init_unistr(&info
->name
, name
);
8913 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
8914 UNISTR2
*environment
,
8921 pstring short_archi
;
8922 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
8924 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
8926 if (get_short_archi(short_archi
, long_archi
)==False
)
8927 return WERR_INVALID_ENVIRONMENT
;
8929 if((info
=(PRINTPROCESSOR_DIRECTORY_1
*)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1
))) == NULL
)
8932 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8934 fill_printprocessordirectory_1(info
, path
);
8936 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
8938 if (!alloc_buffer_size(buffer
, *needed
)) {
8940 return WERR_INSUFFICIENT_BUFFER
;
8943 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
8947 if (*needed
> offered
)
8948 return WERR_INSUFFICIENT_BUFFER
;
8953 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
8955 uint32 level
= q_u
->level
;
8956 NEW_BUFFER
*buffer
= NULL
;
8957 uint32 offered
= q_u
->offered
;
8958 uint32
*needed
= &r_u
->needed
;
8961 /* that's an [in out] buffer */
8962 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8963 buffer
= r_u
->buffer
;
8965 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8971 result
= getprintprocessordirectory_level_1
8972 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
8975 result
= WERR_UNKNOWN_LEVEL
;
8983 WERROR
_spoolss_replyopenprinter(pipes_struct
*p
, SPOOL_Q_REPLYOPENPRINTER
*q_u
,
8984 SPOOL_R_REPLYOPENPRINTER
*r_u
)
8986 DEBUG(5,("_spoolss_replyopenprinter\n"));
8988 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u
->printer
));
8993 WERROR
_spoolss_replycloseprinter(pipes_struct
*p
, SPOOL_Q_REPLYCLOSEPRINTER
*q_u
,
8994 SPOOL_R_REPLYCLOSEPRINTER
*r_u
)
8996 DEBUG(5,("_spoolss_replycloseprinter\n"));