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 char * drv_ver_to_os
[] = {
46 "WIN9X", /* driver version/cversion 0 */
48 "WINNT", /* driver version/cversion 2 */
49 "WIN2K", /* driver version/cversion 3 */
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();
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(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 char *key
, 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
);
2107 if ( (*data
= (uint8
*)talloc_memdup(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2115 DEBUG(5,("get_printer_dataex: copy done\n"));
2120 /****************************************************************************
2121 Internal routine for removing printerdata
2122 ***************************************************************************/
2124 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, char *key
, char *value
)
2126 delete_printer_data( printer
->info_2
, key
, value
);
2128 return mod_a_printer(*printer
, 2);
2131 /****************************************************************************
2132 Internal routine for storing printerdata
2133 ***************************************************************************/
2135 static WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, char *key
, char *value
,
2136 uint32 type
, uint8
*data
, int real_len
)
2138 delete_printer_data( printer
->info_2
, key
, value
);
2140 add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2142 return mod_a_printer(*printer
, 2);
2145 /********************************************************************
2146 GetPrinterData on a printer server Handle.
2147 ********************************************************************/
2149 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2153 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2155 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2157 if((*data
= (uint8
*)talloc_zero(ctx
, 4*sizeof(uint8
) )) == NULL
)
2163 if (!StrCaseCmp(value
, "BeepEnabled")) {
2165 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2167 SIVAL(*data
, 0, 0x00);
2172 if (!StrCaseCmp(value
, "EventLog")) {
2174 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2176 /* formally was 0x1b */
2177 SIVAL(*data
, 0, 0x0);
2182 if (!StrCaseCmp(value
, "NetPopup")) {
2184 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2186 SIVAL(*data
, 0, 0x00);
2191 if (!StrCaseCmp(value
, "MajorVersion")) {
2193 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2204 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2207 fstrcpy(string
, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH
));
2209 *needed
= 2*(strlen(string
)+1);
2210 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2212 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2214 /* it's done by hand ready to go on the wire */
2215 for (i
=0; i
<strlen(string
); i
++) {
2216 (*data
)[2*i
]=string
[i
];
2217 (*data
)[2*i
+1]='\0';
2222 if (!StrCaseCmp(value
, "Architecture")) {
2223 pstring string
="Windows NT x86";
2225 *needed
= 2*(strlen(string
)+1);
2226 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2228 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2229 for (i
=0; i
<strlen(string
); i
++) {
2230 (*data
)[2*i
]=string
[i
];
2231 (*data
)[2*i
+1]='\0';
2236 if (!StrCaseCmp(value
, "DsPresent")) {
2238 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2240 SIVAL(*data
, 0, 0x01);
2245 if (!StrCaseCmp(value
, "DNSMachineName")) {
2248 if (!get_myfullname(hostname
))
2249 return WERR_BADFILE
;
2251 *needed
= 2*(strlen(hostname
)+1);
2252 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2254 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2255 for (i
=0; i
<strlen(hostname
); i
++) {
2256 (*data
)[2*i
]=hostname
[i
];
2257 (*data
)[2*i
+1]='\0';
2263 return WERR_BADFILE
;
2266 /********************************************************************
2267 * spoolss_getprinterdata
2268 ********************************************************************/
2270 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2272 POLICY_HND
*handle
= &q_u
->handle
;
2273 UNISTR2
*valuename
= &q_u
->valuename
;
2274 uint32 in_size
= q_u
->size
;
2275 uint32
*type
= &r_u
->type
;
2276 uint32
*out_size
= &r_u
->size
;
2277 uint8
**data
= &r_u
->data
;
2278 uint32
*needed
= &r_u
->needed
;
2281 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2282 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2286 * Reminder: when it's a string, the length is in BYTES
2287 * even if UNICODE is negociated.
2292 *out_size
= in_size
;
2294 /* in case of problem, return some default values */
2299 DEBUG(4,("_spoolss_getprinterdata\n"));
2302 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2303 status
= WERR_BADFID
;
2307 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2309 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2310 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2313 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2314 status
= WERR_BADFID
;
2318 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
2319 if ( !W_ERROR_IS_OK(status
) )
2322 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2324 if ( strequal(value
, "ChangeId") ) {
2326 *needed
= sizeof(uint32
);
2327 if ( (*data
= (uint8
*)talloc(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2328 status
= WERR_NOMEM
;
2331 **data
= printer
->info_2
->changeid
;
2335 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2338 if (*needed
> *out_size
)
2339 status
= WERR_MORE_DATA
;
2342 if ( !W_ERROR_IS_OK(status
) )
2344 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2346 /* reply this param doesn't exist */
2349 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
2351 free_a_printer( &printer
, 2 );
2360 /* cleanup & exit */
2363 free_a_printer( &printer
, 2 );
2368 /*********************************************************
2369 Connect to the client machine.
2370 **********************************************************/
2372 static BOOL
spoolss_connect_to_client(struct cli_state
*the_cli
, const char *remote_machine
)
2374 ZERO_STRUCTP(the_cli
);
2375 if(cli_initialise(the_cli
) == NULL
) {
2376 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2380 if(!resolve_name( remote_machine
, &the_cli
->dest_ip
, 0x20)) {
2381 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine
));
2382 cli_shutdown(the_cli
);
2386 if (ismyip(the_cli
->dest_ip
)) {
2387 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2388 cli_shutdown(the_cli
);
2392 if (!cli_connect(the_cli
, remote_machine
, &the_cli
->dest_ip
)) {
2393 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2394 cli_shutdown(the_cli
);
2398 if (!attempt_netbios_session_request(the_cli
, global_myname(), remote_machine
, &the_cli
->dest_ip
)) {
2399 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2401 cli_shutdown(the_cli
);
2405 the_cli
->protocol
= PROTOCOL_NT1
;
2407 if (!cli_negprot(the_cli
)) {
2408 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2409 cli_shutdown(the_cli
);
2413 if (the_cli
->protocol
!= PROTOCOL_NT1
) {
2414 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2415 cli_shutdown(the_cli
);
2420 * Do an anonymous session setup.
2423 if (!cli_session_setup(the_cli
, "", "", 0, "", 0, "")) {
2424 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2425 cli_shutdown(the_cli
);
2429 if (!(the_cli
->sec_mode
& 1)) {
2430 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine
));
2431 cli_shutdown(the_cli
);
2435 if (!cli_send_tconX(the_cli
, "IPC$", "IPC", "", 1)) {
2436 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2437 cli_shutdown(the_cli
);
2442 * Ok - we have an anonymous connection to the IPC$ share.
2443 * Now start the NT Domain stuff :-).
2446 if(cli_nt_session_open(the_cli
, PI_SPOOLSS
) == False
) {
2447 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
)));
2448 cli_nt_session_close(the_cli
);
2449 cli_ulogoff(the_cli
);
2450 cli_shutdown(the_cli
);
2457 /***************************************************************************
2458 Connect to the client.
2459 ****************************************************************************/
2461 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
, uint32 localprinter
, uint32 type
, POLICY_HND
*handle
)
2466 * If it's the first connection, contact the client
2467 * and connect to the IPC$ share anonumously
2469 if (smb_connections
==0) {
2470 fstring unix_printer
;
2472 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2474 if(!spoolss_connect_to_client(¬ify_cli
, unix_printer
))
2477 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message_list
);
2478 /* Tell the connections db we're now interested in printer
2479 * notify messages. */
2480 register_message_flags( True
, FLAG_MSG_PRINTING
);
2484 * Tell the specific printing tdb we want messages for this printer
2485 * by registering our PID.
2488 if (!print_notify_register_pid(snum
))
2489 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2493 result
= cli_spoolss_reply_open_printer(¬ify_cli
, notify_cli
.mem_ctx
, printer
, localprinter
,
2496 if (!W_ERROR_IS_OK(result
))
2497 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2498 dos_errstr(result
)));
2500 return (W_ERROR_IS_OK(result
));
2503 /********************************************************************
2505 * ReplyFindFirstPrinterChangeNotifyEx
2507 * before replying OK: status=0 a rpc call is made to the workstation
2508 * asking ReplyOpenPrinter
2510 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2511 * called from api_spoolss_rffpcnex
2512 ********************************************************************/
2514 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2516 POLICY_HND
*handle
= &q_u
->handle
;
2517 uint32 flags
= q_u
->flags
;
2518 uint32 options
= q_u
->options
;
2519 UNISTR2
*localmachine
= &q_u
->localmachine
;
2520 uint32 printerlocal
= q_u
->printerlocal
;
2522 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2524 /* store the notify value in the printer struct */
2526 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2529 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2533 Printer
->notify
.flags
=flags
;
2534 Printer
->notify
.options
=options
;
2535 Printer
->notify
.printerlocal
=printerlocal
;
2537 if (Printer
->notify
.option
)
2538 free_spool_notify_option(&Printer
->notify
.option
);
2540 Printer
->notify
.option
=dup_spool_notify_option(option
);
2542 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2543 sizeof(Printer
->notify
.localmachine
)-1);
2545 /* Connect to the client machine and send a ReplyOpenPrinter */
2547 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2549 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
2550 !get_printer_snum(p
, handle
, &snum
) )
2553 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2554 Printer
->notify
.printerlocal
, 1,
2555 &Printer
->notify
.client_hnd
))
2556 return WERR_SERVER_UNAVAILABLE
;
2558 Printer
->notify
.client_connected
=True
;
2563 /*******************************************************************
2564 * fill a notify_info_data with the servername
2565 ********************************************************************/
2567 void spoolss_notify_server_name(int snum
,
2568 SPOOL_NOTIFY_INFO_DATA
*data
,
2569 print_queue_struct
*queue
,
2570 NT_PRINTER_INFO_LEVEL
*printer
,
2571 TALLOC_CTX
*mem_ctx
)
2573 pstring temp_name
, temp
;
2576 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
2578 len
= rpcstr_push(temp
, temp_name
, sizeof(temp
)-2, STR_TERMINATE
);
2580 data
->notify_data
.data
.length
= len
;
2581 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2583 if (!data
->notify_data
.data
.string
) {
2584 data
->notify_data
.data
.length
= 0;
2588 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2591 /*******************************************************************
2592 * fill a notify_info_data with the printername (not including the servername).
2593 ********************************************************************/
2595 void spoolss_notify_printer_name(int snum
,
2596 SPOOL_NOTIFY_INFO_DATA
*data
,
2597 print_queue_struct
*queue
,
2598 NT_PRINTER_INFO_LEVEL
*printer
,
2599 TALLOC_CTX
*mem_ctx
)
2604 /* the notify name should not contain the \\server\ part */
2605 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2608 p
= printer
->info_2
->printername
;
2613 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2615 data
->notify_data
.data
.length
= len
;
2616 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2618 if (!data
->notify_data
.data
.string
) {
2619 data
->notify_data
.data
.length
= 0;
2623 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2626 /*******************************************************************
2627 * fill a notify_info_data with the servicename
2628 ********************************************************************/
2630 void spoolss_notify_share_name(int snum
,
2631 SPOOL_NOTIFY_INFO_DATA
*data
,
2632 print_queue_struct
*queue
,
2633 NT_PRINTER_INFO_LEVEL
*printer
,
2634 TALLOC_CTX
*mem_ctx
)
2639 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2641 data
->notify_data
.data
.length
= len
;
2642 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2644 if (!data
->notify_data
.data
.string
) {
2645 data
->notify_data
.data
.length
= 0;
2649 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2652 /*******************************************************************
2653 * fill a notify_info_data with the port name
2654 ********************************************************************/
2656 void spoolss_notify_port_name(int snum
,
2657 SPOOL_NOTIFY_INFO_DATA
*data
,
2658 print_queue_struct
*queue
,
2659 NT_PRINTER_INFO_LEVEL
*printer
,
2660 TALLOC_CTX
*mem_ctx
)
2665 /* even if it's strange, that's consistant in all the code */
2667 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2669 data
->notify_data
.data
.length
= len
;
2670 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2672 if (!data
->notify_data
.data
.string
) {
2673 data
->notify_data
.data
.length
= 0;
2677 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2680 /*******************************************************************
2681 * fill a notify_info_data with the printername
2682 * but it doesn't exist, have to see what to do
2683 ********************************************************************/
2685 void spoolss_notify_driver_name(int snum
,
2686 SPOOL_NOTIFY_INFO_DATA
*data
,
2687 print_queue_struct
*queue
,
2688 NT_PRINTER_INFO_LEVEL
*printer
,
2689 TALLOC_CTX
*mem_ctx
)
2694 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2696 data
->notify_data
.data
.length
= len
;
2697 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2699 if (!data
->notify_data
.data
.string
) {
2700 data
->notify_data
.data
.length
= 0;
2704 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2707 /*******************************************************************
2708 * fill a notify_info_data with the comment
2709 ********************************************************************/
2711 void spoolss_notify_comment(int snum
,
2712 SPOOL_NOTIFY_INFO_DATA
*data
,
2713 print_queue_struct
*queue
,
2714 NT_PRINTER_INFO_LEVEL
*printer
,
2715 TALLOC_CTX
*mem_ctx
)
2720 if (*printer
->info_2
->comment
== '\0')
2721 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2723 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2725 data
->notify_data
.data
.length
= len
;
2726 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2728 if (!data
->notify_data
.data
.string
) {
2729 data
->notify_data
.data
.length
= 0;
2733 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2736 /*******************************************************************
2737 * fill a notify_info_data with the comment
2738 * location = "Room 1, floor 2, building 3"
2739 ********************************************************************/
2741 void spoolss_notify_location(int snum
,
2742 SPOOL_NOTIFY_INFO_DATA
*data
,
2743 print_queue_struct
*queue
,
2744 NT_PRINTER_INFO_LEVEL
*printer
,
2745 TALLOC_CTX
*mem_ctx
)
2750 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2752 data
->notify_data
.data
.length
= len
;
2753 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2755 if (!data
->notify_data
.data
.string
) {
2756 data
->notify_data
.data
.length
= 0;
2760 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2763 /*******************************************************************
2764 * fill a notify_info_data with the device mode
2765 * jfm:xxxx don't to it for know but that's a real problem !!!
2766 ********************************************************************/
2768 static void spoolss_notify_devmode(int snum
,
2769 SPOOL_NOTIFY_INFO_DATA
*data
,
2770 print_queue_struct
*queue
,
2771 NT_PRINTER_INFO_LEVEL
*printer
,
2772 TALLOC_CTX
*mem_ctx
)
2776 /*******************************************************************
2777 * fill a notify_info_data with the separator file name
2778 ********************************************************************/
2780 void spoolss_notify_sepfile(int snum
,
2781 SPOOL_NOTIFY_INFO_DATA
*data
,
2782 print_queue_struct
*queue
,
2783 NT_PRINTER_INFO_LEVEL
*printer
,
2784 TALLOC_CTX
*mem_ctx
)
2789 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2791 data
->notify_data
.data
.length
= len
;
2792 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2794 if (!data
->notify_data
.data
.string
) {
2795 data
->notify_data
.data
.length
= 0;
2799 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2802 /*******************************************************************
2803 * fill a notify_info_data with the print processor
2804 * jfm:xxxx return always winprint to indicate we don't do anything to it
2805 ********************************************************************/
2807 void spoolss_notify_print_processor(int snum
,
2808 SPOOL_NOTIFY_INFO_DATA
*data
,
2809 print_queue_struct
*queue
,
2810 NT_PRINTER_INFO_LEVEL
*printer
,
2811 TALLOC_CTX
*mem_ctx
)
2816 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
2818 data
->notify_data
.data
.length
= len
;
2819 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2821 if (!data
->notify_data
.data
.string
) {
2822 data
->notify_data
.data
.length
= 0;
2826 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2829 /*******************************************************************
2830 * fill a notify_info_data with the print processor options
2831 * jfm:xxxx send an empty string
2832 ********************************************************************/
2834 void spoolss_notify_parameters(int snum
,
2835 SPOOL_NOTIFY_INFO_DATA
*data
,
2836 print_queue_struct
*queue
,
2837 NT_PRINTER_INFO_LEVEL
*printer
,
2838 TALLOC_CTX
*mem_ctx
)
2843 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
2845 data
->notify_data
.data
.length
= len
;
2846 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2848 if (!data
->notify_data
.data
.string
) {
2849 data
->notify_data
.data
.length
= 0;
2853 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2856 /*******************************************************************
2857 * fill a notify_info_data with the data type
2858 * jfm:xxxx always send RAW as data type
2859 ********************************************************************/
2861 void spoolss_notify_datatype(int snum
,
2862 SPOOL_NOTIFY_INFO_DATA
*data
,
2863 print_queue_struct
*queue
,
2864 NT_PRINTER_INFO_LEVEL
*printer
,
2865 TALLOC_CTX
*mem_ctx
)
2870 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
2872 data
->notify_data
.data
.length
= len
;
2873 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2875 if (!data
->notify_data
.data
.string
) {
2876 data
->notify_data
.data
.length
= 0;
2880 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2883 /*******************************************************************
2884 * fill a notify_info_data with the security descriptor
2885 * jfm:xxxx send an null pointer to say no security desc
2886 * have to implement security before !
2887 ********************************************************************/
2889 static void spoolss_notify_security_desc(int snum
,
2890 SPOOL_NOTIFY_INFO_DATA
*data
,
2891 print_queue_struct
*queue
,
2892 NT_PRINTER_INFO_LEVEL
*printer
,
2893 TALLOC_CTX
*mem_ctx
)
2895 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
2896 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
2899 /*******************************************************************
2900 * fill a notify_info_data with the attributes
2901 * jfm:xxxx a samba printer is always shared
2902 ********************************************************************/
2904 void spoolss_notify_attributes(int snum
,
2905 SPOOL_NOTIFY_INFO_DATA
*data
,
2906 print_queue_struct
*queue
,
2907 NT_PRINTER_INFO_LEVEL
*printer
,
2908 TALLOC_CTX
*mem_ctx
)
2910 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
2911 data
->notify_data
.value
[1] = 0;
2914 /*******************************************************************
2915 * fill a notify_info_data with the priority
2916 ********************************************************************/
2918 static void spoolss_notify_priority(int snum
,
2919 SPOOL_NOTIFY_INFO_DATA
*data
,
2920 print_queue_struct
*queue
,
2921 NT_PRINTER_INFO_LEVEL
*printer
,
2922 TALLOC_CTX
*mem_ctx
)
2924 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
2925 data
->notify_data
.value
[1] = 0;
2928 /*******************************************************************
2929 * fill a notify_info_data with the default priority
2930 ********************************************************************/
2932 static void spoolss_notify_default_priority(int snum
,
2933 SPOOL_NOTIFY_INFO_DATA
*data
,
2934 print_queue_struct
*queue
,
2935 NT_PRINTER_INFO_LEVEL
*printer
,
2936 TALLOC_CTX
*mem_ctx
)
2938 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
2939 data
->notify_data
.value
[1] = 0;
2942 /*******************************************************************
2943 * fill a notify_info_data with the start time
2944 ********************************************************************/
2946 static void spoolss_notify_start_time(int snum
,
2947 SPOOL_NOTIFY_INFO_DATA
*data
,
2948 print_queue_struct
*queue
,
2949 NT_PRINTER_INFO_LEVEL
*printer
,
2950 TALLOC_CTX
*mem_ctx
)
2952 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
2953 data
->notify_data
.value
[1] = 0;
2956 /*******************************************************************
2957 * fill a notify_info_data with the until time
2958 ********************************************************************/
2960 static void spoolss_notify_until_time(int snum
,
2961 SPOOL_NOTIFY_INFO_DATA
*data
,
2962 print_queue_struct
*queue
,
2963 NT_PRINTER_INFO_LEVEL
*printer
,
2964 TALLOC_CTX
*mem_ctx
)
2966 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
2967 data
->notify_data
.value
[1] = 0;
2970 /*******************************************************************
2971 * fill a notify_info_data with the status
2972 ********************************************************************/
2974 static void spoolss_notify_status(int snum
,
2975 SPOOL_NOTIFY_INFO_DATA
*data
,
2976 print_queue_struct
*queue
,
2977 NT_PRINTER_INFO_LEVEL
*printer
,
2978 TALLOC_CTX
*mem_ctx
)
2980 print_status_struct status
;
2982 print_queue_length(snum
, &status
);
2983 data
->notify_data
.value
[0]=(uint32
) status
.status
;
2984 data
->notify_data
.value
[1] = 0;
2987 /*******************************************************************
2988 * fill a notify_info_data with the number of jobs queued
2989 ********************************************************************/
2991 void spoolss_notify_cjobs(int snum
,
2992 SPOOL_NOTIFY_INFO_DATA
*data
,
2993 print_queue_struct
*queue
,
2994 NT_PRINTER_INFO_LEVEL
*printer
,
2995 TALLOC_CTX
*mem_ctx
)
2997 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
2998 data
->notify_data
.value
[1] = 0;
3001 /*******************************************************************
3002 * fill a notify_info_data with the average ppm
3003 ********************************************************************/
3005 static void spoolss_notify_average_ppm(int snum
,
3006 SPOOL_NOTIFY_INFO_DATA
*data
,
3007 print_queue_struct
*queue
,
3008 NT_PRINTER_INFO_LEVEL
*printer
,
3009 TALLOC_CTX
*mem_ctx
)
3011 /* always respond 8 pages per minutes */
3012 /* a little hard ! */
3013 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3014 data
->notify_data
.value
[1] = 0;
3017 /*******************************************************************
3018 * fill a notify_info_data with username
3019 ********************************************************************/
3021 static void spoolss_notify_username(int snum
,
3022 SPOOL_NOTIFY_INFO_DATA
*data
,
3023 print_queue_struct
*queue
,
3024 NT_PRINTER_INFO_LEVEL
*printer
,
3025 TALLOC_CTX
*mem_ctx
)
3030 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3032 data
->notify_data
.data
.length
= len
;
3033 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3035 if (!data
->notify_data
.data
.string
) {
3036 data
->notify_data
.data
.length
= 0;
3040 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3043 /*******************************************************************
3044 * fill a notify_info_data with job status
3045 ********************************************************************/
3047 static void spoolss_notify_job_status(int snum
,
3048 SPOOL_NOTIFY_INFO_DATA
*data
,
3049 print_queue_struct
*queue
,
3050 NT_PRINTER_INFO_LEVEL
*printer
,
3051 TALLOC_CTX
*mem_ctx
)
3053 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3054 data
->notify_data
.value
[1] = 0;
3057 /*******************************************************************
3058 * fill a notify_info_data with job name
3059 ********************************************************************/
3061 static void spoolss_notify_job_name(int snum
,
3062 SPOOL_NOTIFY_INFO_DATA
*data
,
3063 print_queue_struct
*queue
,
3064 NT_PRINTER_INFO_LEVEL
*printer
,
3065 TALLOC_CTX
*mem_ctx
)
3070 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3072 data
->notify_data
.data
.length
= len
;
3073 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3075 if (!data
->notify_data
.data
.string
) {
3076 data
->notify_data
.data
.length
= 0;
3080 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3083 /*******************************************************************
3084 * fill a notify_info_data with job status
3085 ********************************************************************/
3087 static void spoolss_notify_job_status_string(int snum
,
3088 SPOOL_NOTIFY_INFO_DATA
*data
,
3089 print_queue_struct
*queue
,
3090 NT_PRINTER_INFO_LEVEL
*printer
,
3091 TALLOC_CTX
*mem_ctx
)
3094 * Now we're returning job status codes we just return a "" here. JRA.
3101 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3104 switch (queue
->status
) {
3109 p
= ""; /* NT provides the paused string */
3118 #endif /* NO LONGER NEEDED. */
3120 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3122 data
->notify_data
.data
.length
= len
;
3123 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3125 if (!data
->notify_data
.data
.string
) {
3126 data
->notify_data
.data
.length
= 0;
3130 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3133 /*******************************************************************
3134 * fill a notify_info_data with job time
3135 ********************************************************************/
3137 static void spoolss_notify_job_time(int snum
,
3138 SPOOL_NOTIFY_INFO_DATA
*data
,
3139 print_queue_struct
*queue
,
3140 NT_PRINTER_INFO_LEVEL
*printer
,
3141 TALLOC_CTX
*mem_ctx
)
3143 data
->notify_data
.value
[0]=0x0;
3144 data
->notify_data
.value
[1]=0;
3147 /*******************************************************************
3148 * fill a notify_info_data with job size
3149 ********************************************************************/
3151 static void spoolss_notify_job_size(int snum
,
3152 SPOOL_NOTIFY_INFO_DATA
*data
,
3153 print_queue_struct
*queue
,
3154 NT_PRINTER_INFO_LEVEL
*printer
,
3155 TALLOC_CTX
*mem_ctx
)
3157 data
->notify_data
.value
[0]=queue
->size
;
3158 data
->notify_data
.value
[1]=0;
3161 /*******************************************************************
3162 * fill a notify_info_data with page info
3163 ********************************************************************/
3164 static void spoolss_notify_total_pages(int snum
,
3165 SPOOL_NOTIFY_INFO_DATA
*data
,
3166 print_queue_struct
*queue
,
3167 NT_PRINTER_INFO_LEVEL
*printer
,
3168 TALLOC_CTX
*mem_ctx
)
3170 data
->notify_data
.value
[0]=queue
->page_count
;
3171 data
->notify_data
.value
[1]=0;
3174 /*******************************************************************
3175 * fill a notify_info_data with pages printed info.
3176 ********************************************************************/
3177 static void spoolss_notify_pages_printed(int snum
,
3178 SPOOL_NOTIFY_INFO_DATA
*data
,
3179 print_queue_struct
*queue
,
3180 NT_PRINTER_INFO_LEVEL
*printer
,
3181 TALLOC_CTX
*mem_ctx
)
3183 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3184 data
->notify_data
.value
[1]=0;
3187 /*******************************************************************
3188 Fill a notify_info_data with job position.
3189 ********************************************************************/
3191 static void spoolss_notify_job_position(int snum
,
3192 SPOOL_NOTIFY_INFO_DATA
*data
,
3193 print_queue_struct
*queue
,
3194 NT_PRINTER_INFO_LEVEL
*printer
,
3195 TALLOC_CTX
*mem_ctx
)
3197 data
->notify_data
.value
[0]=queue
->job
;
3198 data
->notify_data
.value
[1]=0;
3201 /*******************************************************************
3202 Fill a notify_info_data with submitted time.
3203 ********************************************************************/
3205 static void spoolss_notify_submitted_time(int snum
,
3206 SPOOL_NOTIFY_INFO_DATA
*data
,
3207 print_queue_struct
*queue
,
3208 NT_PRINTER_INFO_LEVEL
*printer
,
3209 TALLOC_CTX
*mem_ctx
)
3216 t
=gmtime(&queue
->time
);
3218 len
= sizeof(SYSTEMTIME
);
3220 data
->notify_data
.data
.length
= len
;
3221 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3223 if (!data
->notify_data
.data
.string
) {
3224 data
->notify_data
.data
.length
= 0;
3228 make_systemtime(&st
, t
);
3231 * Systemtime must be linearized as a set of UINT16's.
3232 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3235 p
= (char *)data
->notify_data
.data
.string
;
3236 SSVAL(p
, 0, st
.year
);
3237 SSVAL(p
, 2, st
.month
);
3238 SSVAL(p
, 4, st
.dayofweek
);
3239 SSVAL(p
, 6, st
.day
);
3240 SSVAL(p
, 8, st
.hour
);
3241 SSVAL(p
, 10, st
.minute
);
3242 SSVAL(p
, 12, st
.second
);
3243 SSVAL(p
, 14, st
.milliseconds
);
3246 struct s_notify_info_data_table
3252 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3253 print_queue_struct
*queue
,
3254 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3257 /* A table describing the various print notification constants and
3258 whether the notification data is a pointer to a variable sized
3259 buffer, a one value uint32 or a two value uint32. */
3261 struct s_notify_info_data_table notify_info_data_table
[] =
3263 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3264 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3265 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3266 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3267 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3268 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3269 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3270 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3271 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3272 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3273 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3274 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3275 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3276 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3277 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3278 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3279 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3280 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3281 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3282 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3283 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3284 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3285 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3286 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3287 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3288 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3289 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3290 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3291 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3292 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3293 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3294 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3295 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3296 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3297 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3298 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3299 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3300 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3301 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3302 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3303 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3304 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3305 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3306 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3307 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3308 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3309 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3310 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3311 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3314 /*******************************************************************
3315 Return the size of info_data structure.
3316 ********************************************************************/
3318 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3322 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++)
3324 if ( (notify_info_data_table
[i
].type
== type
)
3325 && (notify_info_data_table
[i
].field
== field
) )
3327 switch(notify_info_data_table
[i
].size
)
3329 case NOTIFY_ONE_VALUE
:
3330 case NOTIFY_TWO_VALUE
:
3335 /* The only pointer notify data I have seen on
3336 the wire is the submitted time and this has
3337 the notify size set to 4. -tpot */
3339 case NOTIFY_POINTER
:
3342 case NOTIFY_SECDESC
:
3348 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3353 /*******************************************************************
3354 Return the type of notify_info_data.
3355 ********************************************************************/
3357 static int type_of_notify_info_data(uint16 type
, uint16 field
)
3361 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3362 if (notify_info_data_table
[i
].type
== type
&&
3363 notify_info_data_table
[i
].field
== field
)
3364 return notify_info_data_table
[i
].size
;
3370 /****************************************************************************
3371 ****************************************************************************/
3373 static int search_notify(uint16 type
, uint16 field
, int *value
)
3377 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3378 if (notify_info_data_table
[i
].type
== type
&&
3379 notify_info_data_table
[i
].field
== field
&&
3380 notify_info_data_table
[i
].fn
!= NULL
) {
3389 /****************************************************************************
3390 ****************************************************************************/
3392 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3394 info_data
->type
= type
;
3395 info_data
->field
= field
;
3396 info_data
->reserved
= 0;
3398 info_data
->size
= size_of_notify_info_data(type
, field
);
3399 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3406 /*******************************************************************
3408 * fill a notify_info struct with info asked
3410 ********************************************************************/
3412 static BOOL
construct_notify_printer_info(SPOOL_NOTIFY_INFO
*info
, int
3413 snum
, SPOOL_NOTIFY_OPTION_TYPE
3414 *option_type
, uint32 id
,
3415 TALLOC_CTX
*mem_ctx
)
3421 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3422 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3423 print_queue_struct
*queue
=NULL
;
3425 type
=option_type
->type
;
3427 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3428 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3429 option_type
->count
, lp_servicename(snum
)));
3431 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3434 for(field_num
=0; field_num
<option_type
->count
; field_num
++)
3436 field
= option_type
->fields
[field_num
];
3438 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3440 if (!search_notify(type
, field
, &j
) )
3443 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
)
3445 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3451 current_data
= &info
->data
[info
->count
];
3453 construct_info_data(current_data
, type
, field
, id
);
3455 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3456 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3458 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3464 free_a_printer(&printer
, 2);
3468 /*******************************************************************
3470 * fill a notify_info struct with info asked
3472 ********************************************************************/
3474 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3475 SPOOL_NOTIFY_INFO
*info
,
3476 NT_PRINTER_INFO_LEVEL
*printer
,
3477 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3478 *option_type
, uint32 id
,
3479 TALLOC_CTX
*mem_ctx
)
3485 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3487 DEBUG(4,("construct_notify_jobs_info\n"));
3489 type
= option_type
->type
;
3491 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3492 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3493 option_type
->count
));
3495 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3496 field
= option_type
->fields
[field_num
];
3498 if (!search_notify(type
, field
, &j
) )
3501 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
3502 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3505 else info
->data
= tid
;
3507 current_data
=&(info
->data
[info
->count
]);
3509 construct_info_data(current_data
, type
, field
, id
);
3510 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3519 * JFM: The enumeration is not that simple, it's even non obvious.
3521 * let's take an example: I want to monitor the PRINTER SERVER for
3522 * the printer's name and the number of jobs currently queued.
3523 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3524 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3526 * I have 3 printers on the back of my server.
3528 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3531 * 1 printer 1 name 1
3532 * 2 printer 1 cjob 1
3533 * 3 printer 2 name 2
3534 * 4 printer 2 cjob 2
3535 * 5 printer 3 name 3
3536 * 6 printer 3 name 3
3538 * that's the print server case, the printer case is even worse.
3541 /*******************************************************************
3543 * enumerate all printers on the printserver
3544 * fill a notify_info struct with info asked
3546 ********************************************************************/
3548 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3549 SPOOL_NOTIFY_INFO
*info
,
3550 TALLOC_CTX
*mem_ctx
)
3553 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3554 int n_services
=lp_numservices();
3557 SPOOL_NOTIFY_OPTION
*option
;
3558 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3560 DEBUG(4,("printserver_notify_info\n"));
3565 option
=Printer
->notify
.option
;
3571 for (i
=0; i
<option
->count
; i
++) {
3572 option_type
=&(option
->ctr
.type
[i
]);
3574 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3577 for (snum
=0; snum
<n_services
; snum
++)
3579 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3580 construct_notify_printer_info ( info
, snum
, option_type
, snum
, mem_ctx
);
3586 * Debugging information, don't delete.
3589 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3590 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3591 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3593 for (i
=0; i
<info
->count
; i
++) {
3594 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3595 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3596 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3603 /*******************************************************************
3605 * fill a notify_info struct with info asked
3607 ********************************************************************/
3609 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3610 TALLOC_CTX
*mem_ctx
)
3613 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3616 SPOOL_NOTIFY_OPTION
*option
;
3617 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3619 print_queue_struct
*queue
=NULL
;
3620 print_status_struct status
;
3622 DEBUG(4,("printer_notify_info\n"));
3627 option
=Printer
->notify
.option
;
3633 get_printer_snum(p
, hnd
, &snum
);
3635 for (i
=0; i
<option
->count
; i
++) {
3636 option_type
=&option
->ctr
.type
[i
];
3638 switch ( option_type
->type
) {
3639 case PRINTER_NOTIFY_TYPE
:
3640 if(construct_notify_printer_info(info
, snum
,
3646 case JOB_NOTIFY_TYPE
: {
3647 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3649 count
= print_queue_status(snum
, &queue
, &status
);
3651 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2,
3652 lp_servicename(snum
))))
3655 for (j
=0; j
<count
; j
++) {
3656 construct_notify_jobs_info(&queue
[j
], info
,
3663 free_a_printer(&printer
, 2);
3673 * Debugging information, don't delete.
3676 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3677 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3678 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3680 for (i=0; i<info->count; i++) {
3681 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3682 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3683 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3689 /********************************************************************
3691 ********************************************************************/
3693 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3695 POLICY_HND
*handle
= &q_u
->handle
;
3696 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3698 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3699 WERROR result
= WERR_BADFID
;
3701 /* we always have a NOTIFY_INFO struct */
3705 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3706 OUR_HANDLE(handle
)));
3710 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3713 * We are now using the change value, and
3714 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3715 * I don't have a global notification system, I'm sending back all the
3716 * informations even when _NOTHING_ has changed.
3719 /* We need to keep track of the change value to send back in
3720 RRPCN replies otherwise our updates are ignored. */
3722 if (Printer
->notify
.client_connected
) {
3723 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3724 Printer
->notify
.change
= q_u
->change
;
3727 /* just ignore the SPOOL_NOTIFY_OPTION */
3729 switch (Printer
->printer_type
) {
3730 case PRINTER_HANDLE_IS_PRINTSERVER
:
3731 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3734 case PRINTER_HANDLE_IS_PRINTER
:
3735 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3743 /********************************************************************
3744 * construct_printer_info_0
3745 * fill a printer_info_0 struct
3746 ********************************************************************/
3748 static BOOL
construct_printer_info_0(PRINTER_INFO_0
*printer
, int snum
)
3752 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3753 counter_printer_0
*session_counter
;
3754 uint32 global_counter
;
3757 print_status_struct status
;
3759 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3762 count
= print_queue_length(snum
, &status
);
3764 /* check if we already have a counter for this printer */
3765 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
3767 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
3768 if (session_counter
->snum
== snum
)
3772 /* it's the first time, add it to the list */
3773 if (session_counter
==NULL
) {
3774 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
3775 free_a_printer(&ntprinter
, 2);
3778 ZERO_STRUCTP(session_counter
);
3779 session_counter
->snum
=snum
;
3780 session_counter
->counter
=0;
3781 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
3785 session_counter
->counter
++;
3788 * the global_counter should be stored in a TDB as it's common to all the clients
3789 * and should be zeroed on samba startup
3791 global_counter
=session_counter
->counter
;
3793 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3795 init_unistr(&printer
->printername
, chaine
);
3797 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_called_name());
3798 init_unistr(&printer
->servername
, chaine
);
3800 printer
->cjobs
= count
;
3801 printer
->total_jobs
= 0;
3802 printer
->total_bytes
= 0;
3804 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3805 t
=gmtime(&setuptime
);
3807 printer
->year
= t
->tm_year
+1900;
3808 printer
->month
= t
->tm_mon
+1;
3809 printer
->dayofweek
= t
->tm_wday
;
3810 printer
->day
= t
->tm_mday
;
3811 printer
->hour
= t
->tm_hour
;
3812 printer
->minute
= t
->tm_min
;
3813 printer
->second
= t
->tm_sec
;
3814 printer
->milliseconds
= 0;
3816 printer
->global_counter
= global_counter
;
3817 printer
->total_pages
= 0;
3819 printer
->major_version
= 0x0005; /* NT 5 */
3820 printer
->build_version
= 0x0893; /* build 2195 */
3822 printer
->major_version
= 0x0004; /* NT 4 */
3823 printer
->build_version
= 0x0565; /* build 1381 */
3825 printer
->unknown7
= 0x1;
3826 printer
->unknown8
= 0x0;
3827 printer
->unknown9
= 0x0;
3828 printer
->session_counter
= session_counter
->counter
;
3829 printer
->unknown11
= 0x0;
3830 printer
->printer_errors
= 0x0; /* number of print failure */
3831 printer
->unknown13
= 0x0;
3832 printer
->unknown14
= 0x1;
3833 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
3834 printer
->unknown16
= 0x0;
3835 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3836 printer
->unknown18
= 0x0;
3837 printer
->status
= nt_printq_status(status
.status
);
3838 printer
->unknown20
= 0x0;
3839 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3840 printer
->unknown22
= 0x0;
3841 printer
->unknown23
= 0x6; /* 6 ???*/
3842 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
3843 printer
->unknown25
= 0;
3844 printer
->unknown26
= 0;
3845 printer
->unknown27
= 0;
3846 printer
->unknown28
= 0;
3847 printer
->unknown29
= 0;
3849 free_a_printer(&ntprinter
,2);
3853 /********************************************************************
3854 * construct_printer_info_1
3855 * fill a printer_info_1 struct
3856 ********************************************************************/
3857 static BOOL
construct_printer_info_1(uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
3861 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3863 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3866 printer
->flags
=flags
;
3868 if (*ntprinter
->info_2
->comment
== '\0') {
3869 init_unistr(&printer
->comment
, lp_comment(snum
));
3870 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3871 ntprinter
->info_2
->drivername
, lp_comment(snum
));
3874 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3875 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3876 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
3879 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
3881 init_unistr(&printer
->description
, chaine
);
3882 init_unistr(&printer
->name
, chaine2
);
3884 free_a_printer(&ntprinter
,2);
3889 /****************************************************************************
3890 Free a DEVMODE struct.
3891 ****************************************************************************/
3893 static void free_dev_mode(DEVICEMODE
*dev
)
3898 SAFE_FREE(dev
->private);
3903 /****************************************************************************
3904 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3905 should be valid upon entry
3906 ****************************************************************************/
3908 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
3910 if ( !devmode
|| !ntdevmode
)
3913 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
3915 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
3917 devmode
->specversion
= ntdevmode
->specversion
;
3918 devmode
->driverversion
= ntdevmode
->driverversion
;
3919 devmode
->size
= ntdevmode
->size
;
3920 devmode
->driverextra
= ntdevmode
->driverextra
;
3921 devmode
->fields
= ntdevmode
->fields
;
3923 devmode
->orientation
= ntdevmode
->orientation
;
3924 devmode
->papersize
= ntdevmode
->papersize
;
3925 devmode
->paperlength
= ntdevmode
->paperlength
;
3926 devmode
->paperwidth
= ntdevmode
->paperwidth
;
3927 devmode
->scale
= ntdevmode
->scale
;
3928 devmode
->copies
= ntdevmode
->copies
;
3929 devmode
->defaultsource
= ntdevmode
->defaultsource
;
3930 devmode
->printquality
= ntdevmode
->printquality
;
3931 devmode
->color
= ntdevmode
->color
;
3932 devmode
->duplex
= ntdevmode
->duplex
;
3933 devmode
->yresolution
= ntdevmode
->yresolution
;
3934 devmode
->ttoption
= ntdevmode
->ttoption
;
3935 devmode
->collate
= ntdevmode
->collate
;
3936 devmode
->icmmethod
= ntdevmode
->icmmethod
;
3937 devmode
->icmintent
= ntdevmode
->icmintent
;
3938 devmode
->mediatype
= ntdevmode
->mediatype
;
3939 devmode
->dithertype
= ntdevmode
->dithertype
;
3941 if (ntdevmode
->private != NULL
) {
3942 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
3949 /****************************************************************************
3950 Create a DEVMODE struct. Returns malloced memory.
3951 ****************************************************************************/
3953 DEVICEMODE
*construct_dev_mode(int snum
)
3955 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3956 DEVICEMODE
*devmode
= NULL
;
3958 DEBUG(7,("construct_dev_mode\n"));
3960 DEBUGADD(8,("getting printer characteristics\n"));
3962 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3965 if ( !printer
->info_2
->devmode
) {
3966 DEBUG(5, ("BONG! There was no device mode!\n"));
3970 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
3971 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3975 ZERO_STRUCTP(devmode
);
3977 DEBUGADD(8,("loading DEVICEMODE\n"));
3979 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
3980 free_dev_mode( devmode
);
3985 free_a_printer(&printer
,2);
3990 /********************************************************************
3991 * construct_printer_info_2
3992 * fill a printer_info_2 struct
3993 ********************************************************************/
3995 static BOOL
construct_printer_info_2(PRINTER_INFO_2
*printer
, int snum
)
3998 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4000 print_status_struct status
;
4002 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4005 count
= print_queue_length(snum
, &status
);
4007 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4008 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4009 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4010 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4011 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4013 if (*ntprinter
->info_2
->comment
== '\0')
4014 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4016 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4018 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4019 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4020 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4021 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4022 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4024 printer
->attributes
= ntprinter
->info_2
->attributes
;
4026 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4027 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4028 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4029 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4030 printer
->status
= nt_printq_status(status
.status
); /* status */
4031 printer
->cjobs
= count
; /* jobs */
4032 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4034 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
4035 DEBUG(8, ("Returning NULL Devicemode!\n"));
4038 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4039 /* steal the printer info sec_desc structure. [badly done]. */
4040 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4041 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
4042 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
4043 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
4046 printer
->secdesc
= NULL
;
4049 free_a_printer(&ntprinter
, 2);
4053 /********************************************************************
4054 * construct_printer_info_3
4055 * fill a printer_info_3 struct
4056 ********************************************************************/
4058 static BOOL
construct_printer_info_3(PRINTER_INFO_3
**pp_printer
, int snum
)
4060 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4061 PRINTER_INFO_3
*printer
= NULL
;
4063 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4067 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
4068 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4072 ZERO_STRUCTP(printer
);
4074 printer
->flags
= 4; /* These are the components of the SD we are returning. */
4075 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4076 /* steal the printer info sec_desc structure. [badly done]. */
4077 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4081 * Set the flags for the components we are returning.
4084 if (printer
->secdesc
->owner_sid
)
4085 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
4087 if (printer
->secdesc
->grp_sid
)
4088 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
4090 if (printer
->secdesc
->dacl
)
4091 printer
->flags
|= DACL_SECURITY_INFORMATION
;
4093 if (printer
->secdesc
->sacl
)
4094 printer
->flags
|= SACL_SECURITY_INFORMATION
;
4097 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
4098 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
4099 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
4102 free_a_printer(&ntprinter
, 2);
4104 *pp_printer
= printer
;
4108 /********************************************************************
4109 * construct_printer_info_4
4110 * fill a printer_info_4 struct
4111 ********************************************************************/
4113 static BOOL
construct_printer_info_4(PRINTER_INFO_4
*printer
, int snum
)
4115 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4117 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4120 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4121 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4122 printer
->attributes
= ntprinter
->info_2
->attributes
;
4124 free_a_printer(&ntprinter
, 2);
4128 /********************************************************************
4129 * construct_printer_info_5
4130 * fill a printer_info_5 struct
4131 ********************************************************************/
4133 static BOOL
construct_printer_info_5(PRINTER_INFO_5
*printer
, int snum
)
4135 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4137 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
4140 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4141 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* portname */
4142 printer
->attributes
= ntprinter
->info_2
->attributes
;
4143 printer
->device_not_selected_timeout
= 0x3a98;
4144 printer
->transmission_retry_timeout
= 0xafc8;
4146 free_a_printer(&ntprinter
, 2);
4150 /********************************************************************
4151 * construct_printer_info_7
4152 * fill a printer_info_7 struct
4153 ********************************************************************/
4155 static BOOL
construct_printer_info_7(PRINTER_INFO_7
*printer
, int snum
)
4158 char *guid_str
= NULL
;
4164 const char *attrs
[] = {"objectGUID", NULL
};
4166 printer
->action
= SPOOL_DS_UNPUBLISH
;
4168 ads
= ads_init(NULL
, NULL
, lp_ads_server());
4169 ads_rc
= ads_connect(ads
);
4170 ads_rc
= ads_find_printer_on_server(ads
, &res
, lp_servicename(snum
),
4172 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
4173 prt_dn
= ads_get_dn(ads
, res
);
4174 ads_msgfree(ads
, res
);
4176 ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
4177 ads_rc
= ads_search_dn(ads
, &res
, prt_dn
, attrs
);
4178 ads_memfree(ads
, prt_dn
);
4179 ads_pull_guid(ads
, res
, &guid
);
4180 printer
->action
= SPOOL_DS_PUBLISH
;
4184 ads_msgfree(ads
, res
);
4186 asprintf(&guid_str
, "{%s}", uuid_string_static(guid
));
4188 init_unistr(&printer
->guid
, guid_str
);
4191 printer
->action
= SPOOL_DS_UNPUBLISH
;
4192 init_unistr(&printer
->guid
, "");
4198 /********************************************************************
4199 Spoolss_enumprinters.
4200 ********************************************************************/
4202 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4206 int n_services
=lp_numservices();
4207 PRINTER_INFO_1
*tp
, *printers
=NULL
;
4208 PRINTER_INFO_1 current_prt
;
4210 DEBUG(4,("enum_all_printers_info_1\n"));
4212 for (snum
=0; snum
<n_services
; snum
++) {
4213 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4214 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4216 if (construct_printer_info_1(flags
, ¤t_prt
, snum
)) {
4217 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
4218 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4219 SAFE_FREE(printers
);
4224 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4226 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4232 /* check the required size. */
4233 for (i
=0; i
<*returned
; i
++)
4234 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4236 if (!alloc_buffer_size(buffer
, *needed
))
4237 return WERR_INSUFFICIENT_BUFFER
;
4239 /* fill the buffer with the structures */
4240 for (i
=0; i
<*returned
; i
++)
4241 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4244 SAFE_FREE(printers
);
4246 if (*needed
> offered
) {
4248 return WERR_INSUFFICIENT_BUFFER
;
4254 /********************************************************************
4255 enum_all_printers_info_1_local.
4256 *********************************************************************/
4258 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4260 DEBUG(4,("enum_all_printers_info_1_local\n"));
4262 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4265 /********************************************************************
4266 enum_all_printers_info_1_name.
4267 *********************************************************************/
4269 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4273 DEBUG(4,("enum_all_printers_info_1_name\n"));
4275 if ((name
[0] == '\\') && (name
[1] == '\\'))
4278 if (is_myname_or_ipaddr(s
)) {
4279 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4282 return WERR_INVALID_NAME
;
4285 /********************************************************************
4286 enum_all_printers_info_1_remote.
4287 *********************************************************************/
4289 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4291 PRINTER_INFO_1
*printer
;
4292 fstring printername
;
4295 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4297 /* JFM: currently it's more a place holder than anything else.
4298 * In the spooler world there is a notion of server registration.
4299 * the print servers are registring (sp ?) on the PDC (in the same domain)
4301 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4304 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4309 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4310 slprintf(desc
, sizeof(desc
)-1,"%s", get_called_name());
4311 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4313 init_unistr(&printer
->description
, desc
);
4314 init_unistr(&printer
->name
, printername
);
4315 init_unistr(&printer
->comment
, comment
);
4316 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4318 /* check the required size. */
4319 *needed
+= spoolss_size_printer_info_1(printer
);
4321 if (!alloc_buffer_size(buffer
, *needed
)) {
4323 return WERR_INSUFFICIENT_BUFFER
;
4326 /* fill the buffer with the structures */
4327 smb_io_printer_info_1("", buffer
, printer
, 0);
4332 if (*needed
> offered
) {
4334 return WERR_INSUFFICIENT_BUFFER
;
4340 /********************************************************************
4341 enum_all_printers_info_1_network.
4342 *********************************************************************/
4344 static WERROR
enum_all_printers_info_1_network(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4348 DEBUG(4,("enum_all_printers_info_1_network\n"));
4350 /* If we respond to a enum_printers level 1 on our name with flags
4351 set to PRINTER_ENUM_REMOTE with a list of printers then these
4352 printers incorrectly appear in the APW browse list.
4353 Specifically the printers for the server appear at the workgroup
4354 level where all the other servers in the domain are
4355 listed. Windows responds to this call with a
4356 WERR_CAN_NOT_COMPLETE so we should do the same. */
4358 if (name
[0] == '\\' && name
[1] == '\\')
4361 if (is_myname_or_ipaddr(s
))
4362 return WERR_CAN_NOT_COMPLETE
;
4364 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4367 /********************************************************************
4368 * api_spoolss_enumprinters
4370 * called from api_spoolss_enumprinters (see this to understand)
4371 ********************************************************************/
4373 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4377 int n_services
=lp_numservices();
4378 PRINTER_INFO_2
*tp
, *printers
=NULL
;
4379 PRINTER_INFO_2 current_prt
;
4381 for (snum
=0; snum
<n_services
; snum
++) {
4382 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4383 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4385 if (construct_printer_info_2(¤t_prt
, snum
)) {
4386 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
4387 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4388 SAFE_FREE(printers
);
4393 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
4394 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4400 /* check the required size. */
4401 for (i
=0; i
<*returned
; i
++)
4402 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4404 if (!alloc_buffer_size(buffer
, *needed
)) {
4405 for (i
=0; i
<*returned
; i
++) {
4406 free_devmode(printers
[i
].devmode
);
4408 SAFE_FREE(printers
);
4409 return WERR_INSUFFICIENT_BUFFER
;
4412 /* fill the buffer with the structures */
4413 for (i
=0; i
<*returned
; i
++)
4414 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4417 for (i
=0; i
<*returned
; i
++) {
4418 free_devmode(printers
[i
].devmode
);
4420 SAFE_FREE(printers
);
4422 if (*needed
> offered
) {
4424 return WERR_INSUFFICIENT_BUFFER
;
4430 /********************************************************************
4431 * handle enumeration of printers at level 1
4432 ********************************************************************/
4434 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4435 NEW_BUFFER
*buffer
, uint32 offered
,
4436 uint32
*needed
, uint32
*returned
)
4438 /* Not all the flags are equals */
4440 if (flags
& PRINTER_ENUM_LOCAL
)
4441 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4443 if (flags
& PRINTER_ENUM_NAME
)
4444 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4446 if (flags
& PRINTER_ENUM_REMOTE
)
4447 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4449 if (flags
& PRINTER_ENUM_NETWORK
)
4450 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4452 return WERR_OK
; /* NT4sp5 does that */
4455 /********************************************************************
4456 * handle enumeration of printers at level 2
4457 ********************************************************************/
4459 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4460 NEW_BUFFER
*buffer
, uint32 offered
,
4461 uint32
*needed
, uint32
*returned
)
4463 char *s
= servername
;
4465 if (flags
& PRINTER_ENUM_LOCAL
) {
4466 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4469 if (flags
& PRINTER_ENUM_NAME
) {
4470 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4472 if (is_myname_or_ipaddr(s
))
4473 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4475 return WERR_INVALID_NAME
;
4478 if (flags
& PRINTER_ENUM_REMOTE
)
4479 return WERR_UNKNOWN_LEVEL
;
4484 /********************************************************************
4485 * handle enumeration of printers at level 5
4486 ********************************************************************/
4488 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4489 NEW_BUFFER
*buffer
, uint32 offered
,
4490 uint32
*needed
, uint32
*returned
)
4492 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4496 /********************************************************************
4497 * api_spoolss_enumprinters
4499 * called from api_spoolss_enumprinters (see this to understand)
4500 ********************************************************************/
4502 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4504 uint32 flags
= q_u
->flags
;
4505 UNISTR2
*servername
= &q_u
->servername
;
4506 uint32 level
= q_u
->level
;
4507 NEW_BUFFER
*buffer
= NULL
;
4508 uint32 offered
= q_u
->offered
;
4509 uint32
*needed
= &r_u
->needed
;
4510 uint32
*returned
= &r_u
->returned
;
4514 /* that's an [in out] buffer */
4515 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4516 buffer
= r_u
->buffer
;
4518 DEBUG(4,("_spoolss_enumprinters\n"));
4525 * flags==PRINTER_ENUM_NAME
4526 * if name=="" then enumerates all printers
4527 * if name!="" then enumerate the printer
4528 * flags==PRINTER_ENUM_REMOTE
4529 * name is NULL, enumerate printers
4530 * Level 2: name!="" enumerates printers, name can't be NULL
4531 * Level 3: doesn't exist
4532 * Level 4: does a local registry lookup
4533 * Level 5: same as Level 2
4536 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4541 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4543 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4545 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4550 return WERR_UNKNOWN_LEVEL
;
4553 /****************************************************************************
4554 ****************************************************************************/
4556 static WERROR
getprinter_level_0(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4558 PRINTER_INFO_0
*printer
=NULL
;
4560 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
4563 construct_printer_info_0(printer
, snum
);
4565 /* check the required size. */
4566 *needed
+= spoolss_size_printer_info_0(printer
);
4568 if (!alloc_buffer_size(buffer
, *needed
)) {
4570 return WERR_INSUFFICIENT_BUFFER
;
4573 /* fill the buffer with the structures */
4574 smb_io_printer_info_0("", buffer
, printer
, 0);
4579 if (*needed
> offered
) {
4580 return WERR_INSUFFICIENT_BUFFER
;
4586 /****************************************************************************
4587 ****************************************************************************/
4589 static WERROR
getprinter_level_1(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4591 PRINTER_INFO_1
*printer
=NULL
;
4593 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4596 construct_printer_info_1(PRINTER_ENUM_ICON8
, printer
, snum
);
4598 /* check the required size. */
4599 *needed
+= spoolss_size_printer_info_1(printer
);
4601 if (!alloc_buffer_size(buffer
, *needed
)) {
4603 return WERR_INSUFFICIENT_BUFFER
;
4606 /* fill the buffer with the structures */
4607 smb_io_printer_info_1("", buffer
, printer
, 0);
4612 if (*needed
> offered
) {
4613 return WERR_INSUFFICIENT_BUFFER
;
4619 /****************************************************************************
4620 ****************************************************************************/
4622 static WERROR
getprinter_level_2(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4624 PRINTER_INFO_2
*printer
=NULL
;
4626 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
4629 construct_printer_info_2(printer
, snum
);
4631 /* check the required size. */
4632 *needed
+= spoolss_size_printer_info_2(printer
);
4634 if (!alloc_buffer_size(buffer
, *needed
)) {
4635 free_printer_info_2(printer
);
4636 return WERR_INSUFFICIENT_BUFFER
;
4639 /* fill the buffer with the structures */
4640 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
4641 free_printer_info_2(printer
);
4646 free_printer_info_2(printer
);
4648 if (*needed
> offered
) {
4649 return WERR_INSUFFICIENT_BUFFER
;
4655 /****************************************************************************
4656 ****************************************************************************/
4658 static WERROR
getprinter_level_3(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4660 PRINTER_INFO_3
*printer
=NULL
;
4662 if (!construct_printer_info_3(&printer
, snum
))
4665 /* check the required size. */
4666 *needed
+= spoolss_size_printer_info_3(printer
);
4668 if (!alloc_buffer_size(buffer
, *needed
)) {
4669 free_printer_info_3(printer
);
4670 return WERR_INSUFFICIENT_BUFFER
;
4673 /* fill the buffer with the structures */
4674 smb_io_printer_info_3("", buffer
, printer
, 0);
4677 free_printer_info_3(printer
);
4679 if (*needed
> offered
) {
4680 return WERR_INSUFFICIENT_BUFFER
;
4686 /****************************************************************************
4687 ****************************************************************************/
4689 static WERROR
getprinter_level_4(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4691 PRINTER_INFO_4
*printer
=NULL
;
4693 if((printer
=(PRINTER_INFO_4
*)malloc(sizeof(PRINTER_INFO_4
)))==NULL
)
4696 if (!construct_printer_info_4(printer
, snum
))
4699 /* check the required size. */
4700 *needed
+= spoolss_size_printer_info_4(printer
);
4702 if (!alloc_buffer_size(buffer
, *needed
)) {
4703 free_printer_info_4(printer
);
4704 return WERR_INSUFFICIENT_BUFFER
;
4707 /* fill the buffer with the structures */
4708 smb_io_printer_info_4("", buffer
, printer
, 0);
4711 free_printer_info_4(printer
);
4713 if (*needed
> offered
) {
4714 return WERR_INSUFFICIENT_BUFFER
;
4720 /****************************************************************************
4721 ****************************************************************************/
4723 static WERROR
getprinter_level_5(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4725 PRINTER_INFO_5
*printer
=NULL
;
4727 if((printer
=(PRINTER_INFO_5
*)malloc(sizeof(PRINTER_INFO_5
)))==NULL
)
4730 if (!construct_printer_info_5(printer
, snum
))
4733 /* check the required size. */
4734 *needed
+= spoolss_size_printer_info_5(printer
);
4736 if (!alloc_buffer_size(buffer
, *needed
)) {
4737 free_printer_info_5(printer
);
4738 return WERR_INSUFFICIENT_BUFFER
;
4741 /* fill the buffer with the structures */
4742 smb_io_printer_info_5("", buffer
, printer
, 0);
4745 free_printer_info_5(printer
);
4747 if (*needed
> offered
) {
4748 return WERR_INSUFFICIENT_BUFFER
;
4754 static WERROR
getprinter_level_7(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4756 PRINTER_INFO_7
*printer
=NULL
;
4758 if((printer
=(PRINTER_INFO_7
*)malloc(sizeof(PRINTER_INFO_7
)))==NULL
)
4761 if (!construct_printer_info_7(printer
, snum
))
4764 /* check the required size. */
4765 *needed
+= spoolss_size_printer_info_7(printer
);
4767 if (!alloc_buffer_size(buffer
, *needed
)) {
4768 free_printer_info_7(printer
);
4769 return WERR_INSUFFICIENT_BUFFER
;
4772 /* fill the buffer with the structures */
4773 smb_io_printer_info_7("", buffer
, printer
, 0);
4776 free_printer_info_7(printer
);
4778 if (*needed
> offered
) {
4779 return WERR_INSUFFICIENT_BUFFER
;
4785 /****************************************************************************
4786 ****************************************************************************/
4788 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
4790 POLICY_HND
*handle
= &q_u
->handle
;
4791 uint32 level
= q_u
->level
;
4792 NEW_BUFFER
*buffer
= NULL
;
4793 uint32 offered
= q_u
->offered
;
4794 uint32
*needed
= &r_u
->needed
;
4798 /* that's an [in out] buffer */
4799 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4800 buffer
= r_u
->buffer
;
4804 if (!get_printer_snum(p
, handle
, &snum
))
4809 return getprinter_level_0(snum
, buffer
, offered
, needed
);
4811 return getprinter_level_1(snum
, buffer
, offered
, needed
);
4813 return getprinter_level_2(snum
, buffer
, offered
, needed
);
4815 return getprinter_level_3(snum
, buffer
, offered
, needed
);
4817 return getprinter_level_4(snum
, buffer
, offered
, needed
);
4819 return getprinter_level_5(snum
, buffer
, offered
, needed
);
4821 return getprinter_level_7(snum
, buffer
, offered
, needed
);
4823 return WERR_UNKNOWN_LEVEL
;
4826 /********************************************************************
4827 * fill a DRIVER_INFO_1 struct
4828 ********************************************************************/
4830 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
4832 init_unistr( &info
->name
, driver
.info_3
->name
);
4835 /********************************************************************
4836 * construct_printer_driver_info_1
4837 ********************************************************************/
4839 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4841 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4842 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4844 ZERO_STRUCT(driver
);
4846 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4847 return WERR_INVALID_PRINTER_NAME
;
4849 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4850 return WERR_UNKNOWN_PRINTER_DRIVER
;
4852 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
4854 free_a_printer(&printer
,2);
4859 /********************************************************************
4860 * construct_printer_driver_info_2
4861 * fill a printer_info_2 struct
4862 ********************************************************************/
4864 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4868 info
->version
=driver
.info_3
->cversion
;
4870 init_unistr( &info
->name
, driver
.info_3
->name
);
4871 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4874 if (strlen(driver
.info_3
->driverpath
)) {
4875 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4876 init_unistr( &info
->driverpath
, temp
);
4878 init_unistr( &info
->driverpath
, "" );
4880 if (strlen(driver
.info_3
->datafile
)) {
4881 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4882 init_unistr( &info
->datafile
, temp
);
4884 init_unistr( &info
->datafile
, "" );
4886 if (strlen(driver
.info_3
->configfile
)) {
4887 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4888 init_unistr( &info
->configfile
, temp
);
4890 init_unistr( &info
->configfile
, "" );
4893 /********************************************************************
4894 * construct_printer_driver_info_2
4895 * fill a printer_info_2 struct
4896 ********************************************************************/
4898 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4900 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4901 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4903 ZERO_STRUCT(printer
);
4904 ZERO_STRUCT(driver
);
4906 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4907 return WERR_INVALID_PRINTER_NAME
;
4909 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4910 return WERR_UNKNOWN_PRINTER_DRIVER
;
4912 fill_printer_driver_info_2(info
, driver
, servername
);
4914 free_a_printer(&printer
,2);
4919 /********************************************************************
4920 * copy a strings array and convert to UNICODE
4922 * convert an array of ascii string to a UNICODE string
4923 ********************************************************************/
4925 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, char *servername
)
4933 DEBUG(6,("init_unistr_array\n"));
4944 v
= ""; /* hack to handle null lists */
4947 /* hack to allow this to be used in places other than when generating
4948 the list of dependent files */
4951 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
4955 DEBUGADD(6,("%d:%s:%d\n", i
, line
, strlen(line
)));
4957 if ( (tuary
=Realloc(*uni_array
, (j
+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
4958 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4966 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
4971 (*uni_array
)[j
]=0x0000;
4974 DEBUGADD(6,("last one:done\n"));
4976 /* return size of array in uint16's */
4981 /********************************************************************
4982 * construct_printer_info_3
4983 * fill a printer_info_3 struct
4984 ********************************************************************/
4986 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4992 info
->version
=driver
.info_3
->cversion
;
4994 init_unistr( &info
->name
, driver
.info_3
->name
);
4995 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4997 if (strlen(driver
.info_3
->driverpath
)) {
4998 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4999 init_unistr( &info
->driverpath
, temp
);
5001 init_unistr( &info
->driverpath
, "" );
5003 if (strlen(driver
.info_3
->datafile
)) {
5004 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5005 init_unistr( &info
->datafile
, temp
);
5007 init_unistr( &info
->datafile
, "" );
5009 if (strlen(driver
.info_3
->configfile
)) {
5010 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5011 init_unistr( &info
->configfile
, temp
);
5013 init_unistr( &info
->configfile
, "" );
5015 if (strlen(driver
.info_3
->helpfile
)) {
5016 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5017 init_unistr( &info
->helpfile
, temp
);
5019 init_unistr( &info
->helpfile
, "" );
5021 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5022 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5024 info
->dependentfiles
=NULL
;
5025 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5028 /********************************************************************
5029 * construct_printer_info_3
5030 * fill a printer_info_3 struct
5031 ********************************************************************/
5033 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5035 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5036 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5038 ZERO_STRUCT(driver
);
5040 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
5041 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5042 if (!W_ERROR_IS_OK(status
))
5043 return WERR_INVALID_PRINTER_NAME
;
5045 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5046 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5051 * I put this code in during testing. Helpful when commenting out the
5052 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5053 * as win2k always queries the driver using an infor level of 6.
5054 * I've left it in (but ifdef'd out) because I'll probably
5055 * use it in experimentation again in the future. --jerry 22/01/2002
5058 if (!W_ERROR_IS_OK(status
)) {
5060 * Is this a W2k client ?
5063 /* Yes - try again with a WinNT driver. */
5065 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5066 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5070 if (!W_ERROR_IS_OK(status
)) {
5071 free_a_printer(&printer
,2);
5072 return WERR_UNKNOWN_PRINTER_DRIVER
;
5080 fill_printer_driver_info_3(info
, driver
, servername
);
5082 free_a_printer(&printer
,2);
5087 /********************************************************************
5088 * construct_printer_info_6
5089 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5090 ********************************************************************/
5092 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5098 memset(&nullstr
, '\0', sizeof(fstring
));
5100 info
->version
=driver
.info_3
->cversion
;
5102 init_unistr( &info
->name
, driver
.info_3
->name
);
5103 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5105 if (strlen(driver
.info_3
->driverpath
)) {
5106 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5107 init_unistr( &info
->driverpath
, temp
);
5109 init_unistr( &info
->driverpath
, "" );
5111 if (strlen(driver
.info_3
->datafile
)) {
5112 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5113 init_unistr( &info
->datafile
, temp
);
5115 init_unistr( &info
->datafile
, "" );
5117 if (strlen(driver
.info_3
->configfile
)) {
5118 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5119 init_unistr( &info
->configfile
, temp
);
5121 init_unistr( &info
->configfile
, "" );
5123 if (strlen(driver
.info_3
->helpfile
)) {
5124 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5125 init_unistr( &info
->helpfile
, temp
);
5127 init_unistr( &info
->helpfile
, "" );
5129 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5130 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5132 info
->dependentfiles
= NULL
;
5133 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5135 info
->previousdrivernames
=NULL
;
5136 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5138 info
->driver_date
.low
=0;
5139 info
->driver_date
.high
=0;
5142 info
->driver_version_low
=0;
5143 info
->driver_version_high
=0;
5145 init_unistr( &info
->mfgname
, "");
5146 init_unistr( &info
->oem_url
, "");
5147 init_unistr( &info
->hardware_id
, "");
5148 init_unistr( &info
->provider
, "");
5151 /********************************************************************
5152 * construct_printer_info_6
5153 * fill a printer_info_6 struct
5154 ********************************************************************/
5156 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5157 fstring servername
, fstring architecture
, uint32 version
)
5159 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5160 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5163 ZERO_STRUCT(driver
);
5165 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
5167 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5169 if (!W_ERROR_IS_OK(status
))
5170 return WERR_INVALID_PRINTER_NAME
;
5172 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5174 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5176 if (!W_ERROR_IS_OK(status
))
5179 * Is this a W2k client ?
5183 free_a_printer(&printer
,2);
5184 return WERR_UNKNOWN_PRINTER_DRIVER
;
5187 /* Yes - try again with a WinNT driver. */
5189 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5190 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5191 if (!W_ERROR_IS_OK(status
)) {
5192 free_a_printer(&printer
,2);
5193 return WERR_UNKNOWN_PRINTER_DRIVER
;
5197 fill_printer_driver_info_6(info
, driver
, servername
);
5199 free_a_printer(&printer
,2);
5204 /****************************************************************************
5205 ****************************************************************************/
5207 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5209 SAFE_FREE(info
->dependentfiles
);
5212 /****************************************************************************
5213 ****************************************************************************/
5215 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5217 SAFE_FREE(info
->dependentfiles
);
5221 /****************************************************************************
5222 ****************************************************************************/
5224 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5226 DRIVER_INFO_1
*info
=NULL
;
5229 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
5232 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5233 if (!W_ERROR_IS_OK(status
)) {
5238 /* check the required size. */
5239 *needed
+= spoolss_size_printer_driver_info_1(info
);
5241 if (!alloc_buffer_size(buffer
, *needed
)) {
5243 return WERR_INSUFFICIENT_BUFFER
;
5246 /* fill the buffer with the structures */
5247 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5252 if (*needed
> offered
)
5253 return WERR_INSUFFICIENT_BUFFER
;
5258 /****************************************************************************
5259 ****************************************************************************/
5261 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5263 DRIVER_INFO_2
*info
=NULL
;
5266 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
5269 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5270 if (!W_ERROR_IS_OK(status
)) {
5275 /* check the required size. */
5276 *needed
+= spoolss_size_printer_driver_info_2(info
);
5278 if (!alloc_buffer_size(buffer
, *needed
)) {
5280 return WERR_INSUFFICIENT_BUFFER
;
5283 /* fill the buffer with the structures */
5284 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5289 if (*needed
> offered
)
5290 return WERR_INSUFFICIENT_BUFFER
;
5295 /****************************************************************************
5296 ****************************************************************************/
5298 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5305 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5306 if (!W_ERROR_IS_OK(status
)) {
5310 /* check the required size. */
5311 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5313 if (!alloc_buffer_size(buffer
, *needed
)) {
5314 free_printer_driver_info_3(&info
);
5315 return WERR_INSUFFICIENT_BUFFER
;
5318 /* fill the buffer with the structures */
5319 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5321 free_printer_driver_info_3(&info
);
5323 if (*needed
> offered
)
5324 return WERR_INSUFFICIENT_BUFFER
;
5329 /****************************************************************************
5330 ****************************************************************************/
5332 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5339 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5340 if (!W_ERROR_IS_OK(status
)) {
5344 /* check the required size. */
5345 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5347 if (!alloc_buffer_size(buffer
, *needed
)) {
5348 free_printer_driver_info_6(&info
);
5349 return WERR_INSUFFICIENT_BUFFER
;
5352 /* fill the buffer with the structures */
5353 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5355 free_printer_driver_info_6(&info
);
5357 if (*needed
> offered
)
5358 return WERR_INSUFFICIENT_BUFFER
;
5363 /****************************************************************************
5364 ****************************************************************************/
5366 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5368 POLICY_HND
*handle
= &q_u
->handle
;
5369 UNISTR2
*uni_arch
= &q_u
->architecture
;
5370 uint32 level
= q_u
->level
;
5371 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5372 NEW_BUFFER
*buffer
= NULL
;
5373 uint32 offered
= q_u
->offered
;
5374 uint32
*needed
= &r_u
->needed
;
5375 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5376 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5379 fstring architecture
;
5382 /* that's an [in out] buffer */
5383 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5384 buffer
= r_u
->buffer
;
5386 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5389 *servermajorversion
= 0;
5390 *serverminorversion
= 0;
5392 pstrcpy(servername
, get_called_name());
5393 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5395 if (!get_printer_snum(p
, handle
, &snum
))
5400 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5402 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5404 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5406 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5409 return WERR_UNKNOWN_LEVEL
;
5412 /****************************************************************************
5413 ****************************************************************************/
5415 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5417 POLICY_HND
*handle
= &q_u
->handle
;
5419 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5422 DEBUG(3,("Error in startpageprinter printer handle\n"));
5426 Printer
->page_started
=True
;
5430 /****************************************************************************
5431 ****************************************************************************/
5433 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5435 POLICY_HND
*handle
= &q_u
->handle
;
5438 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5441 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5445 if (!get_printer_snum(p
, handle
, &snum
))
5448 Printer
->page_started
=False
;
5449 print_job_endpage(snum
, Printer
->jobid
);
5454 /********************************************************************
5455 * api_spoolss_getprinter
5456 * called from the spoolss dispatcher
5458 ********************************************************************/
5460 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5462 POLICY_HND
*handle
= &q_u
->handle
;
5463 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5464 uint32
*jobid
= &r_u
->jobid
;
5466 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5470 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5471 struct current_user user
;
5474 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5478 get_current_user(&user
, p
);
5481 * a nice thing with NT is it doesn't listen to what you tell it.
5482 * when asked to send _only_ RAW datas, it tries to send datas
5485 * So I add checks like in NT Server ...
5488 if (info_1
->p_datatype
!= 0) {
5489 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5490 if (strcmp(datatype
, "RAW") != 0) {
5492 return WERR_INVALID_DATATYPE
;
5496 /* get the share number of the printer */
5497 if (!get_printer_snum(p
, handle
, &snum
)) {
5501 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5503 Printer
->jobid
= print_job_start(&user
, snum
, jobname
, Printer
->nt_devmode
);
5505 /* An error occured in print_job_start() so return an appropriate
5508 if (Printer
->jobid
== -1) {
5509 return map_werror_from_unix(errno
);
5512 Printer
->document_started
=True
;
5513 (*jobid
) = Printer
->jobid
;
5518 /********************************************************************
5519 * api_spoolss_getprinter
5520 * called from the spoolss dispatcher
5522 ********************************************************************/
5524 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5526 POLICY_HND
*handle
= &q_u
->handle
;
5528 return _spoolss_enddocprinter_internal(p
, handle
);
5531 /****************************************************************************
5532 ****************************************************************************/
5534 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5536 POLICY_HND
*handle
= &q_u
->handle
;
5537 uint32 buffer_size
= q_u
->buffer_size
;
5538 uint8
*buffer
= q_u
->buffer
;
5539 uint32
*buffer_written
= &q_u
->buffer_size2
;
5541 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5544 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5545 r_u
->buffer_written
= q_u
->buffer_size2
;
5549 if (!get_printer_snum(p
, handle
, &snum
))
5552 (*buffer_written
) = print_job_write(snum
, Printer
->jobid
, (char *)buffer
, buffer_size
);
5553 if (*buffer_written
== -1) {
5554 r_u
->buffer_written
= 0;
5555 if (errno
== ENOSPC
)
5556 return WERR_NO_SPOOL_SPACE
;
5558 return WERR_ACCESS_DENIED
;
5561 r_u
->buffer_written
= q_u
->buffer_size2
;
5566 /********************************************************************
5567 * api_spoolss_getprinter
5568 * called from the spoolss dispatcher
5570 ********************************************************************/
5572 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5575 struct current_user user
;
5577 WERROR errcode
= WERR_BADFUNC
;
5578 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5580 get_current_user(&user
, p
);
5583 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5587 if (!get_printer_snum(p
, handle
, &snum
))
5591 case PRINTER_CONTROL_PAUSE
:
5592 if (print_queue_pause(&user
, snum
, &errcode
)) {
5596 case PRINTER_CONTROL_RESUME
:
5597 case PRINTER_CONTROL_UNPAUSE
:
5598 if (print_queue_resume(&user
, snum
, &errcode
)) {
5602 case PRINTER_CONTROL_PURGE
:
5603 if (print_queue_purge(&user
, snum
, &errcode
)) {
5608 return WERR_UNKNOWN_LEVEL
;
5614 /********************************************************************
5615 * api_spoolss_abortprinter
5616 * From MSDN: "Deletes printer's spool file if printer is configured
5618 ********************************************************************/
5620 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5622 POLICY_HND
*handle
= &q_u
->handle
;
5623 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5625 struct current_user user
;
5626 WERROR errcode
= WERR_OK
;
5629 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5633 if (!get_printer_snum(p
, handle
, &snum
))
5636 get_current_user( &user
, p
);
5638 print_job_delete( &user
, snum
, Printer
->jobid
, &errcode
);
5643 /********************************************************************
5644 * called by spoolss_api_setprinter
5645 * when updating a printer description
5646 ********************************************************************/
5648 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5649 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5650 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5652 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5653 struct current_user user
;
5657 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5659 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5660 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5661 OUR_HANDLE(handle
)));
5663 result
= WERR_BADFID
;
5667 /* NT seems to like setting the security descriptor even though
5668 nothing may have actually changed. This causes annoying
5669 dialog boxes when the user doesn't have permission to change
5670 the security descriptor. */
5672 nt_printing_getsec(p
->mem_ctx
, Printer
->dev
.handlename
, &old_secdesc_ctr
);
5674 if (DEBUGLEVEL
>= 10) {
5678 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5679 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5680 PRINTERNAME(snum
), the_acl
->num_aces
));
5682 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5685 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5687 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5688 the_acl
->ace
[i
].info
.mask
));
5691 the_acl
= secdesc_ctr
->sec
->dacl
;
5694 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5695 PRINTERNAME(snum
), the_acl
->num_aces
));
5697 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5700 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5702 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5703 the_acl
->ace
[i
].info
.mask
));
5706 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5710 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5712 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5717 /* Work out which user is performing the operation */
5719 get_current_user(&user
, p
);
5721 /* Check the user has permissions to change the security
5722 descriptor. By experimentation with two NT machines, the user
5723 requires Full Access to the printer to change security
5726 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5727 result
= WERR_ACCESS_DENIED
;
5731 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
5738 /********************************************************************
5739 Do Samba sanity checks on a printer info struct.
5740 this has changed purpose: it now "canonicalises" printer
5741 info from a client rather than just checking it is correct
5742 ********************************************************************/
5744 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5746 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5747 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5749 /* we force some elements to "correct" values */
5750 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", get_called_name());
5751 fstrcpy(info
->sharename
, lp_servicename(snum
));
5752 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5753 get_called_name(), info
->sharename
);
5754 info
->attributes
= PRINTER_ATTRIBUTE_SHARED
| PRINTER_ATTRIBUTE_NETWORK
;
5759 /****************************************************************************
5760 ****************************************************************************/
5762 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
5764 extern userdom_struct current_user_info
;
5765 char *cmd
= lp_addprinter_cmd();
5771 fstring remote_machine
= "%m";
5773 standard_sub_basic(current_user_info
.smb_name
, remote_machine
,sizeof(remote_machine
));
5775 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5776 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5777 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5778 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
5780 DEBUG(10,("Running [%s]\n", command
));
5781 ret
= smbrun(command
, &fd
);
5782 DEBUGADD(10,("returned [%d]\n", ret
));
5791 /* Get lines and convert them back to dos-codepage */
5792 qlines
= fd_lines_load(fd
, &numlines
);
5793 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5797 /* Set the portname to what the script says the portname should be. */
5798 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5799 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5801 /* Send SIGHUP to process group... is there a better way? */
5804 /* reload our services immediately */
5805 reload_services( False
);
5808 file_lines_free(qlines
);
5812 /********************************************************************
5813 * Called by spoolss_api_setprinter
5814 * when updating a printer description.
5815 ********************************************************************/
5817 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
5818 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5819 DEVICEMODE
*devmode
)
5822 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
5823 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5826 DEBUG(8,("update_printer\n"));
5831 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5832 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5833 result
= WERR_UNKNOWN_LEVEL
;
5838 result
= WERR_BADFID
;
5842 if (!get_printer_snum(p
, handle
, &snum
)) {
5843 result
= WERR_BADFID
;
5847 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))) ||
5848 (!W_ERROR_IS_OK(get_a_printer(&old_printer
, 2, lp_servicename(snum
))))) {
5849 result
= WERR_BADFID
;
5853 DEBUGADD(8,("Converting info_2 struct\n"));
5856 * convert_printer_info converts the incoming
5857 * info from the client and overwrites the info
5858 * just read from the tdb in the pointer 'printer'.
5861 if (!convert_printer_info(info
, printer
, level
)) {
5862 result
= WERR_NOMEM
;
5867 /* we have a valid devmode
5868 convert it and link it*/
5870 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5871 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5872 &printer
->info_2
->devmode
)) {
5873 result
= WERR_NOMEM
;
5878 * make sure we actually reload the services after
5879 * this as smb.conf could have a new section in it
5880 * .... shouldn't .... but could
5882 reload_services(False
);
5885 /* Do sanity check on the requested changes for Samba */
5887 if (!check_printer_ok(printer
->info_2
, snum
)) {
5888 result
= WERR_INVALID_PARAM
;
5892 /* Check calling user has permission to update printer description */
5894 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5895 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5896 result
= WERR_ACCESS_DENIED
;
5900 /* Call addprinter hook */
5901 /* Check changes to see if this is really needed */
5903 if ( *lp_addprinter_cmd()
5904 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
5905 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
5906 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
5907 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
5909 if ( !add_printer_hook(printer
) ) {
5910 result
= WERR_ACCESS_DENIED
;
5916 * When a *new* driver is bound to a printer, the drivername is used to
5917 * lookup previously saved driver initialization info, which is then
5918 * bound to the printer, simulating what happens in the Windows arch.
5920 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
5922 if (!set_driver_init(printer
, 2))
5924 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5925 printer
->info_2
->drivername
));
5928 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5929 printer
->info_2
->drivername
));
5931 notify_printer_driver(snum
, printer
->info_2
->drivername
);
5934 /* Update printer info */
5935 result
= mod_a_printer(*printer
, 2);
5937 /* flag which changes actually occured. This is a small subset of
5938 all the possible changes */
5940 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
))
5941 notify_printer_comment(snum
, printer
->info_2
->comment
);
5943 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
))
5944 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
5946 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
))
5947 notify_printer_port(snum
, printer
->info_2
->portname
);
5949 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
))
5950 notify_printer_location(snum
, printer
->info_2
->location
);
5953 free_a_printer(&printer
, 2);
5954 free_a_printer(&old_printer
, 2);
5960 /****************************************************************************
5961 ****************************************************************************/
5962 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
5963 const SPOOL_PRINTER_INFO_LEVEL
*info
)
5966 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
5968 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5971 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
5978 if (!get_printer_snum(p
, handle
, &snum
))
5981 nt_printer_publish(snum
, info7
->action
);
5985 return WERR_UNKNOWN_LEVEL
;
5988 /****************************************************************************
5989 ****************************************************************************/
5991 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
5993 POLICY_HND
*handle
= &q_u
->handle
;
5994 uint32 level
= q_u
->level
;
5995 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
5996 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
5997 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
5998 uint32 command
= q_u
->command
;
6000 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6003 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6007 /* check the level */
6010 return control_printer(handle
, command
, p
);
6012 return update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6014 return update_printer_sec(handle
, level
, info
, p
,
6017 return publish_or_unpublish_printer(p
, handle
, info
);
6019 return WERR_UNKNOWN_LEVEL
;
6023 /****************************************************************************
6024 ****************************************************************************/
6026 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6028 POLICY_HND
*handle
= &q_u
->handle
;
6029 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6032 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6036 if (Printer
->notify
.client_connected
==True
) {
6039 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
6041 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
6042 !get_printer_snum(p
, handle
, &snum
) )
6045 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6048 Printer
->notify
.flags
=0;
6049 Printer
->notify
.options
=0;
6050 Printer
->notify
.localmachine
[0]='\0';
6051 Printer
->notify
.printerlocal
=0;
6052 if (Printer
->notify
.option
)
6053 free_spool_notify_option(&Printer
->notify
.option
);
6054 Printer
->notify
.client_connected
=False
;
6059 /****************************************************************************
6060 ****************************************************************************/
6062 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6064 /* that's an [in out] buffer (despite appearences to the contrary) */
6065 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6068 return WERR_INVALID_PARAM
; /* this is what a NT server
6069 returns for AddJob. AddJob
6070 must fail on non-local
6074 /****************************************************************************
6075 ****************************************************************************/
6077 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
6078 int position
, int snum
)
6084 t
=gmtime(&queue
->time
);
6085 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
6087 job_info
->jobid
=queue
->job
;
6088 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6089 init_unistr(&job_info
->machinename
, temp_name
);
6090 init_unistr(&job_info
->username
, queue
->fs_user
);
6091 init_unistr(&job_info
->document
, queue
->fs_file
);
6092 init_unistr(&job_info
->datatype
, "RAW");
6093 init_unistr(&job_info
->text_status
, "");
6094 job_info
->status
=nt_printj_status(queue
->status
);
6095 job_info
->priority
=queue
->priority
;
6096 job_info
->position
=position
;
6097 job_info
->totalpages
=queue
->page_count
;
6098 job_info
->pagesprinted
=0;
6100 make_systemtime(&job_info
->submitted
, t
);
6103 /****************************************************************************
6104 ****************************************************************************/
6106 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
6107 int position
, int snum
,
6108 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6109 DEVICEMODE
*devmode
)
6115 t
=gmtime(&queue
->time
);
6116 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
6118 job_info
->jobid
=queue
->job
;
6120 slprintf(chaine
, sizeof(chaine
)-1, "\\\\%s\\%s", get_called_name(), ntprinter
->info_2
->printername
);
6122 init_unistr(&job_info
->printername
, chaine
);
6124 init_unistr(&job_info
->machinename
, temp_name
);
6125 init_unistr(&job_info
->username
, queue
->fs_user
);
6126 init_unistr(&job_info
->document
, queue
->fs_file
);
6127 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6128 init_unistr(&job_info
->datatype
, "RAW");
6129 init_unistr(&job_info
->printprocessor
, "winprint");
6130 init_unistr(&job_info
->parameters
, "");
6131 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6132 init_unistr(&job_info
->text_status
, "");
6134 /* and here the security descriptor */
6136 job_info
->status
=nt_printj_status(queue
->status
);
6137 job_info
->priority
=queue
->priority
;
6138 job_info
->position
=position
;
6139 job_info
->starttime
=0;
6140 job_info
->untiltime
=0;
6141 job_info
->totalpages
=queue
->page_count
;
6142 job_info
->size
=queue
->size
;
6143 make_systemtime(&(job_info
->submitted
), t
);
6144 job_info
->timeelapsed
=0;
6145 job_info
->pagesprinted
=0;
6147 job_info
->devmode
= devmode
;
6152 /****************************************************************************
6153 Enumjobs at level 1.
6154 ****************************************************************************/
6156 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
6157 NEW_BUFFER
*buffer
, uint32 offered
,
6158 uint32
*needed
, uint32
*returned
)
6163 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
6170 for (i
=0; i
<*returned
; i
++)
6171 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
6175 /* check the required size. */
6176 for (i
=0; i
<*returned
; i
++)
6177 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6179 if (!alloc_buffer_size(buffer
, *needed
)) {
6181 return WERR_INSUFFICIENT_BUFFER
;
6184 /* fill the buffer with the structures */
6185 for (i
=0; i
<*returned
; i
++)
6186 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6191 if (*needed
> offered
) {
6193 return WERR_INSUFFICIENT_BUFFER
;
6199 /****************************************************************************
6200 Enumjobs at level 2.
6201 ****************************************************************************/
6203 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
6204 NEW_BUFFER
*buffer
, uint32 offered
,
6205 uint32
*needed
, uint32
*returned
)
6207 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6208 JOB_INFO_2
*info
= NULL
;
6211 DEVICEMODE
*devmode
= NULL
;
6213 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
6216 result
= WERR_NOMEM
;
6220 result
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
6221 if (!W_ERROR_IS_OK(result
)) {
6226 /* this should not be a failure condition if the devmode is NULL */
6228 devmode
= construct_dev_mode(snum
);
6230 for (i
=0; i
<*returned
; i
++)
6231 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
,
6234 free_a_printer(&ntprinter
, 2);
6237 /* check the required size. */
6238 for (i
=0; i
<*returned
; i
++)
6239 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6241 if (*needed
> offered
) {
6243 result
= WERR_INSUFFICIENT_BUFFER
;
6247 if (!alloc_buffer_size(buffer
, *needed
)) {
6249 result
= WERR_INSUFFICIENT_BUFFER
;
6253 /* fill the buffer with the structures */
6254 for (i
=0; i
<*returned
; i
++)
6255 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6260 free_a_printer(&ntprinter
, 2);
6261 free_devmode(devmode
);
6269 /****************************************************************************
6271 ****************************************************************************/
6273 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6275 POLICY_HND
*handle
= &q_u
->handle
;
6276 uint32 level
= q_u
->level
;
6277 NEW_BUFFER
*buffer
= NULL
;
6278 uint32 offered
= q_u
->offered
;
6279 uint32
*needed
= &r_u
->needed
;
6280 uint32
*returned
= &r_u
->returned
;
6283 print_status_struct prt_status
;
6284 print_queue_struct
*queue
=NULL
;
6286 /* that's an [in out] buffer */
6287 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6288 buffer
= r_u
->buffer
;
6290 DEBUG(4,("_spoolss_enumjobs\n"));
6295 if (!get_printer_snum(p
, handle
, &snum
))
6298 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6299 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6301 if (*returned
== 0) {
6308 return enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
6310 return enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
6314 return WERR_UNKNOWN_LEVEL
;
6318 /****************************************************************************
6319 ****************************************************************************/
6321 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6326 /****************************************************************************
6327 ****************************************************************************/
6329 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6331 POLICY_HND
*handle
= &q_u
->handle
;
6332 uint32 jobid
= q_u
->jobid
;
6333 uint32 command
= q_u
->command
;
6335 struct current_user user
;
6337 WERROR errcode
= WERR_BADFUNC
;
6339 if (!get_printer_snum(p
, handle
, &snum
)) {
6343 if (!print_job_exists(snum
, jobid
)) {
6344 return WERR_INVALID_PRINTER_NAME
;
6347 get_current_user(&user
, p
);
6350 case JOB_CONTROL_CANCEL
:
6351 case JOB_CONTROL_DELETE
:
6352 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
6356 case JOB_CONTROL_PAUSE
:
6357 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
6361 case JOB_CONTROL_RESTART
:
6362 case JOB_CONTROL_RESUME
:
6363 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
6368 return WERR_UNKNOWN_LEVEL
;
6374 /****************************************************************************
6375 Enumerates all printer drivers at level 1.
6376 ****************************************************************************/
6378 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6383 fstring
*list
= NULL
;
6385 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6386 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
6390 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6392 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6393 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6399 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
6400 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6401 SAFE_FREE(driver_info_1
);
6405 else driver_info_1
= tdi1
;
6408 for (i
=0; i
<ndrivers
; i
++) {
6410 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6411 ZERO_STRUCT(driver
);
6412 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6413 architecture
, version
);
6414 if (!W_ERROR_IS_OK(status
)) {
6418 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6419 free_a_printer_driver(driver
, 3);
6422 *returned
+=ndrivers
;
6426 /* check the required size. */
6427 for (i
=0; i
<*returned
; i
++) {
6428 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6429 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6432 if (!alloc_buffer_size(buffer
, *needed
)) {
6433 SAFE_FREE(driver_info_1
);
6434 return WERR_INSUFFICIENT_BUFFER
;
6437 /* fill the buffer with the driver structures */
6438 for (i
=0; i
<*returned
; i
++) {
6439 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6440 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6443 SAFE_FREE(driver_info_1
);
6445 if (*needed
> offered
) {
6447 return WERR_INSUFFICIENT_BUFFER
;
6453 /****************************************************************************
6454 Enumerates all printer drivers at level 2.
6455 ****************************************************************************/
6457 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6462 fstring
*list
= NULL
;
6464 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6465 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
6469 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6471 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6472 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6478 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
6479 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6480 SAFE_FREE(driver_info_2
);
6484 else driver_info_2
= tdi2
;
6487 for (i
=0; i
<ndrivers
; i
++) {
6490 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6491 ZERO_STRUCT(driver
);
6492 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6493 architecture
, version
);
6494 if (!W_ERROR_IS_OK(status
)) {
6498 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6499 free_a_printer_driver(driver
, 3);
6502 *returned
+=ndrivers
;
6506 /* check the required size. */
6507 for (i
=0; i
<*returned
; i
++) {
6508 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6509 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6512 if (!alloc_buffer_size(buffer
, *needed
)) {
6513 SAFE_FREE(driver_info_2
);
6514 return WERR_INSUFFICIENT_BUFFER
;
6517 /* fill the buffer with the form structures */
6518 for (i
=0; i
<*returned
; i
++) {
6519 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6520 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6523 SAFE_FREE(driver_info_2
);
6525 if (*needed
> offered
) {
6527 return WERR_INSUFFICIENT_BUFFER
;
6533 /****************************************************************************
6534 Enumerates all printer drivers at level 3.
6535 ****************************************************************************/
6537 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6542 fstring
*list
= NULL
;
6544 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6545 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
6549 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6551 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6552 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6558 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
6559 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6560 SAFE_FREE(driver_info_3
);
6564 else driver_info_3
= tdi3
;
6567 for (i
=0; i
<ndrivers
; i
++) {
6570 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6571 ZERO_STRUCT(driver
);
6572 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6573 architecture
, version
);
6574 if (!W_ERROR_IS_OK(status
)) {
6578 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6579 free_a_printer_driver(driver
, 3);
6582 *returned
+=ndrivers
;
6586 /* check the required size. */
6587 for (i
=0; i
<*returned
; i
++) {
6588 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6589 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6592 if (!alloc_buffer_size(buffer
, *needed
)) {
6593 SAFE_FREE(driver_info_3
);
6594 return WERR_INSUFFICIENT_BUFFER
;
6597 /* fill the buffer with the driver structures */
6598 for (i
=0; i
<*returned
; i
++) {
6599 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6600 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6603 for (i
=0; i
<*returned
; i
++)
6604 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6606 SAFE_FREE(driver_info_3
);
6608 if (*needed
> offered
) {
6610 return WERR_INSUFFICIENT_BUFFER
;
6616 /****************************************************************************
6617 Enumerates all printer drivers.
6618 ****************************************************************************/
6620 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6622 UNISTR2
*environment
= &q_u
->environment
;
6623 uint32 level
= q_u
->level
;
6624 NEW_BUFFER
*buffer
= NULL
;
6625 uint32 offered
= q_u
->offered
;
6626 uint32
*needed
= &r_u
->needed
;
6627 uint32
*returned
= &r_u
->returned
;
6629 fstring
*list
= NULL
;
6631 fstring architecture
;
6633 /* that's an [in out] buffer */
6634 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6635 buffer
= r_u
->buffer
;
6637 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6638 fstrcpy(servername
, get_called_name());
6642 unistr2_to_ascii(architecture
, environment
, sizeof(architecture
)-1);
6646 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
6648 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
6650 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
6654 return WERR_UNKNOWN_LEVEL
;
6658 /****************************************************************************
6659 ****************************************************************************/
6661 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
6663 form
->flag
=list
->flag
;
6664 init_unistr(&form
->name
, list
->name
);
6665 form
->width
=list
->width
;
6666 form
->length
=list
->length
;
6667 form
->left
=list
->left
;
6668 form
->top
=list
->top
;
6669 form
->right
=list
->right
;
6670 form
->bottom
=list
->bottom
;
6673 /****************************************************************************
6674 ****************************************************************************/
6676 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
6678 uint32 level
= q_u
->level
;
6679 NEW_BUFFER
*buffer
= NULL
;
6680 uint32 offered
= q_u
->offered
;
6681 uint32
*needed
= &r_u
->needed
;
6682 uint32
*numofforms
= &r_u
->numofforms
;
6683 uint32 numbuiltinforms
;
6685 nt_forms_struct
*list
=NULL
;
6686 nt_forms_struct
*builtinlist
=NULL
;
6691 /* that's an [in out] buffer */
6692 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6693 buffer
= r_u
->buffer
;
6695 DEBUG(4,("_spoolss_enumforms\n"));
6696 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6697 DEBUGADD(5,("Info level [%d]\n", level
));
6699 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
6700 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
6701 *numofforms
= get_ntforms(&list
);
6702 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
6703 *numofforms
+= numbuiltinforms
;
6705 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
6709 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
6714 /* construct the list of form structures */
6715 for (i
=0; i
<numbuiltinforms
; i
++) {
6716 DEBUGADD(6,("Filling form number [%d]\n",i
));
6717 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
6720 SAFE_FREE(builtinlist
);
6722 for (; i
<*numofforms
; i
++) {
6723 DEBUGADD(6,("Filling form number [%d]\n",i
));
6724 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
6729 /* check the required size. */
6730 for (i
=0; i
<numbuiltinforms
; i
++) {
6731 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6732 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6734 for (; i
<*numofforms
; i
++) {
6735 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6736 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6739 *needed
=buffer_size
;
6741 if (!alloc_buffer_size(buffer
, buffer_size
)){
6743 return WERR_INSUFFICIENT_BUFFER
;
6746 /* fill the buffer with the form structures */
6747 for (i
=0; i
<numbuiltinforms
; i
++) {
6748 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6749 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6751 for (; i
<*numofforms
; i
++) {
6752 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6753 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6758 if (*needed
> offered
) {
6760 return WERR_INSUFFICIENT_BUFFER
;
6767 SAFE_FREE(builtinlist
);
6768 return WERR_UNKNOWN_LEVEL
;
6773 /****************************************************************************
6774 ****************************************************************************/
6776 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
6778 uint32 level
= q_u
->level
;
6779 UNISTR2
*uni_formname
= &q_u
->formname
;
6780 NEW_BUFFER
*buffer
= NULL
;
6781 uint32 offered
= q_u
->offered
;
6782 uint32
*needed
= &r_u
->needed
;
6784 nt_forms_struct
*list
=NULL
;
6785 nt_forms_struct builtin_form
;
6790 int numofforms
=0, i
=0;
6792 /* that's an [in out] buffer */
6793 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6794 buffer
= r_u
->buffer
;
6796 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
6798 DEBUG(4,("_spoolss_getform\n"));
6799 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6800 DEBUGADD(5,("Info level [%d]\n", level
));
6802 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
6803 if (!foundBuiltin
) {
6804 numofforms
= get_ntforms(&list
);
6805 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
6807 if (numofforms
== 0)
6814 fill_form_1(&form_1
, &builtin_form
);
6817 /* Check if the requested name is in the list of form structures */
6818 for (i
=0; i
<numofforms
; i
++) {
6820 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
6822 if (strequal(form_name
, list
[i
].name
)) {
6823 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
6824 fill_form_1(&form_1
, &list
[i
]);
6830 if (i
== numofforms
) {
6834 /* check the required size. */
6836 *needed
=spoolss_size_form_1(&form_1
);
6838 if (!alloc_buffer_size(buffer
, buffer_size
)){
6839 return WERR_INSUFFICIENT_BUFFER
;
6842 if (*needed
> offered
) {
6843 return WERR_INSUFFICIENT_BUFFER
;
6846 /* fill the buffer with the form structures */
6847 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
6848 smb_io_form_1("", buffer
, &form_1
, 0);
6854 return WERR_UNKNOWN_LEVEL
;
6858 /****************************************************************************
6859 ****************************************************************************/
6861 static void fill_port_1(PORT_INFO_1
*port
, char *name
)
6863 init_unistr(&port
->port_name
, name
);
6866 /****************************************************************************
6867 ****************************************************************************/
6869 static void fill_port_2(PORT_INFO_2
*port
, char *name
)
6871 init_unistr(&port
->port_name
, name
);
6872 init_unistr(&port
->monitor_name
, "Local Monitor");
6873 init_unistr(&port
->description
, "Local Port");
6874 #define PORT_TYPE_WRITE 1
6875 port
->port_type
=PORT_TYPE_WRITE
;
6879 /****************************************************************************
6881 ****************************************************************************/
6883 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6885 PORT_INFO_1
*ports
=NULL
;
6888 if (*lp_enumports_cmd()) {
6889 char *cmd
= lp_enumports_cmd();
6896 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
6898 DEBUG(10,("Running [%s]\n", command
));
6899 ret
= smbrun(command
, &fd
);
6900 DEBUG(10,("Returned [%d]\n", ret
));
6904 /* Is this the best error to return here? */
6905 return WERR_ACCESS_DENIED
;
6909 qlines
= fd_lines_load(fd
, &numlines
);
6910 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6914 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
6915 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6916 dos_errstr(WERR_NOMEM
)));
6917 file_lines_free(qlines
);
6921 for (i
=0; i
<numlines
; i
++) {
6922 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6923 fill_port_1(&ports
[i
], qlines
[i
]);
6926 file_lines_free(qlines
);
6929 *returned
= numlines
;
6932 *returned
= 1; /* Sole Samba port returned. */
6934 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
6937 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
6939 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
6942 /* check the required size. */
6943 for (i
=0; i
<*returned
; i
++) {
6944 DEBUGADD(6,("adding port [%d]'s size\n", i
));
6945 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
6948 if (!alloc_buffer_size(buffer
, *needed
)) {
6950 return WERR_INSUFFICIENT_BUFFER
;
6953 /* fill the buffer with the ports structures */
6954 for (i
=0; i
<*returned
; i
++) {
6955 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
6956 smb_io_port_1("", buffer
, &ports
[i
], 0);
6961 if (*needed
> offered
) {
6963 return WERR_INSUFFICIENT_BUFFER
;
6969 /****************************************************************************
6971 ****************************************************************************/
6973 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6975 PORT_INFO_2
*ports
=NULL
;
6978 if (*lp_enumports_cmd()) {
6979 char *cmd
= lp_enumports_cmd();
6988 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
6989 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
6991 path
= lp_lockdir();
6993 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
6994 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
6997 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
6998 ret
= smbrun(command
, &fd
);
6999 DEBUGADD(10,("returned [%d]\n", ret
));
7003 /* Is this the best error to return here? */
7004 return WERR_ACCESS_DENIED
;
7008 qlines
= fd_lines_load(fd
, &numlines
);
7009 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7013 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
7014 file_lines_free(qlines
);
7018 for (i
=0; i
<numlines
; i
++) {
7019 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7020 fill_port_2(&(ports
[i
]), qlines
[i
]);
7023 file_lines_free(qlines
);
7026 *returned
= numlines
;
7032 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
7035 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7037 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7040 /* check the required size. */
7041 for (i
=0; i
<*returned
; i
++) {
7042 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7043 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7046 if (!alloc_buffer_size(buffer
, *needed
)) {
7048 return WERR_INSUFFICIENT_BUFFER
;
7051 /* fill the buffer with the ports structures */
7052 for (i
=0; i
<*returned
; i
++) {
7053 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7054 smb_io_port_2("", buffer
, &ports
[i
], 0);
7059 if (*needed
> offered
) {
7061 return WERR_INSUFFICIENT_BUFFER
;
7067 /****************************************************************************
7069 ****************************************************************************/
7071 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7073 uint32 level
= q_u
->level
;
7074 NEW_BUFFER
*buffer
= NULL
;
7075 uint32 offered
= q_u
->offered
;
7076 uint32
*needed
= &r_u
->needed
;
7077 uint32
*returned
= &r_u
->returned
;
7079 /* that's an [in out] buffer */
7080 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7081 buffer
= r_u
->buffer
;
7083 DEBUG(4,("_spoolss_enumports\n"));
7090 return enumports_level_1(buffer
, offered
, needed
, returned
);
7092 return enumports_level_2(buffer
, offered
, needed
, returned
);
7094 return WERR_UNKNOWN_LEVEL
;
7098 /****************************************************************************
7099 ****************************************************************************/
7101 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7102 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7103 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7104 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7107 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7110 WERROR err
= WERR_OK
;
7112 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
7113 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7117 ZERO_STRUCTP(printer
);
7119 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7120 if (!convert_printer_info(info
, printer
, 2)) {
7121 free_a_printer(&printer
, 2);
7125 /* check to see if the printer already exists */
7127 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7128 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7129 printer
->info_2
->sharename
));
7130 free_a_printer(&printer
, 2);
7131 return WERR_PRINTER_ALREADY_EXISTS
;
7134 if (*lp_addprinter_cmd() ) {
7135 if ( !add_printer_hook(printer
) ) {
7136 free_a_printer(&printer
,2);
7137 return WERR_ACCESS_DENIED
;
7141 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", get_called_name(),
7142 printer
->info_2
->sharename
);
7145 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7146 free_a_printer(&printer
,2);
7147 return WERR_ACCESS_DENIED
;
7150 /* you must be a printer admin to add a new printer */
7151 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7152 free_a_printer(&printer
,2);
7153 return WERR_ACCESS_DENIED
;
7157 * Do sanity check on the requested changes for Samba.
7160 if (!check_printer_ok(printer
->info_2
, snum
)) {
7161 free_a_printer(&printer
,2);
7162 return WERR_INVALID_PARAM
;
7166 * When a printer is created, the drivername bound to the printer is used
7167 * to lookup previously saved driver initialization info, which is then
7168 * bound to the new printer, simulating what happens in the Windows arch.
7173 set_driver_init(printer
, 2);
7177 /* A valid devmode was included, convert and link it
7179 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7181 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7182 &printer
->info_2
->devmode
))
7186 /* write the ASCII on disk */
7187 err
= mod_a_printer(*printer
, 2);
7188 if (!W_ERROR_IS_OK(err
)) {
7189 free_a_printer(&printer
,2);
7193 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7194 /* Handle open failed - remove addition. */
7195 del_a_printer(printer
->info_2
->sharename
);
7196 free_a_printer(&printer
,2);
7197 return WERR_ACCESS_DENIED
;
7200 update_c_setprinter(False
);
7201 free_a_printer(&printer
,2);
7206 /****************************************************************************
7207 ****************************************************************************/
7209 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7211 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
7212 uint32 level
= q_u
->level
;
7213 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7214 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7215 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7216 uint32 user_switch
= q_u
->user_switch
;
7217 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7218 POLICY_HND
*handle
= &r_u
->handle
;
7222 /* we don't handle yet */
7223 /* but I know what to do ... */
7224 return WERR_UNKNOWN_LEVEL
;
7226 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7228 user_switch
, user
, handle
);
7230 return WERR_UNKNOWN_LEVEL
;
7234 /****************************************************************************
7235 ****************************************************************************/
7237 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7239 uint32 level
= q_u
->level
;
7240 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7241 WERROR err
= WERR_OK
;
7242 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7243 struct current_user user
;
7244 fstring driver_name
;
7247 ZERO_STRUCT(driver
);
7249 get_current_user(&user
, p
);
7251 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7256 DEBUG(5,("Cleaning driver's information\n"));
7257 err
= clean_up_driver_struct(driver
, level
, &user
);
7258 if (!W_ERROR_IS_OK(err
))
7261 DEBUG(5,("Moving driver to final destination\n"));
7262 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
7263 if (W_ERROR_IS_OK(err
))
7264 err
= WERR_ACCESS_DENIED
;
7268 if (add_a_printer_driver(driver
, level
)!=0) {
7269 err
= WERR_ACCESS_DENIED
;
7273 /* BEGIN_ADMIN_LOG */
7276 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7277 driver
.info_3
->name
,drv_ver_to_os
[driver
.info_3
->cversion
],uidtoname(user
.uid
));
7278 fstrcpy(driver_name
, driver
.info_3
->name
);
7281 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7282 driver
.info_6
->name
,drv_ver_to_os
[driver
.info_6
->version
],uidtoname(user
.uid
));
7283 fstrcpy(driver_name
, driver
.info_6
->name
);
7289 * I think this is where he DrvUpgradePrinter() hook would be
7290 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7291 * server. Right now, we just need to send ourselves a message
7292 * to update each printer bound to this driver. --jerry
7295 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7296 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7301 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7302 * decide if the driver init data should be deleted. The rules are:
7303 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7304 * 2) delete init data only if there is no 2k/Xp driver
7305 * 3) always delete init data
7306 * The generalized rule is always use init data from the highest order driver.
7307 * It is necessary to follow the driver install by an initialization step to
7308 * finish off this process.
7311 version
= driver
.info_3
->cversion
;
7312 else if (level
== 6)
7313 version
= driver
.info_6
->version
;
7318 * 9x printer driver - never delete init data
7321 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7326 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7327 * there is no 2k/Xp driver init data for this driver name.
7331 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7333 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7335 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7337 if (!del_driver_init(driver_name
))
7338 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7341 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7343 free_a_printer_driver(driver1
,3);
7344 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7351 * 2k or Xp printer driver - always delete init data
7354 if (!del_driver_init(driver_name
))
7355 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7359 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7365 free_a_printer_driver(driver
, level
);
7369 /********************************************************************
7370 * spoolss_addprinterdriverex
7371 ********************************************************************/
7373 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7375 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7376 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7379 * we only support the semantics of AddPrinterDriver()
7380 * i.e. only copy files that are newer than existing ones
7383 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7384 return WERR_ACCESS_DENIED
;
7386 ZERO_STRUCT(q_u_local
);
7387 ZERO_STRUCT(r_u_local
);
7389 /* just pass the information off to _spoolss_addprinterdriver() */
7390 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7391 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7392 q_u_local
.level
= q_u
->level
;
7393 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7395 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7398 /****************************************************************************
7399 ****************************************************************************/
7401 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7403 init_unistr(&info
->name
, name
);
7406 /****************************************************************************
7407 ****************************************************************************/
7409 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7413 pstring short_archi
;
7414 DRIVER_DIRECTORY_1
*info
=NULL
;
7416 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7418 if (get_short_archi(short_archi
, long_archi
)==False
)
7419 return WERR_INVALID_ENVIRONMENT
;
7421 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
7424 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi
);
7426 DEBUG(4,("printer driver directory: [%s]\n", path
));
7428 fill_driverdir_1(info
, path
);
7430 *needed
+= spoolss_size_driverdir_info_1(info
);
7432 if (!alloc_buffer_size(buffer
, *needed
)) {
7434 return WERR_INSUFFICIENT_BUFFER
;
7437 smb_io_driverdir_1("", buffer
, info
, 0);
7441 if (*needed
> offered
)
7442 return WERR_INSUFFICIENT_BUFFER
;
7447 /****************************************************************************
7448 ****************************************************************************/
7450 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7452 UNISTR2
*name
= &q_u
->name
;
7453 UNISTR2
*uni_environment
= &q_u
->environment
;
7454 uint32 level
= q_u
->level
;
7455 NEW_BUFFER
*buffer
= NULL
;
7456 uint32 offered
= q_u
->offered
;
7457 uint32
*needed
= &r_u
->needed
;
7459 /* that's an [in out] buffer */
7460 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7461 buffer
= r_u
->buffer
;
7463 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7469 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7471 return WERR_UNKNOWN_LEVEL
;
7475 /****************************************************************************
7476 ****************************************************************************/
7478 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7480 POLICY_HND
*handle
= &q_u
->handle
;
7481 uint32 idx
= q_u
->index
;
7482 uint32 in_value_len
= q_u
->valuesize
;
7483 uint32 in_data_len
= q_u
->datasize
;
7484 uint32
*out_max_value_len
= &r_u
->valuesize
;
7485 uint16
**out_value
= &r_u
->value
;
7486 uint32
*out_value_len
= &r_u
->realvaluesize
;
7487 uint32
*out_type
= &r_u
->type
;
7488 uint32
*out_max_data_len
= &r_u
->datasize
;
7489 uint8
**data_out
= &r_u
->data
;
7490 uint32
*out_data_len
= &r_u
->realdatasize
;
7492 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7495 uint32 biggest_valuesize
;
7496 uint32 biggest_datasize
;
7498 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7501 REGISTRY_VALUE
*val
;
7502 NT_PRINTER_DATA
*p_data
;
7503 int i
, key_index
, num_values
;
7506 ZERO_STRUCT( printer
);
7510 *out_max_data_len
= 0;
7514 DEBUG(5,("spoolss_enumprinterdata\n"));
7517 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7521 if (!get_printer_snum(p
,handle
, &snum
))
7524 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7525 if (!W_ERROR_IS_OK(result
))
7528 p_data
= &printer
->info_2
->data
;
7529 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7534 * The NT machine wants to know the biggest size of value and data
7536 * cf: MSDN EnumPrinterData remark section
7539 if ( !in_value_len
&& !in_data_len
)
7541 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7544 biggest_valuesize
= 0;
7545 biggest_datasize
= 0;
7547 num_values
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
7549 for ( i
=0; i
<num_values
; i
++ )
7551 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
7553 name_length
= strlen(val
->valuename
);
7554 if ( strlen(val
->valuename
) > biggest_valuesize
)
7555 biggest_valuesize
= name_length
;
7557 if ( val
->size
> biggest_datasize
)
7558 biggest_datasize
= val
->size
;
7560 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7564 /* the value is an UNICODE string but real_value_size is the length
7565 in bytes including the trailing 0 */
7567 *out_value_len
= 2 * (1+biggest_valuesize
);
7568 *out_data_len
= biggest_datasize
;
7570 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7576 * the value len is wrong in NT sp3
7577 * that's the number of bytes not the number of unicode chars
7580 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, idx
);
7585 /* out_value should default to "" or else NT4 has
7586 problems unmarshalling the response */
7588 *out_max_value_len
= (in_value_len
/sizeof(uint16
));
7590 if ( (*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7592 result
= WERR_NOMEM
;
7596 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
7598 /* the data is counted in bytes */
7600 *out_max_data_len
= in_data_len
;
7601 *out_data_len
= in_data_len
;
7603 /* only allocate when given a non-zero data_len */
7605 if ( in_data_len
&& ((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
7607 result
= WERR_NOMEM
;
7611 result
= WERR_NO_MORE_ITEMS
;
7617 * - counted in bytes in the request
7618 * - counted in UNICODE chars in the max reply
7619 * - counted in bytes in the real size
7621 * take a pause *before* coding not *during* coding
7625 *out_max_value_len
= ( in_value_len
/ sizeof(uint16
) );
7626 if ( (*out_value
= (uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7628 result
= WERR_NOMEM
;
7632 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), in_value_len
, 0);
7636 *out_type
= regval_type( val
);
7638 /* data - counted in bytes */
7640 *out_max_data_len
= in_data_len
;
7641 if ( (*data_out
= (uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
7643 result
= WERR_NOMEM
;
7646 data_len
= (size_t)regval_size(val
);
7647 memcpy( *data_out
, regval_data_p(val
), data_len
);
7648 *out_data_len
= data_len
;
7652 free_a_printer(&printer
, 2);
7656 /****************************************************************************
7657 ****************************************************************************/
7659 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
7661 POLICY_HND
*handle
= &q_u
->handle
;
7662 UNISTR2
*value
= &q_u
->value
;
7663 uint32 type
= q_u
->type
;
7664 uint8
*data
= q_u
->data
;
7665 uint32 real_len
= q_u
->real_len
;
7667 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7669 WERROR status
= WERR_OK
;
7670 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7673 DEBUG(5,("spoolss_setprinterdata\n"));
7676 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7680 if (!get_printer_snum(p
,handle
, &snum
))
7684 * Access check : NT returns "access denied" if you make a
7685 * SetPrinterData call without the necessary privildge.
7686 * we were originally returning OK if nothing changed
7687 * which made Win2k issue **a lot** of SetPrinterData
7688 * when connecting to a printer --jerry
7691 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
7693 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7694 status
= WERR_ACCESS_DENIED
;
7698 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7699 if (!W_ERROR_IS_OK(status
))
7702 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
7705 * When client side code sets a magic printer data key, detect it and save
7706 * the current printer data and the magic key's data (its the DEVMODE) for
7707 * future printer/driver initializations.
7709 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
7711 /* Set devmode and printer initialization info */
7712 status
= save_driver_init( printer
, 2, data
, real_len
);
7714 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
7718 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
7719 type
, data
, real_len
);
7720 if ( W_ERROR_IS_OK(status
) )
7721 status
= mod_a_printer(*printer
, 2);
7725 free_a_printer(&printer
, 2);
7730 /****************************************************************************
7731 ****************************************************************************/
7733 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
7735 POLICY_HND
*handle
= &q_u
->handle
;
7736 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7739 DEBUG(5,("_spoolss_resetprinter\n"));
7742 * All we do is to check to see if the handle and queue is valid.
7743 * This call really doesn't mean anything to us because we only
7744 * support RAW printing. --jerry
7748 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7752 if (!get_printer_snum(p
,handle
, &snum
))
7756 /* blindly return success */
7761 /****************************************************************************
7762 ****************************************************************************/
7764 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
7766 POLICY_HND
*handle
= &q_u
->handle
;
7767 UNISTR2
*value
= &q_u
->valuename
;
7769 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7771 WERROR status
= WERR_OK
;
7772 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7775 DEBUG(5,("spoolss_deleteprinterdata\n"));
7778 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7782 if (!get_printer_snum(p
, handle
, &snum
))
7785 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7786 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7787 return WERR_ACCESS_DENIED
;
7790 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7791 if (!W_ERROR_IS_OK(status
))
7794 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
7796 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
7798 free_a_printer(&printer
, 2);
7803 /****************************************************************************
7804 ****************************************************************************/
7806 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
7808 POLICY_HND
*handle
= &q_u
->handle
;
7809 FORM
*form
= &q_u
->form
;
7810 nt_forms_struct tmpForm
;
7812 WERROR status
= WERR_OK
;
7813 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7816 nt_forms_struct
*list
=NULL
;
7817 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7819 DEBUG(5,("spoolss_addform\n"));
7822 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7827 /* forms can be added on printer of on the print server handle */
7829 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7831 if (!get_printer_snum(p
,handle
, &snum
))
7834 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7835 if (!W_ERROR_IS_OK(status
))
7839 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7840 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7841 status
= WERR_ACCESS_DENIED
;
7845 /* can't add if builtin */
7847 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7848 status
= WERR_ALREADY_EXISTS
;
7852 count
= get_ntforms(&list
);
7854 if(!add_a_form(&list
, form
, &count
)) {
7855 status
= WERR_NOMEM
;
7859 write_ntforms(&list
, count
);
7862 * ChangeID must always be set if this is a printer
7865 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7866 status
= mod_a_printer(*printer
, 2);
7870 free_a_printer(&printer
, 2);
7876 /****************************************************************************
7877 ****************************************************************************/
7879 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
7881 POLICY_HND
*handle
= &q_u
->handle
;
7882 UNISTR2
*form_name
= &q_u
->name
;
7883 nt_forms_struct tmpForm
;
7885 nt_forms_struct
*list
=NULL
;
7886 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7888 WERROR status
= WERR_OK
;
7889 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7891 DEBUG(5,("spoolss_deleteform\n"));
7894 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7898 /* forms can be deleted on printer of on the print server handle */
7900 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7902 if (!get_printer_snum(p
,handle
, &snum
))
7905 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7906 if (!W_ERROR_IS_OK(status
))
7910 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7911 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7912 status
= WERR_ACCESS_DENIED
;
7916 /* can't delete if builtin */
7918 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
7919 status
= WERR_INVALID_PARAM
;
7923 count
= get_ntforms(&list
);
7925 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
7929 * ChangeID must always be set if this is a printer
7932 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7933 status
= mod_a_printer(*printer
, 2);
7937 free_a_printer(&printer
, 2);
7943 /****************************************************************************
7944 ****************************************************************************/
7946 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
7948 POLICY_HND
*handle
= &q_u
->handle
;
7949 FORM
*form
= &q_u
->form
;
7950 nt_forms_struct tmpForm
;
7952 WERROR status
= WERR_OK
;
7953 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7956 nt_forms_struct
*list
=NULL
;
7957 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7959 DEBUG(5,("spoolss_setform\n"));
7962 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7966 /* forms can be modified on printer of on the print server handle */
7968 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7970 if (!get_printer_snum(p
,handle
, &snum
))
7973 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7974 if (!W_ERROR_IS_OK(status
))
7978 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7979 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7980 status
= WERR_ACCESS_DENIED
;
7984 /* can't set if builtin */
7985 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7986 status
= WERR_INVALID_PARAM
;
7990 count
= get_ntforms(&list
);
7991 update_a_form(&list
, form
, count
);
7992 write_ntforms(&list
, count
);
7995 * ChangeID must always be set if this is a printer
7998 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7999 status
= mod_a_printer(*printer
, 2);
8004 free_a_printer(&printer
, 2);
8010 /****************************************************************************
8011 enumprintprocessors level 1.
8012 ****************************************************************************/
8014 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8016 PRINTPROCESSOR_1
*info_1
=NULL
;
8018 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
8023 init_unistr(&info_1
->name
, "winprint");
8025 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8027 if (!alloc_buffer_size(buffer
, *needed
))
8028 return WERR_INSUFFICIENT_BUFFER
;
8030 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8034 if (*needed
> offered
) {
8036 return WERR_INSUFFICIENT_BUFFER
;
8042 /****************************************************************************
8043 ****************************************************************************/
8045 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8047 uint32 level
= q_u
->level
;
8048 NEW_BUFFER
*buffer
= NULL
;
8049 uint32 offered
= q_u
->offered
;
8050 uint32
*needed
= &r_u
->needed
;
8051 uint32
*returned
= &r_u
->returned
;
8053 /* that's an [in out] buffer */
8054 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8055 buffer
= r_u
->buffer
;
8057 DEBUG(5,("spoolss_enumprintprocessors\n"));
8060 * Enumerate the print processors ...
8062 * Just reply with "winprint", to keep NT happy
8063 * and I can use my nice printer checker.
8071 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8073 return WERR_UNKNOWN_LEVEL
;
8077 /****************************************************************************
8078 enumprintprocdatatypes level 1.
8079 ****************************************************************************/
8081 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8083 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8085 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
8090 init_unistr(&info_1
->name
, "RAW");
8092 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8094 if (!alloc_buffer_size(buffer
, *needed
))
8095 return WERR_INSUFFICIENT_BUFFER
;
8097 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8101 if (*needed
> offered
) {
8103 return WERR_INSUFFICIENT_BUFFER
;
8109 /****************************************************************************
8110 ****************************************************************************/
8112 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8114 uint32 level
= q_u
->level
;
8115 NEW_BUFFER
*buffer
= NULL
;
8116 uint32 offered
= q_u
->offered
;
8117 uint32
*needed
= &r_u
->needed
;
8118 uint32
*returned
= &r_u
->returned
;
8120 /* that's an [in out] buffer */
8121 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8122 buffer
= r_u
->buffer
;
8124 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8131 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8133 return WERR_UNKNOWN_LEVEL
;
8137 /****************************************************************************
8138 enumprintmonitors level 1.
8139 ****************************************************************************/
8141 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8143 PRINTMONITOR_1
*info_1
=NULL
;
8145 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
8150 init_unistr(&info_1
->name
, "Local Port");
8152 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
8154 if (!alloc_buffer_size(buffer
, *needed
))
8155 return WERR_INSUFFICIENT_BUFFER
;
8157 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
8161 if (*needed
> offered
) {
8163 return WERR_INSUFFICIENT_BUFFER
;
8169 /****************************************************************************
8170 enumprintmonitors level 2.
8171 ****************************************************************************/
8173 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8175 PRINTMONITOR_2
*info_2
=NULL
;
8177 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
8182 init_unistr(&info_2
->name
, "Local Port");
8183 init_unistr(&info_2
->environment
, "Windows NT X86");
8184 init_unistr(&info_2
->dll_name
, "localmon.dll");
8186 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
8188 if (!alloc_buffer_size(buffer
, *needed
))
8189 return WERR_INSUFFICIENT_BUFFER
;
8191 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
8195 if (*needed
> offered
) {
8197 return WERR_INSUFFICIENT_BUFFER
;
8203 /****************************************************************************
8204 ****************************************************************************/
8206 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8208 uint32 level
= q_u
->level
;
8209 NEW_BUFFER
*buffer
= NULL
;
8210 uint32 offered
= q_u
->offered
;
8211 uint32
*needed
= &r_u
->needed
;
8212 uint32
*returned
= &r_u
->returned
;
8214 /* that's an [in out] buffer */
8215 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8216 buffer
= r_u
->buffer
;
8218 DEBUG(5,("spoolss_enumprintmonitors\n"));
8221 * Enumerate the print monitors ...
8223 * Just reply with "Local Port", to keep NT happy
8224 * and I can use my nice printer checker.
8232 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8234 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8236 return WERR_UNKNOWN_LEVEL
;
8240 /****************************************************************************
8241 ****************************************************************************/
8243 static WERROR
getjob_level_1(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
8247 JOB_INFO_1
*info_1
=NULL
;
8249 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
8251 if (info_1
== NULL
) {
8256 for (i
=0; i
<count
&& found
==False
; i
++) {
8257 if (queue
[i
].job
==(int)jobid
)
8264 /* NT treats not found as bad param... yet another bad choice */
8265 return WERR_INVALID_PARAM
;
8268 fill_job_info_1(info_1
, &(queue
[i
-1]), i
, snum
);
8270 *needed
+= spoolss_size_job_info_1(info_1
);
8272 if (!alloc_buffer_size(buffer
, *needed
)) {
8274 return WERR_INSUFFICIENT_BUFFER
;
8277 smb_io_job_info_1("", buffer
, info_1
, 0);
8281 if (*needed
> offered
)
8282 return WERR_INSUFFICIENT_BUFFER
;
8287 /****************************************************************************
8288 ****************************************************************************/
8290 static WERROR
getjob_level_2(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
8295 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8297 DEVICEMODE
*devmode
= NULL
;
8298 NT_DEVICEMODE
*nt_devmode
= NULL
;
8300 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
8302 ZERO_STRUCTP(info_2
);
8304 if (info_2
== NULL
) {
8309 for ( i
=0; i
<count
&& found
==False
; i
++ )
8311 if (queue
[i
].job
== (int)jobid
)
8317 /* NT treats not found as bad param... yet another bad
8319 ret
= WERR_INVALID_PARAM
;
8323 ret
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
8324 if (!W_ERROR_IS_OK(ret
))
8328 * if the print job does not have a DEVMODE associated with it,
8329 * just use the one for the printer. A NULL devicemode is not
8330 * a failure condition
8333 if ( !(nt_devmode
=print_job_devmode( snum
, jobid
)) )
8334 devmode
= construct_dev_mode(snum
);
8336 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) != NULL
) {
8337 ZERO_STRUCTP( devmode
);
8338 convert_nt_devicemode( devmode
, nt_devmode
);
8342 fill_job_info_2(info_2
, &(queue
[i
-1]), i
, snum
, ntprinter
, devmode
);
8344 *needed
+= spoolss_size_job_info_2(info_2
);
8346 if (!alloc_buffer_size(buffer
, *needed
)) {
8347 ret
= WERR_INSUFFICIENT_BUFFER
;
8351 smb_io_job_info_2("", buffer
, info_2
, 0);
8353 if (*needed
> offered
) {
8354 ret
= WERR_INSUFFICIENT_BUFFER
;
8361 /* Cleanup allocated memory */
8363 free_job_info_2(info_2
); /* Also frees devmode */
8365 free_a_printer(&ntprinter
, 2);
8370 /****************************************************************************
8371 ****************************************************************************/
8373 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8375 POLICY_HND
*handle
= &q_u
->handle
;
8376 uint32 jobid
= q_u
->jobid
;
8377 uint32 level
= q_u
->level
;
8378 NEW_BUFFER
*buffer
= NULL
;
8379 uint32 offered
= q_u
->offered
;
8380 uint32
*needed
= &r_u
->needed
;
8381 WERROR wstatus
= WERR_OK
;
8385 print_queue_struct
*queue
= NULL
;
8386 print_status_struct prt_status
;
8388 /* that's an [in out] buffer */
8389 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8390 buffer
= r_u
->buffer
;
8392 DEBUG(5,("spoolss_getjob\n"));
8396 if (!get_printer_snum(p
, handle
, &snum
))
8399 count
= print_queue_status(snum
, &queue
, &prt_status
);
8401 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8402 count
, prt_status
.status
, prt_status
.message
));
8406 wstatus
= getjob_level_1(queue
, count
, snum
, jobid
,
8407 buffer
, offered
, needed
);
8410 wstatus
= getjob_level_2(queue
, count
, snum
, jobid
,
8411 buffer
, offered
, needed
);
8414 wstatus
= WERR_UNKNOWN_LEVEL
;
8422 /********************************************************************
8423 spoolss_getprinterdataex
8425 From MSDN documentation of GetPrinterDataEx: pass request
8426 to GetPrinterData if key is "PrinterDriverData".
8427 ********************************************************************/
8429 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8431 POLICY_HND
*handle
= &q_u
->handle
;
8432 uint32 in_size
= q_u
->size
;
8433 uint32
*type
= &r_u
->type
;
8434 uint32
*out_size
= &r_u
->size
;
8435 uint8
**data
= &r_u
->data
;
8436 uint32
*needed
= &r_u
->needed
;
8437 fstring keyname
, valuename
;
8439 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8441 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8443 WERROR status
= WERR_OK
;
8445 DEBUG(4,("_spoolss_getprinterdataex\n"));
8447 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8448 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
8450 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8451 keyname
, valuename
));
8453 /* in case of problem, return some default values */
8457 *out_size
= in_size
;
8460 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8461 status
= WERR_BADFID
;
8465 /* Is the handle to a printer or to the server? */
8467 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8468 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8469 status
= WERR_INVALID_PARAM
;
8473 if ( !get_printer_snum(p
,handle
, &snum
) )
8476 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8477 if ( !W_ERROR_IS_OK(status
) )
8480 /* check to see if the keyname is valid */
8481 if ( !strlen(keyname
) ) {
8482 status
= WERR_INVALID_PARAM
;
8486 if ( lookup_printerkey( &printer
->info_2
->data
, keyname
) == -1 ) {
8487 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
8488 free_a_printer( &printer
, 2 );
8489 status
= WERR_BADFILE
;
8493 /* When given a new keyname, we should just create it */
8495 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
8497 if (*needed
> *out_size
)
8498 status
= WERR_MORE_DATA
;
8501 if ( !W_ERROR_IS_OK(status
) )
8503 DEBUG(5, ("error: allocating %d\n", *out_size
));
8505 /* reply this param doesn't exist */
8509 if( (*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
8510 status
= WERR_NOMEM
;
8520 free_a_printer( &printer
, 2 );
8525 /********************************************************************
8526 * spoolss_setprinterdataex
8527 ********************************************************************/
8529 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
8531 POLICY_HND
*handle
= &q_u
->handle
;
8532 uint32 type
= q_u
->type
;
8533 uint8
*data
= q_u
->data
;
8534 uint32 real_len
= q_u
->real_len
;
8536 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8538 WERROR status
= WERR_OK
;
8539 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8544 DEBUG(4,("_spoolss_setprinterdataex\n"));
8546 /* From MSDN documentation of SetPrinterDataEx: pass request to
8547 SetPrinterData if key is "PrinterDriverData" */
8550 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8554 if ( !get_printer_snum(p
,handle
, &snum
) )
8558 * Access check : NT returns "access denied" if you make a
8559 * SetPrinterData call without the necessary privildge.
8560 * we were originally returning OK if nothing changed
8561 * which made Win2k issue **a lot** of SetPrinterData
8562 * when connecting to a printer --jerry
8565 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8567 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8568 return WERR_ACCESS_DENIED
;
8571 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8572 if (!W_ERROR_IS_OK(status
))
8575 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
8576 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
8578 /* check for OID in valuename */
8580 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
8586 /* save the registry data */
8588 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
8590 /* save the OID if one was specified and the previous set call succeeded */
8592 if ( W_ERROR_IS_OK(status
) && oid_string
)
8595 fstrcat( keyname
, "\\" );
8596 fstrcat( keyname
, SPOOL_OID_KEY
);
8599 * I'm not checking the status here on purpose. Don't know
8600 * if this is right, but I'm returning the status from the
8601 * previous set_printer_dataex() call. I have no idea if
8602 * this is right. --jerry
8605 set_printer_dataex( printer
, keyname
, valuename
,
8606 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
8609 free_a_printer(&printer
, 2);
8615 /********************************************************************
8616 * spoolss_deleteprinterdataex
8617 ********************************************************************/
8619 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
8621 POLICY_HND
*handle
= &q_u
->handle
;
8622 UNISTR2
*value
= &q_u
->valuename
;
8623 UNISTR2
*key
= &q_u
->keyname
;
8625 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8627 WERROR status
= WERR_OK
;
8628 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8629 pstring valuename
, keyname
;
8631 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8634 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8638 if (!get_printer_snum(p
, handle
, &snum
))
8641 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8642 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8643 return WERR_ACCESS_DENIED
;
8646 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8647 if (!W_ERROR_IS_OK(status
))
8650 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8651 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
8653 status
= delete_printer_dataex( printer
, keyname
, valuename
);
8655 free_a_printer(&printer
, 2);
8660 /********************************************************************
8661 * spoolss_enumprinterkey
8662 ********************************************************************/
8665 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
8668 fstring
*keynames
= NULL
;
8669 uint16
*enumkeys
= NULL
;
8672 POLICY_HND
*handle
= &q_u
->handle
;
8673 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8674 NT_PRINTER_DATA
*data
;
8675 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8677 WERROR status
= WERR_BADFILE
;
8680 DEBUG(4,("_spoolss_enumprinterkey\n"));
8683 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8687 if ( !get_printer_snum(p
,handle
, &snum
) )
8690 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8691 if (!W_ERROR_IS_OK(status
))
8694 /* get the list of subkey names */
8696 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
8697 data
= &printer
->info_2
->data
;
8699 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
8701 if ( num_keys
== -1 ) {
8702 status
= WERR_BADFILE
;
8706 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
8708 r_u
->needed
= printerkey_len
*2;
8710 if ( q_u
->size
< r_u
->needed
) {
8711 status
= WERR_MORE_DATA
;
8715 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
8716 status
= WERR_NOMEM
;
8722 if ( q_u
->size
< r_u
->needed
)
8723 status
= WERR_MORE_DATA
;
8726 free_a_printer( &printer
, 2 );
8727 SAFE_FREE( keynames
);
8732 /********************************************************************
8733 * spoolss_deleteprinterkey
8734 ********************************************************************/
8736 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
8738 POLICY_HND
*handle
= &q_u
->handle
;
8739 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
8741 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8745 DEBUG(5,("spoolss_deleteprinterkey\n"));
8748 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8752 /* if keyname == NULL, return error */
8754 if ( !q_u
->keyname
.buffer
)
8755 return WERR_INVALID_PARAM
;
8757 if (!get_printer_snum(p
, handle
, &snum
))
8760 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8761 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8762 return WERR_ACCESS_DENIED
;
8765 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8766 if (!W_ERROR_IS_OK(status
))
8769 /* delete the key and all subneys */
8771 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
8773 status
= delete_all_printer_data( printer
->info_2
, key
);
8775 if ( W_ERROR_IS_OK(status
) )
8776 status
= mod_a_printer(*printer
, 2);
8778 free_a_printer( &printer
, 2 );
8784 /********************************************************************
8785 * spoolss_enumprinterdataex
8786 ********************************************************************/
8788 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
8790 POLICY_HND
*handle
= &q_u
->handle
;
8791 uint32 in_size
= q_u
->size
;
8794 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8795 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
8796 NT_PRINTER_DATA
*p_data
;
8798 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8803 REGISTRY_VALUE
*val
;
8808 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8811 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
8815 /* first get the printer off of disk */
8817 if (!get_printer_snum(p
,handle
, &snum
))
8820 ZERO_STRUCT(printer
);
8821 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8822 if (!W_ERROR_IS_OK(result
))
8825 /* now look for a match on the key name */
8827 p_data
= &printer
->info_2
->data
;
8829 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
8830 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
8832 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
8833 result
= WERR_INVALID_PARAM
;
8840 /* allocate the memory for the array of pointers -- if necessary */
8842 num_entries
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
8845 if ( (enum_values
=talloc(p
->mem_ctx
, num_entries
*sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
8847 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8848 num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
8849 result
= WERR_NOMEM
;
8853 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
8857 * loop through all params and build the array to pass
8858 * back to the client
8861 for ( i
=0; i
<num_entries
; i
++ )
8863 /* lookup the registry value */
8865 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
8866 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
8870 value_name
= regval_name( val
);
8871 init_unistr( &enum_values
[i
].valuename
, value_name
);
8872 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
8873 enum_values
[i
].type
= regval_type( val
);
8875 data_len
= regval_size( val
);
8877 if ( !(enum_values
[i
].data
= talloc_memdup(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
8879 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8881 result
= WERR_NOMEM
;
8885 enum_values
[i
].data_len
= data_len
;
8887 /* keep track of the size of the array in bytes */
8889 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
8892 /* housekeeping information in the reply */
8894 r_u
->needed
= needed
;
8895 r_u
->returned
= num_entries
;
8897 if (needed
> in_size
) {
8898 result
= WERR_MORE_DATA
;
8902 /* copy data into the reply */
8904 r_u
->ctr
.size
= r_u
->needed
;
8905 r_u
->ctr
.size_of_array
= r_u
->returned
;
8906 r_u
->ctr
.values
= enum_values
;
8911 free_a_printer(&printer
, 2);
8916 /****************************************************************************
8917 ****************************************************************************/
8919 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
8921 init_unistr(&info
->name
, name
);
8924 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
8925 UNISTR2
*environment
,
8932 pstring short_archi
;
8933 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
8935 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
8937 if (get_short_archi(short_archi
, long_archi
)==False
)
8938 return WERR_INVALID_ENVIRONMENT
;
8940 if((info
=(PRINTPROCESSOR_DIRECTORY_1
*)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1
))) == NULL
)
8943 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8945 fill_printprocessordirectory_1(info
, path
);
8947 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
8949 if (!alloc_buffer_size(buffer
, *needed
)) {
8951 return WERR_INSUFFICIENT_BUFFER
;
8954 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
8958 if (*needed
> offered
)
8959 return WERR_INSUFFICIENT_BUFFER
;
8964 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
8966 uint32 level
= q_u
->level
;
8967 NEW_BUFFER
*buffer
= NULL
;
8968 uint32 offered
= q_u
->offered
;
8969 uint32
*needed
= &r_u
->needed
;
8972 /* that's an [in out] buffer */
8973 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8974 buffer
= r_u
->buffer
;
8976 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8982 result
= getprintprocessordirectory_level_1
8983 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
8986 result
= WERR_UNKNOWN_LEVEL
;
8994 WERROR
_spoolss_replyopenprinter(pipes_struct
*p
, SPOOL_Q_REPLYOPENPRINTER
*q_u
,
8995 SPOOL_R_REPLYOPENPRINTER
*r_u
)
8997 DEBUG(5,("_spoolss_replyopenprinter\n"));
8999 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u
->printer
));
9004 WERROR
_spoolss_replycloseprinter(pipes_struct
*p
, SPOOL_Q_REPLYCLOSEPRINTER
*q_u
,
9005 SPOOL_R_REPLYCLOSEPRINTER
*r_u
)
9007 DEBUG(5,("_spoolss_replycloseprinter\n"));