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
33 /* #define EMULATE_WIN2K_HACK 1 */
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41 #define PRINTER_HANDLE_IS_PRINTER 0
42 #define PRINTER_HANDLE_IS_PRINTSERVER 1
44 /* Table to map the driver version */
46 char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
60 /* structure to store the printer handles */
61 /* and a reference to what it's pointing to */
62 /* and the notify info asked about */
63 /* that's the central struct */
64 typedef struct _Printer{
65 struct _Printer *prev, *next;
66 BOOL document_started;
68 uint32 jobid; /* jobid in printing backend */
72 fstring printerservername;
75 uint32 access_granted;
81 SPOOL_NOTIFY_OPTION *option;
82 POLICY_HND client_hnd;
83 uint32 client_connected;
92 static Printer_entry *printers_list;
94 typedef struct _counter_printer_0 {
102 static ubi_dlList counter_list;
104 static struct cli_state notify_cli; /* print notify back-channel */
105 static uint32 smb_connections=0;
108 /* in printing/nt_printing.c */
110 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
112 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
113 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
115 /* translate between internal status numbers and NT status numbers */
116 static int nt_printj_status(int v)
122 return JOB_STATUS_PAUSED;
124 return JOB_STATUS_SPOOLING;
126 return JOB_STATUS_PRINTING;
128 return JOB_STATUS_ERROR;
130 return JOB_STATUS_DELETING;
132 return JOB_STATUS_OFFLINE;
134 return JOB_STATUS_PAPEROUT;
136 return JOB_STATUS_PRINTED;
138 return JOB_STATUS_DELETED;
140 return JOB_STATUS_BLOCKED;
141 case LPQ_USER_INTERVENTION:
142 return JOB_STATUS_USER_INTERVENTION;
147 static int nt_printq_status(int v)
151 return PRINTER_STATUS_PAUSED;
160 /****************************************************************************
161 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
162 ****************************************************************************/
164 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
169 SAFE_FREE((*pp)->ctr.type);
173 /***************************************************************************
174 Disconnect from the client
175 ****************************************************************************/
177 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
181 /* weird if the test succeds !!! */
182 if (smb_connections==0) {
183 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
187 result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle);
189 if (!W_ERROR_IS_OK(result))
190 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
191 dos_errstr(result)));
193 /* if it's the last connection, deconnect the IPC$ share */
194 if (smb_connections==1) {
195 cli_nt_session_close(¬ify_cli);
196 cli_ulogoff(¬ify_cli);
197 cli_shutdown(¬ify_cli);
198 message_deregister(MSG_PRINTER_NOTIFY2);
200 /* Tell the connections db we're no longer interested in
201 * printer notify messages. */
203 register_message_flags( False, FLAG_MSG_PRINTING );
209 /****************************************************************************
210 Functions to free a printer entry datastruct.
211 ****************************************************************************/
213 static void free_printer_entry(void *ptr)
215 Printer_entry *Printer = (Printer_entry *)ptr;
217 if (Printer->notify.client_connected==True)
218 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
220 Printer->notify.flags=0;
221 Printer->notify.options=0;
222 Printer->notify.localmachine[0]='\0';
223 Printer->notify.printerlocal=0;
224 free_spool_notify_option(&Printer->notify.option);
225 Printer->notify.option=NULL;
226 Printer->notify.client_connected=False;
228 /* Remove from the internal list. */
229 DLIST_REMOVE(printers_list, Printer);
234 /****************************************************************************
235 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
236 ****************************************************************************/
238 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
240 SPOOL_NOTIFY_OPTION *new_sp = NULL;
245 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
252 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
254 if (!new_sp->ctr.type) {
263 /****************************************************************************
264 find printer index by handle
265 ****************************************************************************/
267 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
269 Printer_entry *find_printer = NULL;
271 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
272 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
279 /****************************************************************************
280 Close printer index by handle.
281 ****************************************************************************/
283 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
285 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
288 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
292 close_policy_hnd(p, hnd);
297 /****************************************************************************
298 Delete a printer given a handle.
299 ****************************************************************************/
301 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
303 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
306 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
310 if (del_a_printer(Printer->dev.handlename) != 0) {
311 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
315 /* Check calling user has permission to delete printer. Note that
316 since we set the snum parameter to -1 only administrators can
317 delete the printer. This stops people with the Full Control
318 permission from deleting the printer. */
320 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
321 DEBUG(3, ("printer delete denied by security descriptor\n"));
322 return WERR_ACCESS_DENIED;
325 if (*lp_deleteprinter_cmd()) {
327 char *cmd = lp_deleteprinter_cmd();
332 /* Printer->dev.handlename equals portname equals sharename */
333 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
334 Printer->dev.handlename);
336 DEBUG(10,("Running [%s]\n", command));
337 ret = smbrun(command, NULL);
339 return WERR_BADFID; /* What to return here? */
341 DEBUGADD(10,("returned [%d]\n", ret));
343 /* Send SIGHUP to process group... is there a better way? */
346 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
350 return WERR_ACCESS_DENIED;
356 /****************************************************************************
357 Return the snum of a printer corresponding to an handle.
358 ****************************************************************************/
360 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
362 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
365 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
369 switch (Printer->printer_type) {
370 case PRINTER_HANDLE_IS_PRINTER:
371 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
372 *number = print_queue_snum(Printer->dev.handlename);
373 return (*number != -1);
374 case PRINTER_HANDLE_IS_PRINTSERVER:
381 /****************************************************************************
382 Set printer handle type.
383 Check if it's \\server or \\server\printer
384 ****************************************************************************/
386 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
388 DEBUG(3,("Setting printer type=%s\n", handlename));
390 if ( strlen(handlename) < 3 ) {
391 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
395 /* it's a print server */
396 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
397 DEBUGADD(4,("Printer is a print server\n"));
398 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
402 DEBUGADD(4,("Printer is a printer\n"));
403 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
409 /****************************************************************************
410 Set printer handle name.
411 ****************************************************************************/
413 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
416 int n_services=lp_numservices();
421 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
423 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
424 ZERO_STRUCT(Printer->dev.printerservername);
425 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
429 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
432 if (*handlename=='\\') {
433 aprinter=strchr_m(handlename+2, '\\');
440 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
443 * The original code allowed smbd to store a printer name that
444 * was different from the share name. This is not possible
445 * anymore, so I've simplified this loop greatly. Here
446 * we are just verifying that the printer name is a valid
447 * printer service defined in smb.conf
448 * --jerry [Fri Feb 15 11:17:46 CST 2002]
451 for (snum=0; snum<n_services; snum++) {
453 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
456 fstrcpy(sname, lp_servicename(snum));
458 DEBUGADD(5,("share:%s\n",sname));
460 if (! StrCaseCmp(sname, aprinter)) {
469 DEBUGADD(4,("Printer not found\n"));
473 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
475 ZERO_STRUCT(Printer->dev.handlename);
476 fstrcpy(Printer->dev.handlename, sname);
481 /****************************************************************************
482 Find first available printer slot. creates a printer handle for you.
483 ****************************************************************************/
485 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
487 Printer_entry *new_printer;
489 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
491 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
494 ZERO_STRUCTP(new_printer);
496 new_printer->notify.option=NULL;
498 /* Add to the internal list. */
499 DLIST_ADD(printers_list, new_printer);
501 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
502 SAFE_FREE(new_printer);
506 if (!set_printer_hnd_printertype(new_printer, name)) {
507 close_printer_handle(p, hnd);
511 if (!set_printer_hnd_name(new_printer, name)) {
512 close_printer_handle(p, hnd);
516 new_printer->access_granted = access_granted;
518 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
523 /****************************************************************************
524 Allocate more memory for a BUFFER.
525 ****************************************************************************/
527 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
535 /* damn, I'm doing the reverse operation of prs_grow() :) */
536 if (buffer_size < prs_data_size(ps))
539 extra_space = buffer_size - prs_data_size(ps);
542 * save the offset and move to the end of the buffer
543 * prs_grow() checks the extra_space against the offset
545 old_offset=prs_offset(ps);
546 prs_set_offset(ps, prs_data_size(ps));
548 if (!prs_grow(ps, extra_space))
551 prs_set_offset(ps, old_offset);
553 buffer->string_at_end=prs_data_size(ps);
558 /***************************************************************************
559 check to see if the client motify handle is monitoring the notification
560 given by (notify_type, notify_field).
561 **************************************************************************/
563 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
569 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
572 SPOOL_NOTIFY_OPTION *option = p->notify.option;
576 * Flags should always be zero when the change notify
577 * is registered by the cliebnt's spooler. A user Win32 app
578 * might use the flags though instead of the NOTIFY_OPTION_INFO
583 return is_monitoring_event_flags(
584 p->notify.flags, notify_type, notify_field);
586 for (i = 0; i < option->count; i++) {
588 /* Check match for notify_type */
590 if (option->ctr.type[i].type != notify_type)
593 /* Check match for field */
595 for (j = 0; j < option->ctr.type[i].count; j++) {
596 if (option->ctr.type[i].fields[j] == notify_field) {
602 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
603 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
604 p->dev.handlename : p->dev.printerservername,
605 notify_type, notify_field));
610 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
612 static void notify_one_value(struct spoolss_notify_msg *msg,
613 SPOOL_NOTIFY_INFO_DATA *data,
616 data->notify_data.value[0] = msg->notify.value[0];
617 data->notify_data.value[1] = 0;
620 static void notify_string(struct spoolss_notify_msg *msg,
621 SPOOL_NOTIFY_INFO_DATA *data,
626 /* The length of the message includes the trailing \0 */
628 init_unistr2(&unistr, msg->notify.data, msg->len);
630 data->notify_data.data.length = msg->len * 2;
631 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
633 if (!data->notify_data.data.string) {
634 data->notify_data.data.length = 0;
638 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
641 static void notify_system_time(struct spoolss_notify_msg *msg,
642 SPOOL_NOTIFY_INFO_DATA *data,
648 if (msg->len != sizeof(time_t)) {
649 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
654 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
655 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
659 if (!make_systemtime(&systime, localtime((time_t *)msg->notify.data))) {
660 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
664 if (!spoolss_io_system_time("", &ps, 0, &systime))
667 data->notify_data.data.length = prs_offset(&ps);
668 data->notify_data.data.string =
669 talloc(mem_ctx, prs_offset(&ps));
671 memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
676 struct notify2_message_table {
678 void (*fn)(struct spoolss_notify_msg *msg,
679 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
682 static struct notify2_message_table printer_notify_table[] = {
683 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
684 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
685 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
686 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
687 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
688 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
689 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
690 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
691 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
692 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
693 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
694 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
695 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
696 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
697 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
698 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
699 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
700 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
701 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
704 static struct notify2_message_table job_notify_table[] = {
705 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
706 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
707 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
708 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
709 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
710 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
711 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
712 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
713 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
714 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
715 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
716 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
717 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
718 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
719 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
720 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
721 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
722 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
723 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
724 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
725 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
726 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
727 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
728 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
732 /***********************************************************************
733 Allocate talloc context for container object
734 **********************************************************************/
736 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
741 ctr->ctx = talloc_init();
746 /***********************************************************************
747 release all allocated memory and zero out structure
748 **********************************************************************/
750 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
756 talloc_destroy(ctr->ctx);
763 /***********************************************************************
764 **********************************************************************/
766 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
774 /***********************************************************************
775 **********************************************************************/
777 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 index )
779 if ( !ctr || !ctr->msg_groups )
782 if ( index >= ctr->num_groups )
785 return &ctr->msg_groups[index];
789 /***********************************************************************
790 How many groups of change messages do we have ?
791 **********************************************************************/
793 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
798 return ctr->num_groups;
801 /***********************************************************************
802 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
803 **********************************************************************/
805 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
807 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
808 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
809 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
815 /* loop over all groups looking for a matching printer name */
817 for ( i=0; i<ctr->num_groups; i++ ) {
818 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
822 /* add a new group? */
824 if ( i == ctr->num_groups )
828 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
829 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
832 ctr->msg_groups = groups;
834 /* clear the new entry and set the printer name */
836 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
837 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
840 /* add the change messages; 'i' is the correct index now regardless */
842 msg_grp = &ctr->msg_groups[i];
846 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
847 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
850 msg_grp->msgs = msg_list;
852 new_slot = msg_grp->num_msgs-1;
853 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
855 /* need to allocate own copy of data */
858 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
860 return ctr->num_groups;
863 /***********************************************************************
864 Send a change notication message on all handles which have a call
866 **********************************************************************/
868 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 index )
871 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
872 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, index );
873 SPOOLSS_NOTIFY_MSG *messages;
877 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
881 messages = msg_group->msgs;
884 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
888 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
890 /* loop over all printers */
892 for (p = printers_list; p; p = p->next)
894 SPOOL_NOTIFY_INFO_DATA *data;
899 /* Is there notification on this handle? */
901 if ( !p->notify.client_connected )
904 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
906 /* For this printer? Print servers always receive
909 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
910 ( !strequal(msg_group->printername, p->dev.handlename) ) )
913 DEBUG(10,("Our printer\n"));
915 /* allocate the max entries possible */
917 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
920 /* build the array of change notifications */
922 for ( i=0; i<msg_group->num_msgs; i++ )
924 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
926 /* Are we monitoring this event? */
928 if (!is_monitoring_event(p, msg->type, msg->field))
932 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
933 msg->type, msg->field, p->dev.handlename));
936 * if the is a printer notification handle and not a job notification
937 * type, then set the id to 0. Other wise just use what was specified
940 * When registering change notification on a print server handle
941 * we always need to send back the id (snum) matching the printer
942 * for which the change took place. For change notify registered
943 * on a printer handle, this does not matter and the id should be 0.
948 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
954 /* Convert unix jobid to smb jobid */
956 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID)
958 id = sysjob_to_jobid(msg->id);
961 DEBUG(3, ("no such unix jobid %d\n", msg->id));
966 construct_info_data( &data[data_len], msg->type, msg->field, id );
969 case PRINTER_NOTIFY_TYPE:
970 if ( !printer_notify_table[msg->field].fn )
972 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
976 case JOB_NOTIFY_TYPE:
977 if ( !job_notify_table[msg->field].fn )
979 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
984 DEBUG(5, ("Unknown notification type %d\n", msg->type));
991 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
992 data_len, data, p->notify.change, 0 );
996 DEBUG(8,("send_notify2_changes: Exit...\n"));
1000 /***********************************************************************
1001 **********************************************************************/
1003 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
1008 /* Unpack message */
1010 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1013 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
1014 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1017 tdb_unpack((char *)buf + offset, len - offset, "dd",
1018 &msg->notify.value[0], &msg->notify.value[1]);
1020 tdb_unpack((char *)buf + offset, len - offset, "B",
1021 &msg->len, &msg->notify.data);
1023 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1024 msg->type, msg->field, msg->flags));
1027 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1028 msg->notify.value[1]));
1030 dump_data(3, msg->notify.data, msg->len);
1035 /********************************************************************
1036 Receive a notify2 message list
1037 ********************************************************************/
1039 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1041 size_t msg_count, i;
1042 char *buf = (char *)msg;
1045 SPOOLSS_NOTIFY_MSG notify;
1046 SPOOLSS_NOTIFY_MSG_CTR messages;
1050 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1054 msg_count = IVAL(buf, 0);
1057 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1059 if (msg_count == 0) {
1060 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1064 /* initialize the container */
1066 ZERO_STRUCT( messages );
1067 notify_msg_ctr_init( &messages );
1070 * build message groups for each printer identified
1071 * in a change_notify msg. Remember that a PCN message
1072 * includes the handle returned for the srv_spoolss_replyopenprinter()
1073 * call. Therefore messages are grouped according to printer handle.
1076 for ( i=0; i<msg_count; i++ )
1078 if (msg_ptr + 4 - buf > len) {
1079 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1083 msg_len = IVAL(msg_ptr,0);
1086 if (msg_ptr + msg_len - buf > len) {
1087 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1091 /* unpack messages */
1093 ZERO_STRUCT( notify );
1094 notify2_unpack_msg( ¬ify, msg_ptr, msg_len );
1097 /* add to correct list in container */
1099 notify_msg_ctr_addmsg( &messages, ¬ify );
1101 /* free memory that might have been allocated by notify2_unpack_msg() */
1103 if ( notify.len != 0 )
1104 SAFE_FREE( notify.notify.data );
1107 /* process each group of messages */
1109 num_groups = notify_msg_ctr_numgroups( &messages );
1110 for ( i=0; i<num_groups; i++ )
1111 send_notify2_changes( &messages, i );
1116 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1118 notify_msg_ctr_destroy( &messages );
1123 /********************************************************************
1124 Send a message to ourself about new driver being installed
1125 so we can upgrade the information for each printer bound to this
1127 ********************************************************************/
1129 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1131 int len = strlen(drivername);
1136 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1139 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1144 /**********************************************************************
1145 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1146 over all printers, upgrading ones as neessary
1147 **********************************************************************/
1149 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1153 int n_services = lp_numservices();
1155 len = MIN(len,sizeof(drivername)-1);
1156 strncpy(drivername, buf, len);
1158 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1160 /* Iterate the printer list */
1162 for (snum=0; snum<n_services; snum++)
1164 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1167 NT_PRINTER_INFO_LEVEL *printer = NULL;
1169 result = get_a_printer(&printer, 2, lp_servicename(snum));
1170 if (!W_ERROR_IS_OK(result))
1173 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1175 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1177 /* all we care about currently is the change_id */
1179 result = mod_a_printer(*printer, 2);
1180 if (!W_ERROR_IS_OK(result)) {
1181 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1182 dos_errstr(result)));
1186 free_a_printer(&printer, 2);
1193 /********************************************************************
1194 Send a message to ourself about new driver being installed
1195 so we can upgrade the information for each printer bound to this
1197 ********************************************************************/
1199 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1201 int len = strlen(drivername);
1206 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1209 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1214 /**********************************************************************
1215 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1216 over all printers, resetting printer data as neessary
1217 **********************************************************************/
1219 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1223 int n_services = lp_numservices();
1225 len = MIN( len, sizeof(drivername)-1 );
1226 strncpy( drivername, buf, len );
1228 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1230 /* Iterate the printer list */
1232 for ( snum=0; snum<n_services; snum++ )
1234 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1237 NT_PRINTER_INFO_LEVEL *printer = NULL;
1239 result = get_a_printer( &printer, 2, lp_servicename(snum) );
1240 if ( !W_ERROR_IS_OK(result) )
1244 * if the printer is bound to the driver,
1245 * then reset to the new driver initdata
1248 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1250 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1252 if ( !set_driver_init(printer, 2) ) {
1253 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1254 printer->info_2->printername, printer->info_2->drivername));
1258 free_a_printer( &printer, 2 );
1267 /********************************************************************
1268 Copy routines used by convert_to_openprinterex()
1269 *******************************************************************/
1271 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1279 DEBUG (8,("dup_devmode\n"));
1281 /* bulk copy first */
1283 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1287 /* dup the pointer members separately */
1289 len = unistrlen(devmode->devicename.buffer);
1291 d->devicename.buffer = talloc(ctx, len*2);
1292 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1297 len = unistrlen(devmode->formname.buffer);
1299 d->devicename.buffer = talloc(ctx, len*2);
1300 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1304 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1309 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1311 if (!new_ctr || !ctr)
1314 DEBUG(8,("copy_devmode_ctr\n"));
1316 new_ctr->size = ctr->size;
1317 new_ctr->devmode_ptr = ctr->devmode_ptr;
1319 if(ctr->devmode_ptr)
1320 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1323 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1325 if (!new_def || !def)
1328 DEBUG(8,("copy_printer_defaults\n"));
1330 new_def->datatype_ptr = def->datatype_ptr;
1332 if (def->datatype_ptr)
1333 copy_unistr2(&new_def->datatype, &def->datatype);
1335 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1337 new_def->access_required = def->access_required;
1340 /********************************************************************
1341 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1342 * SPOOL_Q_OPEN_PRINTER_EX structure
1343 ********************************************************************/
1345 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1347 if (!q_u_ex || !q_u)
1350 DEBUG(8,("convert_to_openprinterex\n"));
1352 q_u_ex->printername_ptr = q_u->printername_ptr;
1354 if (q_u->printername_ptr)
1355 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1357 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1360 /********************************************************************
1361 * spoolss_open_printer
1363 * called from the spoolss dispatcher
1364 ********************************************************************/
1366 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1368 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1369 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1374 ZERO_STRUCT(q_u_ex);
1375 ZERO_STRUCT(r_u_ex);
1377 /* convert the OpenPrinter() call to OpenPrinterEx() */
1379 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1381 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1383 /* convert back to OpenPrinter() */
1385 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1390 /********************************************************************
1391 * spoolss_open_printer
1393 * If the openprinterex rpc call contains a devmode,
1394 * it's a per-user one. This per-user devmode is derivated
1395 * from the global devmode. Openprinterex() contains a per-user
1396 * devmode for when you do EMF printing and spooling.
1397 * In the EMF case, the NT workstation is only doing half the job
1398 * of rendering the page. The other half is done by running the printer
1399 * driver on the server.
1400 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1401 * The EMF file only contains what is to be printed on the page.
1402 * So in order for the server to know how to print, the NT client sends
1403 * a devicemode attached to the openprinterex call.
1404 * But this devicemode is short lived, it's only valid for the current print job.
1406 * If Samba would have supported EMF spooling, this devicemode would
1407 * have been attached to the handle, to sent it to the driver to correctly
1408 * rasterize the EMF file.
1410 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1411 * we just act as a pass-thru between windows and the printer.
1413 * In order to know that Samba supports only RAW spooling, NT has to call
1414 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1415 * and until NT sends a RAW job, we refuse it.
1417 * But to call getprinter() or startdoc(), you first need a valid handle,
1418 * and to get an handle you have to call openprintex(). Hence why you have
1419 * a devicemode in the openprinterex() call.
1422 * Differences between NT4 and NT 2000.
1425 * On NT4, you only have a global devicemode. This global devicemode can be changed
1426 * by the administrator (or by a user with enough privs). Everytime a user
1427 * wants to print, the devicemode is resetted to the default. In Word, everytime
1428 * you print, the printer's characteristics are always reset to the global devicemode.
1432 * In W2K, there is the notion of per-user devicemode. The first time you use
1433 * a printer, a per-user devicemode is build from the global devicemode.
1434 * If you change your per-user devicemode, it is saved in the registry, under the
1435 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1436 * printer preferences available.
1438 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1439 * on the General Tab of the printer properties windows.
1441 * To change the global devicemode: it's the "Printing Defaults..." button
1442 * on the Advanced Tab of the printer properties window.
1445 ********************************************************************/
1447 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1449 UNISTR2 *printername = NULL;
1450 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1451 POLICY_HND *handle = &r_u->handle;
1455 struct current_user user;
1456 Printer_entry *Printer=NULL;
1458 if (q_u->printername_ptr != 0)
1459 printername = &q_u->printername;
1461 if (printername == NULL)
1462 return WERR_INVALID_PRINTER_NAME;
1464 /* some sanity check because you can open a printer or a print server */
1465 /* aka: \\server\printer or \\server */
1466 unistr2_to_ascii(name, printername, sizeof(name)-1);
1468 DEBUGADD(3,("checking name: %s\n",name));
1470 if (!open_printer_hnd(p, handle, name, 0))
1471 return WERR_INVALID_PRINTER_NAME;
1473 Printer=find_printer_index_by_hnd(p, handle);
1475 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1476 Can't find printer handle we created for printer %s\n", name ));
1477 close_printer_handle(p,handle);
1478 return WERR_INVALID_PRINTER_NAME;
1481 get_current_user(&user, p);
1484 * First case: the user is opening the print server:
1486 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1487 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1489 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1490 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1491 * or if the user is listed in the smb.conf printer admin parameter.
1493 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1494 * client view printer folder, but does not show the MSAPW.
1496 * Note: this test needs code to check access rights here too. Jeremy
1497 * could you look at this?
1499 * Second case: the user is opening a printer:
1500 * NT doesn't let us connect to a printer if the connecting user
1501 * doesn't have print permission.
1504 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1506 /* Printserver handles use global struct... */
1510 /* Map standard access rights to object specific access rights */
1512 se_map_standard(&printer_default->access_required,
1513 &printserver_std_mapping);
1515 /* Deny any object specific bits that don't apply to print
1516 servers (i.e printer and job specific bits) */
1518 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1520 if (printer_default->access_required &
1521 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1522 DEBUG(3, ("access DENIED for non-printserver bits"));
1523 close_printer_handle(p, handle);
1524 return WERR_ACCESS_DENIED;
1527 /* Allow admin access */
1529 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1531 if (!lp_ms_add_printer_wizard()) {
1532 close_printer_handle(p, handle);
1533 return WERR_ACCESS_DENIED;
1536 /* if the user is not root and not a printer admin, then fail */
1539 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
1541 close_printer_handle(p, handle);
1542 return WERR_ACCESS_DENIED;
1545 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1549 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1552 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1553 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1555 /* We fall through to return WERR_OK */
1560 /* NT doesn't let us connect to a printer if the connecting user
1561 doesn't have print permission. */
1563 if (!get_printer_snum(p, handle, &snum))
1566 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1568 /* map an empty access mask to the minimum access mask */
1569 if (printer_default->access_required == 0x0)
1570 printer_default->access_required = PRINTER_ACCESS_USE;
1573 * If we are not serving the printer driver for this printer,
1574 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1575 * will keep NT clients happy --jerry
1578 if (lp_use_client_driver(snum)
1579 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1581 printer_default->access_required = PRINTER_ACCESS_USE;
1584 /* check smb.conf parameters and the the sec_desc */
1586 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1587 DEBUG(3, ("access DENIED for printer open\n"));
1588 close_printer_handle(p, handle);
1589 return WERR_ACCESS_DENIED;
1592 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1593 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1594 close_printer_handle(p, handle);
1595 return WERR_ACCESS_DENIED;
1598 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1599 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1601 printer_default->access_required = PRINTER_ACCESS_USE;
1603 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1604 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1608 Printer->access_granted = printer_default->access_required;
1613 /****************************************************************************
1614 ****************************************************************************/
1616 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1617 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1623 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1632 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1633 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1639 printer->info_3=NULL;
1640 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1644 printer->info_6=NULL;
1645 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1655 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1656 NT_DEVICEMODE **pp_nt_devmode)
1658 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1661 * Ensure nt_devmode is a valid pointer
1662 * as we will be overwriting it.
1665 if (nt_devmode == NULL) {
1666 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1667 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1671 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1672 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1674 nt_devmode->specversion=devmode->specversion;
1675 nt_devmode->driverversion=devmode->driverversion;
1676 nt_devmode->size=devmode->size;
1677 nt_devmode->fields=devmode->fields;
1678 nt_devmode->orientation=devmode->orientation;
1679 nt_devmode->papersize=devmode->papersize;
1680 nt_devmode->paperlength=devmode->paperlength;
1681 nt_devmode->paperwidth=devmode->paperwidth;
1682 nt_devmode->scale=devmode->scale;
1683 nt_devmode->copies=devmode->copies;
1684 nt_devmode->defaultsource=devmode->defaultsource;
1685 nt_devmode->printquality=devmode->printquality;
1686 nt_devmode->color=devmode->color;
1687 nt_devmode->duplex=devmode->duplex;
1688 nt_devmode->yresolution=devmode->yresolution;
1689 nt_devmode->ttoption=devmode->ttoption;
1690 nt_devmode->collate=devmode->collate;
1692 nt_devmode->logpixels=devmode->logpixels;
1693 nt_devmode->bitsperpel=devmode->bitsperpel;
1694 nt_devmode->pelswidth=devmode->pelswidth;
1695 nt_devmode->pelsheight=devmode->pelsheight;
1696 nt_devmode->displayflags=devmode->displayflags;
1697 nt_devmode->displayfrequency=devmode->displayfrequency;
1698 nt_devmode->icmmethod=devmode->icmmethod;
1699 nt_devmode->icmintent=devmode->icmintent;
1700 nt_devmode->mediatype=devmode->mediatype;
1701 nt_devmode->dithertype=devmode->dithertype;
1702 nt_devmode->reserved1=devmode->reserved1;
1703 nt_devmode->reserved2=devmode->reserved2;
1704 nt_devmode->panningwidth=devmode->panningwidth;
1705 nt_devmode->panningheight=devmode->panningheight;
1708 * Only change private and driverextra if the incoming devmode
1709 * has a new one. JRA.
1712 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1713 SAFE_FREE(nt_devmode->private);
1714 nt_devmode->driverextra=devmode->driverextra;
1715 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1717 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1720 *pp_nt_devmode = nt_devmode;
1725 /********************************************************************
1726 * _spoolss_enddocprinter_internal.
1727 ********************************************************************/
1729 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1731 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1735 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1739 if (!get_printer_snum(p, handle, &snum))
1742 Printer->document_started=False;
1743 print_job_end(snum, Printer->jobid,True);
1744 /* error codes unhandled so far ... */
1749 /********************************************************************
1750 * api_spoolss_closeprinter
1751 ********************************************************************/
1753 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1755 POLICY_HND *handle = &q_u->handle;
1757 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1759 if (Printer && Printer->document_started)
1760 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1762 if (!close_printer_handle(p, handle))
1765 /* clear the returned printer handle. Observed behavior
1766 from Win2k server. Don't think this really matters.
1767 Previous code just copied the value of the closed
1770 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1775 /********************************************************************
1776 * api_spoolss_deleteprinter
1778 ********************************************************************/
1780 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1782 POLICY_HND *handle = &q_u->handle;
1783 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1786 if (Printer && Printer->document_started)
1787 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1789 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1791 result = delete_printer_handle(p, handle);
1793 update_c_setprinter(False);
1798 /*******************************************************************
1799 * static function to lookup the version id corresponding to an
1800 * long architecture string
1801 ******************************************************************/
1803 static int get_version_id (char * arch)
1806 struct table_node archi_table[]= {
1808 {"Windows 4.0", "WIN40", 0 },
1809 {"Windows NT x86", "W32X86", 2 },
1810 {"Windows NT R4000", "W32MIPS", 2 },
1811 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1812 {"Windows NT PowerPC", "W32PPC", 2 },
1816 for (i=0; archi_table[i].long_archi != NULL; i++)
1818 if (strcmp(arch, archi_table[i].long_archi) == 0)
1819 return (archi_table[i].version);
1825 /********************************************************************
1826 * _spoolss_deleteprinterdriver
1827 ********************************************************************/
1829 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1833 NT_PRINTER_DRIVER_INFO_LEVEL info;
1834 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1836 struct current_user user;
1838 WERROR status_win2k = WERR_ACCESS_DENIED;
1840 get_current_user(&user, p);
1842 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1843 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1845 /* check that we have a valid driver name first */
1847 if ((version=get_version_id(arch)) == -1)
1848 return WERR_INVALID_ENVIRONMENT;
1851 ZERO_STRUCT(info_win2k);
1853 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1855 /* try for Win2k driver if "Windows NT x86" */
1857 if ( version == 2 ) {
1859 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1860 status = WERR_UNKNOWN_PRINTER_DRIVER;
1866 if (printer_driver_in_use(info.info_3)) {
1867 status = WERR_PRINTER_DRIVER_IN_USE;
1873 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1875 /* if we get to here, we now have 2 driver info structures to remove */
1876 /* remove the Win2k driver first*/
1878 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1879 free_a_printer_driver( info_win2k, 3 );
1881 /* this should not have failed---if it did, report to client */
1882 if ( !W_ERROR_IS_OK(status_win2k) )
1887 status = delete_printer_driver(info.info_3, &user, version, False);
1889 /* if at least one of the deletes succeeded return OK */
1891 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1895 free_a_printer_driver( info, 3 );
1900 /********************************************************************
1901 * spoolss_deleteprinterdriverex
1902 ********************************************************************/
1904 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1908 NT_PRINTER_DRIVER_INFO_LEVEL info;
1909 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1911 uint32 flags = q_u->delete_flags;
1913 struct current_user user;
1915 WERROR status_win2k = WERR_ACCESS_DENIED;
1917 get_current_user(&user, p);
1919 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1920 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1922 /* check that we have a valid driver name first */
1923 if ((version=get_version_id(arch)) == -1) {
1924 /* this is what NT returns */
1925 return WERR_INVALID_ENVIRONMENT;
1928 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
1929 version = q_u->version;
1932 ZERO_STRUCT(info_win2k);
1934 status = get_a_printer_driver(&info, 3, driver, arch, version);
1936 if ( !W_ERROR_IS_OK(status) )
1938 /* if the client asked for a specific version, then we've failed */
1940 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
1943 /* try for Win2k driver if "Windows NT x86" */
1948 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1949 status = WERR_UNKNOWN_PRINTER_DRIVER;
1955 if ( printer_driver_in_use(info.info_3) ) {
1956 status = WERR_PRINTER_DRIVER_IN_USE;
1961 * we have a couple of cases to consider.
1962 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1963 * then the delete should fail if **any** files overlap with
1965 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1966 * non-overlapping files
1967 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1968 * is set, the do not delete any files
1969 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1972 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1974 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1976 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
1977 /* no idea of the correct error here */
1978 status = WERR_ACCESS_DENIED;
1983 /* also check for W32X86/3 if necessary; maybe we already have? */
1985 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
1986 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1989 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
1990 /* no idea of the correct error here */
1991 status = WERR_ACCESS_DENIED;
1995 /* if we get to here, we now have 2 driver info structures to remove */
1996 /* remove the Win2k driver first*/
1998 status_win2k = delete_printer_driver(info.info_3, &user, 3, delete_files);
1999 free_a_printer_driver( info_win2k, 3 );
2001 /* this should not have failed---if it did, report to client */
2003 if ( !W_ERROR_IS_OK(status_win2k) )
2008 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2010 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2013 free_a_printer_driver( info, 3 );
2019 /****************************************************************************
2020 Internal routine for retreiving printerdata
2021 ***************************************************************************/
2023 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2024 char *key, char *value, uint32 *type, uint8 **data,
2025 uint32 *needed, uint32 in_size )
2027 REGISTRY_VALUE *val;
2030 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2031 return WERR_BADFILE;
2033 *type = regval_type( val );
2035 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2037 size = regval_size( val );
2039 /* copy the min(in_size, len) */
2042 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2043 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2051 DEBUG(5,("get_printer_dataex: copy done\n"));
2056 /****************************************************************************
2057 Internal routine for removing printerdata
2058 ***************************************************************************/
2060 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value )
2062 delete_printer_data( printer->info_2, key, value );
2064 return mod_a_printer(*printer, 2);
2067 /****************************************************************************
2068 Internal routine for storing printerdata
2069 ***************************************************************************/
2071 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value,
2072 uint32 type, uint8 *data, int real_len )
2074 delete_printer_data( printer->info_2, key, value );
2076 add_printer_data( printer->info_2, key, value, type, data, real_len );
2078 return mod_a_printer(*printer, 2);
2081 /********************************************************************
2082 GetPrinterData on a printer server Handle.
2083 ********************************************************************/
2085 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2089 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2091 if (!strcmp(value, "W3SvcInstalled")) {
2093 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2099 if (!strcmp(value, "BeepEnabled")) {
2101 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2103 SIVAL(*data, 0, 0x00);
2108 if (!strcmp(value, "EventLog")) {
2110 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2112 /* formally was 0x1b */
2113 SIVAL(*data, 0, 0x0);
2118 if (!strcmp(value, "NetPopup")) {
2120 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2122 SIVAL(*data, 0, 0x00);
2127 if (!strcmp(value, "MajorVersion")) {
2129 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2131 #ifndef EMULATE_WIN2K_HACK /* JERRY */
2140 if (!strcmp(value, "DefaultSpoolDirectory")) {
2143 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2145 *needed = 2*(strlen(string)+1);
2146 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2148 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2150 /* it's done by hand ready to go on the wire */
2151 for (i=0; i<strlen(string); i++) {
2152 (*data)[2*i]=string[i];
2153 (*data)[2*i+1]='\0';
2158 if (!strcmp(value, "Architecture")) {
2159 pstring string="Windows NT x86";
2161 *needed = 2*(strlen(string)+1);
2162 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2164 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2165 for (i=0; i<strlen(string); i++) {
2166 (*data)[2*i]=string[i];
2167 (*data)[2*i+1]='\0';
2172 return WERR_INVALID_PARAM;
2175 /********************************************************************
2176 * spoolss_getprinterdata
2177 ********************************************************************/
2179 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2181 POLICY_HND *handle = &q_u->handle;
2182 UNISTR2 *valuename = &q_u->valuename;
2183 uint32 in_size = q_u->size;
2184 uint32 *type = &r_u->type;
2185 uint32 *out_size = &r_u->size;
2186 uint8 **data = &r_u->data;
2187 uint32 *needed = &r_u->needed;
2190 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2191 NT_PRINTER_INFO_LEVEL *printer = NULL;
2195 * Reminder: when it's a string, the length is in BYTES
2196 * even if UNICODE is negociated.
2201 *out_size = in_size;
2203 /* in case of problem, return some default values */
2208 DEBUG(4,("_spoolss_getprinterdata\n"));
2211 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2212 status = WERR_BADFID;
2216 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2218 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2219 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2222 if ( !get_printer_snum(p,handle, &snum) ) {
2223 status = WERR_BADFID;
2227 status = get_a_printer(&printer, 2, lp_servicename(snum));
2228 if ( !W_ERROR_IS_OK(status) )
2231 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2234 if (*needed > *out_size)
2235 status = WERR_MORE_DATA;
2238 if ( !W_ERROR_IS_OK(status) )
2240 DEBUG(5, ("error: allocating %d\n", *out_size));
2242 /* reply this param doesn't exist */
2245 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2247 free_a_printer( &printer, 2 );
2256 /* cleanup & exit */
2259 free_a_printer( &printer, 2 );
2264 /*********************************************************
2265 Connect to the client machine.
2266 **********************************************************/
2268 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, char *remote_machine)
2270 extern pstring global_myname;
2272 ZERO_STRUCTP(the_cli);
2273 if(cli_initialise(the_cli) == NULL) {
2274 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2278 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2279 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2280 cli_shutdown(the_cli);
2284 if (ismyip(the_cli->dest_ip)) {
2285 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2286 cli_shutdown(the_cli);
2290 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2291 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2292 cli_shutdown(the_cli);
2296 if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
2297 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2302 the_cli->protocol = PROTOCOL_NT1;
2304 if (!cli_negprot(the_cli)) {
2305 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2306 cli_shutdown(the_cli);
2310 if (the_cli->protocol != PROTOCOL_NT1) {
2311 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2312 cli_shutdown(the_cli);
2317 * Do an anonymous session setup.
2320 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2321 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2322 cli_shutdown(the_cli);
2326 if (!(the_cli->sec_mode & 1)) {
2327 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2328 cli_shutdown(the_cli);
2332 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2333 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2334 cli_shutdown(the_cli);
2339 * Ok - we have an anonymous connection to the IPC$ share.
2340 * Now start the NT Domain stuff :-).
2343 if(cli_nt_session_open(the_cli, PIPE_SPOOLSS) == False) {
2344 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)));
2345 cli_nt_session_close(the_cli);
2346 cli_ulogoff(the_cli);
2347 cli_shutdown(the_cli);
2354 /***************************************************************************
2355 Connect to the client.
2356 ****************************************************************************/
2358 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2363 * If it's the first connection, contact the client
2364 * and connect to the IPC$ share anonumously
2366 if (smb_connections==0) {
2367 fstring unix_printer;
2369 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2371 if(!spoolss_connect_to_client(¬ify_cli, unix_printer))
2374 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2375 /* Tell the connections db we're now interested in printer
2376 * notify messages. */
2377 register_message_flags( True, FLAG_MSG_PRINTING );
2382 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2385 if (!W_ERROR_IS_OK(result))
2386 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2387 dos_errstr(result)));
2389 return (W_ERROR_IS_OK(result));
2392 /********************************************************************
2394 * ReplyFindFirstPrinterChangeNotifyEx
2396 * before replying OK: status=0 a rpc call is made to the workstation
2397 * asking ReplyOpenPrinter
2399 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2400 * called from api_spoolss_rffpcnex
2401 ********************************************************************/
2403 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2405 POLICY_HND *handle = &q_u->handle;
2406 uint32 flags = q_u->flags;
2407 uint32 options = q_u->options;
2408 UNISTR2 *localmachine = &q_u->localmachine;
2409 uint32 printerlocal = q_u->printerlocal;
2410 SPOOL_NOTIFY_OPTION *option = q_u->option;
2412 /* store the notify value in the printer struct */
2414 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2417 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2421 Printer->notify.flags=flags;
2422 Printer->notify.options=options;
2423 Printer->notify.printerlocal=printerlocal;
2425 if (Printer->notify.option)
2426 free_spool_notify_option(&Printer->notify.option);
2428 Printer->notify.option=dup_spool_notify_option(option);
2430 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2431 sizeof(Printer->notify.localmachine)-1);
2433 /* Connect to the client machine and send a ReplyOpenPrinter */
2435 if(!srv_spoolss_replyopenprinter(Printer->notify.localmachine,
2436 Printer->notify.printerlocal, 1,
2437 &Printer->notify.client_hnd))
2438 return WERR_SERVER_UNAVAILABLE;
2440 Printer->notify.client_connected=True;
2445 /*******************************************************************
2446 * fill a notify_info_data with the servername
2447 ********************************************************************/
2449 void spoolss_notify_server_name(int snum,
2450 SPOOL_NOTIFY_INFO_DATA *data,
2451 print_queue_struct *queue,
2452 NT_PRINTER_INFO_LEVEL *printer,
2453 TALLOC_CTX *mem_ctx)
2455 pstring temp_name, temp;
2458 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2460 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2462 data->notify_data.data.length = len;
2463 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2465 if (!data->notify_data.data.string) {
2466 data->notify_data.data.length = 0;
2470 memcpy(data->notify_data.data.string, temp, len);
2473 /*******************************************************************
2474 * fill a notify_info_data with the printername (not including the servername).
2475 ********************************************************************/
2477 void spoolss_notify_printer_name(int snum,
2478 SPOOL_NOTIFY_INFO_DATA *data,
2479 print_queue_struct *queue,
2480 NT_PRINTER_INFO_LEVEL *printer,
2481 TALLOC_CTX *mem_ctx)
2486 /* the notify name should not contain the \\server\ part */
2487 char *p = strrchr(printer->info_2->printername, '\\');
2490 p = printer->info_2->printername;
2495 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2497 data->notify_data.data.length = len;
2498 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2500 if (!data->notify_data.data.string) {
2501 data->notify_data.data.length = 0;
2505 memcpy(data->notify_data.data.string, temp, len);
2508 /*******************************************************************
2509 * fill a notify_info_data with the servicename
2510 ********************************************************************/
2512 void spoolss_notify_share_name(int snum,
2513 SPOOL_NOTIFY_INFO_DATA *data,
2514 print_queue_struct *queue,
2515 NT_PRINTER_INFO_LEVEL *printer,
2516 TALLOC_CTX *mem_ctx)
2521 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2523 data->notify_data.data.length = len;
2524 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2526 if (!data->notify_data.data.string) {
2527 data->notify_data.data.length = 0;
2531 memcpy(data->notify_data.data.string, temp, len);
2534 /*******************************************************************
2535 * fill a notify_info_data with the port name
2536 ********************************************************************/
2538 void spoolss_notify_port_name(int snum,
2539 SPOOL_NOTIFY_INFO_DATA *data,
2540 print_queue_struct *queue,
2541 NT_PRINTER_INFO_LEVEL *printer,
2542 TALLOC_CTX *mem_ctx)
2547 /* even if it's strange, that's consistant in all the code */
2549 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2551 data->notify_data.data.length = len;
2552 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2554 if (!data->notify_data.data.string) {
2555 data->notify_data.data.length = 0;
2559 memcpy(data->notify_data.data.string, temp, len);
2562 /*******************************************************************
2563 * fill a notify_info_data with the printername
2564 * but it doesn't exist, have to see what to do
2565 ********************************************************************/
2567 void spoolss_notify_driver_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)
2576 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2578 data->notify_data.data.length = len;
2579 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2581 if (!data->notify_data.data.string) {
2582 data->notify_data.data.length = 0;
2586 memcpy(data->notify_data.data.string, temp, len);
2589 /*******************************************************************
2590 * fill a notify_info_data with the comment
2591 ********************************************************************/
2593 void spoolss_notify_comment(int snum,
2594 SPOOL_NOTIFY_INFO_DATA *data,
2595 print_queue_struct *queue,
2596 NT_PRINTER_INFO_LEVEL *printer,
2597 TALLOC_CTX *mem_ctx)
2602 if (*printer->info_2->comment == '\0')
2603 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2605 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2607 data->notify_data.data.length = len;
2608 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2610 if (!data->notify_data.data.string) {
2611 data->notify_data.data.length = 0;
2615 memcpy(data->notify_data.data.string, temp, len);
2618 /*******************************************************************
2619 * fill a notify_info_data with the comment
2620 * location = "Room 1, floor 2, building 3"
2621 ********************************************************************/
2623 void spoolss_notify_location(int snum,
2624 SPOOL_NOTIFY_INFO_DATA *data,
2625 print_queue_struct *queue,
2626 NT_PRINTER_INFO_LEVEL *printer,
2627 TALLOC_CTX *mem_ctx)
2632 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2634 data->notify_data.data.length = len;
2635 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2637 if (!data->notify_data.data.string) {
2638 data->notify_data.data.length = 0;
2642 memcpy(data->notify_data.data.string, temp, len);
2645 /*******************************************************************
2646 * fill a notify_info_data with the device mode
2647 * jfm:xxxx don't to it for know but that's a real problem !!!
2648 ********************************************************************/
2650 static void spoolss_notify_devmode(int snum,
2651 SPOOL_NOTIFY_INFO_DATA *data,
2652 print_queue_struct *queue,
2653 NT_PRINTER_INFO_LEVEL *printer,
2654 TALLOC_CTX *mem_ctx)
2658 /*******************************************************************
2659 * fill a notify_info_data with the separator file name
2660 ********************************************************************/
2662 void spoolss_notify_sepfile(int snum,
2663 SPOOL_NOTIFY_INFO_DATA *data,
2664 print_queue_struct *queue,
2665 NT_PRINTER_INFO_LEVEL *printer,
2666 TALLOC_CTX *mem_ctx)
2671 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2673 data->notify_data.data.length = len;
2674 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2676 if (!data->notify_data.data.string) {
2677 data->notify_data.data.length = 0;
2681 memcpy(data->notify_data.data.string, temp, len);
2684 /*******************************************************************
2685 * fill a notify_info_data with the print processor
2686 * jfm:xxxx return always winprint to indicate we don't do anything to it
2687 ********************************************************************/
2689 void spoolss_notify_print_processor(int snum,
2690 SPOOL_NOTIFY_INFO_DATA *data,
2691 print_queue_struct *queue,
2692 NT_PRINTER_INFO_LEVEL *printer,
2693 TALLOC_CTX *mem_ctx)
2698 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2700 data->notify_data.data.length = len;
2701 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2703 if (!data->notify_data.data.string) {
2704 data->notify_data.data.length = 0;
2708 memcpy(data->notify_data.data.string, temp, len);
2711 /*******************************************************************
2712 * fill a notify_info_data with the print processor options
2713 * jfm:xxxx send an empty string
2714 ********************************************************************/
2716 void spoolss_notify_parameters(int snum,
2717 SPOOL_NOTIFY_INFO_DATA *data,
2718 print_queue_struct *queue,
2719 NT_PRINTER_INFO_LEVEL *printer,
2720 TALLOC_CTX *mem_ctx)
2725 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2727 data->notify_data.data.length = len;
2728 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2730 if (!data->notify_data.data.string) {
2731 data->notify_data.data.length = 0;
2735 memcpy(data->notify_data.data.string, temp, len);
2738 /*******************************************************************
2739 * fill a notify_info_data with the data type
2740 * jfm:xxxx always send RAW as data type
2741 ********************************************************************/
2743 void spoolss_notify_datatype(int snum,
2744 SPOOL_NOTIFY_INFO_DATA *data,
2745 print_queue_struct *queue,
2746 NT_PRINTER_INFO_LEVEL *printer,
2747 TALLOC_CTX *mem_ctx)
2752 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2754 data->notify_data.data.length = len;
2755 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2757 if (!data->notify_data.data.string) {
2758 data->notify_data.data.length = 0;
2762 memcpy(data->notify_data.data.string, temp, len);
2765 /*******************************************************************
2766 * fill a notify_info_data with the security descriptor
2767 * jfm:xxxx send an null pointer to say no security desc
2768 * have to implement security before !
2769 ********************************************************************/
2771 static void spoolss_notify_security_desc(int snum,
2772 SPOOL_NOTIFY_INFO_DATA *data,
2773 print_queue_struct *queue,
2774 NT_PRINTER_INFO_LEVEL *printer,
2775 TALLOC_CTX *mem_ctx)
2777 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2778 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2781 /*******************************************************************
2782 * fill a notify_info_data with the attributes
2783 * jfm:xxxx a samba printer is always shared
2784 ********************************************************************/
2786 void spoolss_notify_attributes(int snum,
2787 SPOOL_NOTIFY_INFO_DATA *data,
2788 print_queue_struct *queue,
2789 NT_PRINTER_INFO_LEVEL *printer,
2790 TALLOC_CTX *mem_ctx)
2792 data->notify_data.value[0] = printer->info_2->attributes;
2793 data->notify_data.value[1] = 0;
2796 /*******************************************************************
2797 * fill a notify_info_data with the priority
2798 ********************************************************************/
2800 static void spoolss_notify_priority(int snum,
2801 SPOOL_NOTIFY_INFO_DATA *data,
2802 print_queue_struct *queue,
2803 NT_PRINTER_INFO_LEVEL *printer,
2804 TALLOC_CTX *mem_ctx)
2806 data->notify_data.value[0] = printer->info_2->priority;
2807 data->notify_data.value[1] = 0;
2810 /*******************************************************************
2811 * fill a notify_info_data with the default priority
2812 ********************************************************************/
2814 static void spoolss_notify_default_priority(int snum,
2815 SPOOL_NOTIFY_INFO_DATA *data,
2816 print_queue_struct *queue,
2817 NT_PRINTER_INFO_LEVEL *printer,
2818 TALLOC_CTX *mem_ctx)
2820 data->notify_data.value[0] = printer->info_2->default_priority;
2821 data->notify_data.value[1] = 0;
2824 /*******************************************************************
2825 * fill a notify_info_data with the start time
2826 ********************************************************************/
2828 static void spoolss_notify_start_time(int snum,
2829 SPOOL_NOTIFY_INFO_DATA *data,
2830 print_queue_struct *queue,
2831 NT_PRINTER_INFO_LEVEL *printer,
2832 TALLOC_CTX *mem_ctx)
2834 data->notify_data.value[0] = printer->info_2->starttime;
2835 data->notify_data.value[1] = 0;
2838 /*******************************************************************
2839 * fill a notify_info_data with the until time
2840 ********************************************************************/
2842 static void spoolss_notify_until_time(int snum,
2843 SPOOL_NOTIFY_INFO_DATA *data,
2844 print_queue_struct *queue,
2845 NT_PRINTER_INFO_LEVEL *printer,
2846 TALLOC_CTX *mem_ctx)
2848 data->notify_data.value[0] = printer->info_2->untiltime;
2849 data->notify_data.value[1] = 0;
2852 /*******************************************************************
2853 * fill a notify_info_data with the status
2854 ********************************************************************/
2856 static void spoolss_notify_status(int snum,
2857 SPOOL_NOTIFY_INFO_DATA *data,
2858 print_queue_struct *queue,
2859 NT_PRINTER_INFO_LEVEL *printer,
2860 TALLOC_CTX *mem_ctx)
2862 print_status_struct status;
2864 print_queue_length(snum, &status);
2865 data->notify_data.value[0]=(uint32) status.status;
2866 data->notify_data.value[1] = 0;
2869 /*******************************************************************
2870 * fill a notify_info_data with the number of jobs queued
2871 ********************************************************************/
2873 void spoolss_notify_cjobs(int snum,
2874 SPOOL_NOTIFY_INFO_DATA *data,
2875 print_queue_struct *queue,
2876 NT_PRINTER_INFO_LEVEL *printer,
2877 TALLOC_CTX *mem_ctx)
2879 data->notify_data.value[0] = print_queue_length(snum, NULL);
2880 data->notify_data.value[1] = 0;
2883 /*******************************************************************
2884 * fill a notify_info_data with the average ppm
2885 ********************************************************************/
2887 static void spoolss_notify_average_ppm(int snum,
2888 SPOOL_NOTIFY_INFO_DATA *data,
2889 print_queue_struct *queue,
2890 NT_PRINTER_INFO_LEVEL *printer,
2891 TALLOC_CTX *mem_ctx)
2893 /* always respond 8 pages per minutes */
2894 /* a little hard ! */
2895 data->notify_data.value[0] = printer->info_2->averageppm;
2896 data->notify_data.value[1] = 0;
2899 /*******************************************************************
2900 * fill a notify_info_data with username
2901 ********************************************************************/
2903 static void spoolss_notify_username(int snum,
2904 SPOOL_NOTIFY_INFO_DATA *data,
2905 print_queue_struct *queue,
2906 NT_PRINTER_INFO_LEVEL *printer,
2907 TALLOC_CTX *mem_ctx)
2912 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2914 data->notify_data.data.length = len;
2915 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2917 if (!data->notify_data.data.string) {
2918 data->notify_data.data.length = 0;
2922 memcpy(data->notify_data.data.string, temp, len);
2925 /*******************************************************************
2926 * fill a notify_info_data with job status
2927 ********************************************************************/
2929 static void spoolss_notify_job_status(int snum,
2930 SPOOL_NOTIFY_INFO_DATA *data,
2931 print_queue_struct *queue,
2932 NT_PRINTER_INFO_LEVEL *printer,
2933 TALLOC_CTX *mem_ctx)
2935 data->notify_data.value[0]=nt_printj_status(queue->status);
2936 data->notify_data.value[1] = 0;
2939 /*******************************************************************
2940 * fill a notify_info_data with job name
2941 ********************************************************************/
2943 static void spoolss_notify_job_name(int snum,
2944 SPOOL_NOTIFY_INFO_DATA *data,
2945 print_queue_struct *queue,
2946 NT_PRINTER_INFO_LEVEL *printer,
2947 TALLOC_CTX *mem_ctx)
2952 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
2954 data->notify_data.data.length = len;
2955 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2957 if (!data->notify_data.data.string) {
2958 data->notify_data.data.length = 0;
2962 memcpy(data->notify_data.data.string, temp, len);
2965 /*******************************************************************
2966 * fill a notify_info_data with job status
2967 ********************************************************************/
2969 static void spoolss_notify_job_status_string(int snum,
2970 SPOOL_NOTIFY_INFO_DATA *data,
2971 print_queue_struct *queue,
2972 NT_PRINTER_INFO_LEVEL *printer,
2973 TALLOC_CTX *mem_ctx)
2976 * Now we're returning job status codes we just return a "" here. JRA.
2983 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2986 switch (queue->status) {
2991 p = ""; /* NT provides the paused string */
3000 #endif /* NO LONGER NEEDED. */
3002 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3004 data->notify_data.data.length = len;
3005 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3007 if (!data->notify_data.data.string) {
3008 data->notify_data.data.length = 0;
3012 memcpy(data->notify_data.data.string, temp, len);
3015 /*******************************************************************
3016 * fill a notify_info_data with job time
3017 ********************************************************************/
3019 static void spoolss_notify_job_time(int snum,
3020 SPOOL_NOTIFY_INFO_DATA *data,
3021 print_queue_struct *queue,
3022 NT_PRINTER_INFO_LEVEL *printer,
3023 TALLOC_CTX *mem_ctx)
3025 data->notify_data.value[0]=0x0;
3026 data->notify_data.value[1]=0;
3029 /*******************************************************************
3030 * fill a notify_info_data with job size
3031 ********************************************************************/
3033 static void spoolss_notify_job_size(int snum,
3034 SPOOL_NOTIFY_INFO_DATA *data,
3035 print_queue_struct *queue,
3036 NT_PRINTER_INFO_LEVEL *printer,
3037 TALLOC_CTX *mem_ctx)
3039 data->notify_data.value[0]=queue->size;
3040 data->notify_data.value[1]=0;
3043 /*******************************************************************
3044 * fill a notify_info_data with page info
3045 ********************************************************************/
3046 static void spoolss_notify_total_pages(int snum,
3047 SPOOL_NOTIFY_INFO_DATA *data,
3048 print_queue_struct *queue,
3049 NT_PRINTER_INFO_LEVEL *printer,
3050 TALLOC_CTX *mem_ctx)
3052 data->notify_data.value[0]=queue->page_count;
3053 data->notify_data.value[1]=0;
3056 /*******************************************************************
3057 * fill a notify_info_data with pages printed info.
3058 ********************************************************************/
3059 static void spoolss_notify_pages_printed(int snum,
3060 SPOOL_NOTIFY_INFO_DATA *data,
3061 print_queue_struct *queue,
3062 NT_PRINTER_INFO_LEVEL *printer,
3063 TALLOC_CTX *mem_ctx)
3065 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3066 data->notify_data.value[1]=0;
3069 /*******************************************************************
3070 Fill a notify_info_data with job position.
3071 ********************************************************************/
3073 static void spoolss_notify_job_position(int snum,
3074 SPOOL_NOTIFY_INFO_DATA *data,
3075 print_queue_struct *queue,
3076 NT_PRINTER_INFO_LEVEL *printer,
3077 TALLOC_CTX *mem_ctx)
3079 data->notify_data.value[0]=queue->job;
3080 data->notify_data.value[1]=0;
3083 /*******************************************************************
3084 Fill a notify_info_data with submitted time.
3085 ********************************************************************/
3087 static void spoolss_notify_submitted_time(int snum,
3088 SPOOL_NOTIFY_INFO_DATA *data,
3089 print_queue_struct *queue,
3090 NT_PRINTER_INFO_LEVEL *printer,
3091 TALLOC_CTX *mem_ctx)
3098 t=gmtime(&queue->time);
3100 len = sizeof(SYSTEMTIME);
3102 data->notify_data.data.length = len;
3103 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3105 if (!data->notify_data.data.string) {
3106 data->notify_data.data.length = 0;
3110 make_systemtime(&st, t);
3113 * Systemtime must be linearized as a set of UINT16's.
3114 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3117 p = (char *)data->notify_data.data.string;
3118 SSVAL(p, 0, st.year);
3119 SSVAL(p, 2, st.month);
3120 SSVAL(p, 4, st.dayofweek);
3121 SSVAL(p, 6, st.day);
3122 SSVAL(p, 8, st.hour);
3123 SSVAL(p, 10, st.minute);
3124 SSVAL(p, 12, st.second);
3125 SSVAL(p, 14, st.milliseconds);
3128 struct s_notify_info_data_table
3134 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3135 print_queue_struct *queue,
3136 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3139 /* A table describing the various print notification constants and
3140 whether the notification data is a pointer to a variable sized
3141 buffer, a one value uint32 or a two value uint32. */
3143 struct s_notify_info_data_table notify_info_data_table[] =
3145 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3146 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3147 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3148 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3149 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3150 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3151 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3152 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3153 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3154 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3155 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3156 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3157 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3158 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3159 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3160 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3161 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3162 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3163 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3164 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3165 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3166 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3167 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3168 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3169 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3170 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3171 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3172 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3173 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3174 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3175 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3176 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3177 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3178 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3179 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3180 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3181 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3182 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3183 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3184 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3185 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3186 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3187 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3188 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3189 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3190 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3191 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3192 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3193 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3196 /*******************************************************************
3197 Return the size of info_data structure.
3198 ********************************************************************/
3200 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3204 for (i = 0; i < sizeof(notify_info_data_table); i++)
3206 if ( (notify_info_data_table[i].type == type)
3207 && (notify_info_data_table[i].field == field) )
3209 switch(notify_info_data_table[i].size)
3211 case NOTIFY_ONE_VALUE:
3212 case NOTIFY_TWO_VALUE:
3217 /* The only pointer notify data I have seen on
3218 the wire is the submitted time and this has
3219 the notify size set to 4. -tpot */
3221 case NOTIFY_POINTER:
3224 case NOTIFY_SECDESC:
3230 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3235 /*******************************************************************
3236 Return the type of notify_info_data.
3237 ********************************************************************/
3239 static int type_of_notify_info_data(uint16 type, uint16 field)
3243 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3244 if (notify_info_data_table[i].type == type &&
3245 notify_info_data_table[i].field == field)
3246 return notify_info_data_table[i].size;
3252 /****************************************************************************
3253 ****************************************************************************/
3255 static int search_notify(uint16 type, uint16 field, int *value)
3259 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3260 if (notify_info_data_table[i].type == type &&
3261 notify_info_data_table[i].field == field &&
3262 notify_info_data_table[i].fn != NULL) {
3271 /****************************************************************************
3272 ****************************************************************************/
3274 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3276 info_data->type = type;
3277 info_data->field = field;
3278 info_data->reserved = 0;
3280 info_data->size = size_of_notify_info_data(type, field);
3281 info_data->enc_type = type_of_notify_info_data(type, field);
3288 /*******************************************************************
3290 * fill a notify_info struct with info asked
3292 ********************************************************************/
3294 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
3295 snum, SPOOL_NOTIFY_OPTION_TYPE
3296 *option_type, uint32 id,
3297 TALLOC_CTX *mem_ctx)
3303 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3304 NT_PRINTER_INFO_LEVEL *printer = NULL;
3305 print_queue_struct *queue=NULL;
3307 type=option_type->type;
3309 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3310 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3311 option_type->count, lp_servicename(snum)));
3313 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3316 for(field_num=0; field_num<option_type->count; field_num++)
3318 field = option_type->fields[field_num];
3320 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3322 if (!search_notify(type, field, &j) )
3325 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
3327 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3333 current_data = &info->data[info->count];
3335 construct_info_data(current_data, type, field, id);
3337 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3338 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3340 notify_info_data_table[j].fn(snum, current_data, queue,
3346 free_a_printer(&printer, 2);
3350 /*******************************************************************
3352 * fill a notify_info struct with info asked
3354 ********************************************************************/
3356 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3357 SPOOL_NOTIFY_INFO *info,
3358 NT_PRINTER_INFO_LEVEL *printer,
3359 int snum, SPOOL_NOTIFY_OPTION_TYPE
3360 *option_type, uint32 id,
3361 TALLOC_CTX *mem_ctx)
3367 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3369 DEBUG(4,("construct_notify_jobs_info\n"));
3371 type = option_type->type;
3373 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3374 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3375 option_type->count));
3377 for(field_num=0; field_num<option_type->count; field_num++) {
3378 field = option_type->fields[field_num];
3380 if (!search_notify(type, field, &j) )
3383 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3384 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3387 else info->data = tid;
3389 current_data=&(info->data[info->count]);
3391 construct_info_data(current_data, type, field, id);
3392 notify_info_data_table[j].fn(snum, current_data, queue,
3401 * JFM: The enumeration is not that simple, it's even non obvious.
3403 * let's take an example: I want to monitor the PRINTER SERVER for
3404 * the printer's name and the number of jobs currently queued.
3405 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3406 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3408 * I have 3 printers on the back of my server.
3410 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3413 * 1 printer 1 name 1
3414 * 2 printer 1 cjob 1
3415 * 3 printer 2 name 2
3416 * 4 printer 2 cjob 2
3417 * 5 printer 3 name 3
3418 * 6 printer 3 name 3
3420 * that's the print server case, the printer case is even worse.
3423 /*******************************************************************
3425 * enumerate all printers on the printserver
3426 * fill a notify_info struct with info asked
3428 ********************************************************************/
3430 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3431 SPOOL_NOTIFY_INFO *info,
3432 TALLOC_CTX *mem_ctx)
3435 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3436 int n_services=lp_numservices();
3439 SPOOL_NOTIFY_OPTION *option;
3440 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3442 DEBUG(4,("printserver_notify_info\n"));
3447 option=Printer->notify.option;
3453 for (i=0; i<option->count; i++) {
3454 option_type=&(option->ctr.type[i]);
3456 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3459 for (snum=0; snum<n_services; snum++)
3461 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3462 construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
3468 * Debugging information, don't delete.
3471 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3472 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3473 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3475 for (i=0; i<info->count; i++) {
3476 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3477 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3478 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3485 /*******************************************************************
3487 * fill a notify_info struct with info asked
3489 ********************************************************************/
3491 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3492 TALLOC_CTX *mem_ctx)
3495 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3498 SPOOL_NOTIFY_OPTION *option;
3499 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3501 print_queue_struct *queue=NULL;
3502 print_status_struct status;
3504 DEBUG(4,("printer_notify_info\n"));
3509 option=Printer->notify.option;
3515 get_printer_snum(p, hnd, &snum);
3517 for (i=0; i<option->count; i++) {
3518 option_type=&option->ctr.type[i];
3520 switch ( option_type->type ) {
3521 case PRINTER_NOTIFY_TYPE:
3522 if(construct_notify_printer_info(info, snum,
3528 case JOB_NOTIFY_TYPE: {
3529 NT_PRINTER_INFO_LEVEL *printer = NULL;
3531 count = print_queue_status(snum, &queue, &status);
3533 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3534 lp_servicename(snum))))
3537 for (j=0; j<count; j++) {
3538 construct_notify_jobs_info(&queue[j], info,
3545 free_a_printer(&printer, 2);
3555 * Debugging information, don't delete.
3558 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3559 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3560 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3562 for (i=0; i<info->count; i++) {
3563 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3564 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3565 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3571 /********************************************************************
3573 ********************************************************************/
3575 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3577 POLICY_HND *handle = &q_u->handle;
3578 SPOOL_NOTIFY_INFO *info = &r_u->info;
3580 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3581 WERROR result = WERR_BADFID;
3583 /* we always have a NOTIFY_INFO struct */
3587 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3588 OUR_HANDLE(handle)));
3592 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3595 * We are now using the change value, and
3596 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3597 * I don't have a global notification system, I'm sending back all the
3598 * informations even when _NOTHING_ has changed.
3601 /* We need to keep track of the change value to send back in
3602 RRPCN replies otherwise our updates are ignored. */
3604 if (Printer->notify.client_connected) {
3605 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3606 Printer->notify.change = q_u->change;
3609 /* just ignore the SPOOL_NOTIFY_OPTION */
3611 switch (Printer->printer_type) {
3612 case PRINTER_HANDLE_IS_PRINTSERVER:
3613 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3616 case PRINTER_HANDLE_IS_PRINTER:
3617 result = printer_notify_info(p, handle, info, p->mem_ctx);
3625 /********************************************************************
3626 * construct_printer_info_0
3627 * fill a printer_info_0 struct
3628 ********************************************************************/
3630 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3634 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3635 counter_printer_0 *session_counter;
3636 uint32 global_counter;
3639 print_status_struct status;
3641 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3644 count = print_queue_length(snum, &status);
3646 /* check if we already have a counter for this printer */
3647 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3649 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3650 if (session_counter->snum == snum)
3654 /* it's the first time, add it to the list */
3655 if (session_counter==NULL) {
3656 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3657 free_a_printer(&ntprinter, 2);
3660 ZERO_STRUCTP(session_counter);
3661 session_counter->snum=snum;
3662 session_counter->counter=0;
3663 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3667 session_counter->counter++;
3670 * the global_counter should be stored in a TDB as it's common to all the clients
3671 * and should be zeroed on samba startup
3673 global_counter=session_counter->counter;
3675 pstrcpy(chaine,ntprinter->info_2->printername);
3677 init_unistr(&printer->printername, chaine);
3679 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3680 init_unistr(&printer->servername, chaine);
3682 printer->cjobs = count;
3683 printer->total_jobs = 0;
3684 printer->total_bytes = 0;
3686 setuptime = (time_t)ntprinter->info_2->setuptime;
3687 t=gmtime(&setuptime);
3689 printer->year = t->tm_year+1900;
3690 printer->month = t->tm_mon+1;
3691 printer->dayofweek = t->tm_wday;
3692 printer->day = t->tm_mday;
3693 printer->hour = t->tm_hour;
3694 printer->minute = t->tm_min;
3695 printer->second = t->tm_sec;
3696 printer->milliseconds = 0;
3698 printer->global_counter = global_counter;
3699 printer->total_pages = 0;
3700 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3701 printer->major_version = 0x0004; /* NT 4 */
3702 printer->build_version = 0x0565; /* build 1381 */
3704 printer->major_version = 0x0005; /* NT 5 */
3705 printer->build_version = 0x0893; /* build 2195 */
3707 printer->unknown7 = 0x1;
3708 printer->unknown8 = 0x0;
3709 printer->unknown9 = 0x0;
3710 printer->session_counter = session_counter->counter;
3711 printer->unknown11 = 0x0;
3712 printer->printer_errors = 0x0; /* number of print failure */
3713 printer->unknown13 = 0x0;
3714 printer->unknown14 = 0x1;
3715 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3716 printer->unknown16 = 0x0;
3717 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3718 printer->unknown18 = 0x0;
3719 printer->status = nt_printq_status(status.status);
3720 printer->unknown20 = 0x0;
3721 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3722 printer->unknown22 = 0x0;
3723 printer->unknown23 = 0x6; /* 6 ???*/
3724 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3725 printer->unknown25 = 0;
3726 printer->unknown26 = 0;
3727 printer->unknown27 = 0;
3728 printer->unknown28 = 0;
3729 printer->unknown29 = 0;
3731 free_a_printer(&ntprinter,2);
3735 /********************************************************************
3736 * construct_printer_info_1
3737 * fill a printer_info_1 struct
3738 ********************************************************************/
3739 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3743 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3745 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3748 printer->flags=flags;
3750 if (*ntprinter->info_2->comment == '\0') {
3751 init_unistr(&printer->comment, lp_comment(snum));
3752 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3753 ntprinter->info_2->drivername, lp_comment(snum));
3756 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3757 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3758 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3761 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3763 init_unistr(&printer->description, chaine);
3764 init_unistr(&printer->name, chaine2);
3766 free_a_printer(&ntprinter,2);
3771 /****************************************************************************
3772 Free a DEVMODE struct.
3773 ****************************************************************************/
3775 static void free_dev_mode(DEVICEMODE *dev)
3780 SAFE_FREE(dev->private);
3784 /****************************************************************************
3785 Create a DEVMODE struct. Returns malloced memory.
3786 ****************************************************************************/
3788 DEVICEMODE *construct_dev_mode(int snum)
3792 NT_PRINTER_INFO_LEVEL *printer = NULL;
3793 NT_DEVICEMODE *ntdevmode = NULL;
3794 DEVICEMODE *devmode = NULL;
3796 DEBUG(7,("construct_dev_mode\n"));
3798 DEBUGADD(8,("getting printer characteristics\n"));
3800 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3801 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3805 ZERO_STRUCTP(devmode);
3807 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3810 if (printer->info_2->devmode)
3811 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
3813 if (ntdevmode == NULL) {
3814 DEBUG(5, ("BONG! There was no device mode!\n"));
3818 DEBUGADD(8,("loading DEVICEMODE\n"));
3820 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
3821 init_unistr(&devmode->devicename, adevice);
3823 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
3824 init_unistr(&devmode->formname, aform);
3826 devmode->specversion = ntdevmode->specversion;
3827 devmode->driverversion = ntdevmode->driverversion;
3828 devmode->size = ntdevmode->size;
3829 devmode->driverextra = ntdevmode->driverextra;
3830 devmode->fields = ntdevmode->fields;
3832 devmode->orientation = ntdevmode->orientation;
3833 devmode->papersize = ntdevmode->papersize;
3834 devmode->paperlength = ntdevmode->paperlength;
3835 devmode->paperwidth = ntdevmode->paperwidth;
3836 devmode->scale = ntdevmode->scale;
3837 devmode->copies = ntdevmode->copies;
3838 devmode->defaultsource = ntdevmode->defaultsource;
3839 devmode->printquality = ntdevmode->printquality;
3840 devmode->color = ntdevmode->color;
3841 devmode->duplex = ntdevmode->duplex;
3842 devmode->yresolution = ntdevmode->yresolution;
3843 devmode->ttoption = ntdevmode->ttoption;
3844 devmode->collate = ntdevmode->collate;
3845 devmode->icmmethod = ntdevmode->icmmethod;
3846 devmode->icmintent = ntdevmode->icmintent;
3847 devmode->mediatype = ntdevmode->mediatype;
3848 devmode->dithertype = ntdevmode->dithertype;
3850 if (ntdevmode->private != NULL) {
3851 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3855 free_nt_devicemode(&ntdevmode);
3856 free_a_printer(&printer,2);
3863 free_nt_devicemode(&ntdevmode);
3865 free_a_printer(&printer,2);
3866 free_dev_mode(devmode);
3871 /********************************************************************
3872 * construct_printer_info_2
3873 * fill a printer_info_2 struct
3874 ********************************************************************/
3876 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3879 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3881 print_status_struct status;
3883 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3886 count = print_queue_length(snum, &status);
3888 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3889 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3890 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3891 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3892 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3894 if (*ntprinter->info_2->comment == '\0')
3895 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3897 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3899 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3900 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3901 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3902 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3903 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3905 printer->attributes = ntprinter->info_2->attributes;
3907 printer->priority = ntprinter->info_2->priority; /* priority */
3908 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3909 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3910 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3911 printer->status = nt_printq_status(status.status); /* status */
3912 printer->cjobs = count; /* jobs */
3913 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3915 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3916 DEBUG(8, ("Returning NULL Devicemode!\n"));
3919 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3920 /* steal the printer info sec_desc structure. [badly done]. */
3921 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3922 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3923 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3924 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3927 printer->secdesc = NULL;
3930 free_a_printer(&ntprinter, 2);
3934 /********************************************************************
3935 * construct_printer_info_3
3936 * fill a printer_info_3 struct
3937 ********************************************************************/
3939 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3941 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3942 PRINTER_INFO_3 *printer = NULL;
3944 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3948 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3949 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3953 ZERO_STRUCTP(printer);
3955 printer->flags = 4; /* These are the components of the SD we are returning. */
3956 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3957 /* steal the printer info sec_desc structure. [badly done]. */
3958 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3962 * Set the flags for the components we are returning.
3965 if (printer->secdesc->owner_sid)
3966 printer->flags |= OWNER_SECURITY_INFORMATION;
3968 if (printer->secdesc->grp_sid)
3969 printer->flags |= GROUP_SECURITY_INFORMATION;
3971 if (printer->secdesc->dacl)
3972 printer->flags |= DACL_SECURITY_INFORMATION;
3974 if (printer->secdesc->sacl)
3975 printer->flags |= SACL_SECURITY_INFORMATION;
3978 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
3979 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
3980 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
3983 free_a_printer(&ntprinter, 2);
3985 *pp_printer = printer;
3989 /********************************************************************
3990 * construct_printer_info_4
3991 * fill a printer_info_4 struct
3992 ********************************************************************/
3994 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
3996 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3998 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4001 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4002 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4003 printer->attributes = ntprinter->info_2->attributes;
4005 free_a_printer(&ntprinter, 2);
4009 /********************************************************************
4010 * construct_printer_info_5
4011 * fill a printer_info_5 struct
4012 ********************************************************************/
4014 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
4016 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4018 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4021 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4022 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
4023 printer->attributes = ntprinter->info_2->attributes;
4024 printer->device_not_selected_timeout = 0x3a98;
4025 printer->transmission_retry_timeout = 0xafc8;
4027 free_a_printer(&ntprinter, 2);
4031 /********************************************************************
4032 Spoolss_enumprinters.
4033 ********************************************************************/
4035 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4039 int n_services=lp_numservices();
4040 PRINTER_INFO_1 *tp, *printers=NULL;
4041 PRINTER_INFO_1 current_prt;
4043 DEBUG(4,("enum_all_printers_info_1\n"));
4045 for (snum=0; snum<n_services; snum++) {
4046 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4047 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4049 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
4050 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4051 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4052 SAFE_FREE(printers);
4057 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4059 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4065 /* check the required size. */
4066 for (i=0; i<*returned; i++)
4067 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4069 if (!alloc_buffer_size(buffer, *needed))
4070 return WERR_INSUFFICIENT_BUFFER;
4072 /* fill the buffer with the structures */
4073 for (i=0; i<*returned; i++)
4074 smb_io_printer_info_1("", buffer, &printers[i], 0);
4077 SAFE_FREE(printers);
4079 if (*needed > offered) {
4081 return WERR_INSUFFICIENT_BUFFER;
4087 /********************************************************************
4088 enum_all_printers_info_1_local.
4089 *********************************************************************/
4091 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4093 DEBUG(4,("enum_all_printers_info_1_local\n"));
4095 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4098 /********************************************************************
4099 enum_all_printers_info_1_name.
4100 *********************************************************************/
4102 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4106 DEBUG(4,("enum_all_printers_info_1_name\n"));
4108 if ((name[0] == '\\') && (name[1] == '\\'))
4111 if (is_myname_or_ipaddr(s)) {
4112 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4115 return WERR_INVALID_NAME;
4118 /********************************************************************
4119 enum_all_printers_info_1_remote.
4120 *********************************************************************/
4122 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4124 PRINTER_INFO_1 *printer;
4125 fstring printername;
4128 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4130 /* JFM: currently it's more a place holder than anything else.
4131 * In the spooler world there is a notion of server registration.
4132 * the print servers are registring (sp ?) on the PDC (in the same domain)
4134 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4137 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4142 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4143 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4144 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4146 init_unistr(&printer->description, desc);
4147 init_unistr(&printer->name, printername);
4148 init_unistr(&printer->comment, comment);
4149 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4151 /* check the required size. */
4152 *needed += spoolss_size_printer_info_1(printer);
4154 if (!alloc_buffer_size(buffer, *needed)) {
4156 return WERR_INSUFFICIENT_BUFFER;
4159 /* fill the buffer with the structures */
4160 smb_io_printer_info_1("", buffer, printer, 0);
4165 if (*needed > offered) {
4167 return WERR_INSUFFICIENT_BUFFER;
4173 /********************************************************************
4174 enum_all_printers_info_1_network.
4175 *********************************************************************/
4177 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4181 DEBUG(4,("enum_all_printers_info_1_network\n"));
4183 /* If we respond to a enum_printers level 1 on our name with flags
4184 set to PRINTER_ENUM_REMOTE with a list of printers then these
4185 printers incorrectly appear in the APW browse list.
4186 Specifically the printers for the server appear at the workgroup
4187 level where all the other servers in the domain are
4188 listed. Windows responds to this call with a
4189 WERR_CAN_NOT_COMPLETE so we should do the same. */
4191 if (name[0] == '\\' && name[1] == '\\')
4194 if (is_myname_or_ipaddr(s))
4195 return WERR_CAN_NOT_COMPLETE;
4197 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4200 /********************************************************************
4201 * api_spoolss_enumprinters
4203 * called from api_spoolss_enumprinters (see this to understand)
4204 ********************************************************************/
4206 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4210 int n_services=lp_numservices();
4211 PRINTER_INFO_2 *tp, *printers=NULL;
4212 PRINTER_INFO_2 current_prt;
4214 for (snum=0; snum<n_services; snum++) {
4215 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4216 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4218 if (construct_printer_info_2(¤t_prt, snum)) {
4219 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4220 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4221 SAFE_FREE(printers);
4226 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4227 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4233 /* check the required size. */
4234 for (i=0; i<*returned; i++)
4235 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4237 if (!alloc_buffer_size(buffer, *needed)) {
4238 for (i=0; i<*returned; i++) {
4239 free_devmode(printers[i].devmode);
4241 SAFE_FREE(printers);
4242 return WERR_INSUFFICIENT_BUFFER;
4245 /* fill the buffer with the structures */
4246 for (i=0; i<*returned; i++)
4247 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4250 for (i=0; i<*returned; i++) {
4251 free_devmode(printers[i].devmode);
4253 SAFE_FREE(printers);
4255 if (*needed > offered) {
4257 return WERR_INSUFFICIENT_BUFFER;
4263 /********************************************************************
4264 * handle enumeration of printers at level 1
4265 ********************************************************************/
4267 static WERROR enumprinters_level1( uint32 flags, fstring name,
4268 NEW_BUFFER *buffer, uint32 offered,
4269 uint32 *needed, uint32 *returned)
4271 /* Not all the flags are equals */
4273 if (flags & PRINTER_ENUM_LOCAL)
4274 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4276 if (flags & PRINTER_ENUM_NAME)
4277 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4279 if (flags & PRINTER_ENUM_REMOTE)
4280 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4282 if (flags & PRINTER_ENUM_NETWORK)
4283 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4285 return WERR_OK; /* NT4sp5 does that */
4288 /********************************************************************
4289 * handle enumeration of printers at level 2
4290 ********************************************************************/
4292 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4293 NEW_BUFFER *buffer, uint32 offered,
4294 uint32 *needed, uint32 *returned)
4296 char *s = servername;
4298 if (flags & PRINTER_ENUM_LOCAL) {
4299 return enum_all_printers_info_2(buffer, offered, needed, returned);
4302 if (flags & PRINTER_ENUM_NAME) {
4303 if ((servername[0] == '\\') && (servername[1] == '\\'))
4305 if (is_myname_or_ipaddr(s))
4306 return enum_all_printers_info_2(buffer, offered, needed, returned);
4308 return WERR_INVALID_NAME;
4311 if (flags & PRINTER_ENUM_REMOTE)
4312 return WERR_UNKNOWN_LEVEL;
4317 /********************************************************************
4318 * handle enumeration of printers at level 5
4319 ********************************************************************/
4321 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4322 NEW_BUFFER *buffer, uint32 offered,
4323 uint32 *needed, uint32 *returned)
4325 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4329 /********************************************************************
4330 * api_spoolss_enumprinters
4332 * called from api_spoolss_enumprinters (see this to understand)
4333 ********************************************************************/
4335 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4337 uint32 flags = q_u->flags;
4338 UNISTR2 *servername = &q_u->servername;
4339 uint32 level = q_u->level;
4340 NEW_BUFFER *buffer = NULL;
4341 uint32 offered = q_u->offered;
4342 uint32 *needed = &r_u->needed;
4343 uint32 *returned = &r_u->returned;
4347 /* that's an [in out] buffer */
4348 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4349 buffer = r_u->buffer;
4351 DEBUG(4,("_spoolss_enumprinters\n"));
4358 * flags==PRINTER_ENUM_NAME
4359 * if name=="" then enumerates all printers
4360 * if name!="" then enumerate the printer
4361 * flags==PRINTER_ENUM_REMOTE
4362 * name is NULL, enumerate printers
4363 * Level 2: name!="" enumerates printers, name can't be NULL
4364 * Level 3: doesn't exist
4365 * Level 4: does a local registry lookup
4366 * Level 5: same as Level 2
4369 unistr2_to_ascii(name, servername, sizeof(name)-1);
4374 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4376 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4378 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4383 return WERR_UNKNOWN_LEVEL;
4386 /****************************************************************************
4387 ****************************************************************************/
4389 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4391 PRINTER_INFO_0 *printer=NULL;
4393 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4396 construct_printer_info_0(printer, snum);
4398 /* check the required size. */
4399 *needed += spoolss_size_printer_info_0(printer);
4401 if (!alloc_buffer_size(buffer, *needed)) {
4403 return WERR_INSUFFICIENT_BUFFER;
4406 /* fill the buffer with the structures */
4407 smb_io_printer_info_0("", buffer, printer, 0);
4412 if (*needed > offered) {
4413 return WERR_INSUFFICIENT_BUFFER;
4419 /****************************************************************************
4420 ****************************************************************************/
4422 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4424 PRINTER_INFO_1 *printer=NULL;
4426 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4429 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4431 /* check the required size. */
4432 *needed += spoolss_size_printer_info_1(printer);
4434 if (!alloc_buffer_size(buffer, *needed)) {
4436 return WERR_INSUFFICIENT_BUFFER;
4439 /* fill the buffer with the structures */
4440 smb_io_printer_info_1("", buffer, printer, 0);
4445 if (*needed > offered) {
4446 return WERR_INSUFFICIENT_BUFFER;
4452 /****************************************************************************
4453 ****************************************************************************/
4455 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4457 PRINTER_INFO_2 *printer=NULL;
4459 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4462 construct_printer_info_2(printer, snum);
4464 /* check the required size. */
4465 *needed += spoolss_size_printer_info_2(printer);
4467 if (!alloc_buffer_size(buffer, *needed)) {
4468 free_printer_info_2(printer);
4469 return WERR_INSUFFICIENT_BUFFER;
4472 /* fill the buffer with the structures */
4473 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4474 free_printer_info_2(printer);
4479 free_printer_info_2(printer);
4481 if (*needed > offered) {
4482 return WERR_INSUFFICIENT_BUFFER;
4488 /****************************************************************************
4489 ****************************************************************************/
4491 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4493 PRINTER_INFO_3 *printer=NULL;
4495 if (!construct_printer_info_3(&printer, snum))
4498 /* check the required size. */
4499 *needed += spoolss_size_printer_info_3(printer);
4501 if (!alloc_buffer_size(buffer, *needed)) {
4502 free_printer_info_3(printer);
4503 return WERR_INSUFFICIENT_BUFFER;
4506 /* fill the buffer with the structures */
4507 smb_io_printer_info_3("", buffer, printer, 0);
4510 free_printer_info_3(printer);
4512 if (*needed > offered) {
4513 return WERR_INSUFFICIENT_BUFFER;
4519 /****************************************************************************
4520 ****************************************************************************/
4522 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4524 PRINTER_INFO_4 *printer=NULL;
4526 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4529 if (!construct_printer_info_4(printer, snum))
4532 /* check the required size. */
4533 *needed += spoolss_size_printer_info_4(printer);
4535 if (!alloc_buffer_size(buffer, *needed)) {
4536 free_printer_info_4(printer);
4537 return WERR_INSUFFICIENT_BUFFER;
4540 /* fill the buffer with the structures */
4541 smb_io_printer_info_4("", buffer, printer, 0);
4544 free_printer_info_4(printer);
4546 if (*needed > offered) {
4547 return WERR_INSUFFICIENT_BUFFER;
4553 /****************************************************************************
4554 ****************************************************************************/
4556 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4558 PRINTER_INFO_5 *printer=NULL;
4560 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4563 if (!construct_printer_info_5(printer, snum))
4566 /* check the required size. */
4567 *needed += spoolss_size_printer_info_5(printer);
4569 if (!alloc_buffer_size(buffer, *needed)) {
4570 free_printer_info_5(printer);
4571 return WERR_INSUFFICIENT_BUFFER;
4574 /* fill the buffer with the structures */
4575 smb_io_printer_info_5("", buffer, printer, 0);
4578 free_printer_info_5(printer);
4580 if (*needed > offered) {
4581 return WERR_INSUFFICIENT_BUFFER;
4587 /****************************************************************************
4588 ****************************************************************************/
4590 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4592 POLICY_HND *handle = &q_u->handle;
4593 uint32 level = q_u->level;
4594 NEW_BUFFER *buffer = NULL;
4595 uint32 offered = q_u->offered;
4596 uint32 *needed = &r_u->needed;
4600 /* that's an [in out] buffer */
4601 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4602 buffer = r_u->buffer;
4606 if (!get_printer_snum(p, handle, &snum))
4611 return getprinter_level_0(snum, buffer, offered, needed);
4613 return getprinter_level_1(snum, buffer, offered, needed);
4615 return getprinter_level_2(snum, buffer, offered, needed);
4617 return getprinter_level_3(snum, buffer, offered, needed);
4619 return getprinter_level_4(snum, buffer, offered, needed);
4621 return getprinter_level_5(snum, buffer, offered, needed);
4623 return WERR_UNKNOWN_LEVEL;
4626 /********************************************************************
4627 * fill a DRIVER_INFO_1 struct
4628 ********************************************************************/
4630 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4632 init_unistr( &info->name, driver.info_3->name);
4635 /********************************************************************
4636 * construct_printer_driver_info_1
4637 ********************************************************************/
4639 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4641 NT_PRINTER_INFO_LEVEL *printer = NULL;
4642 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4644 ZERO_STRUCT(driver);
4646 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4647 return WERR_INVALID_PRINTER_NAME;
4649 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4650 return WERR_UNKNOWN_PRINTER_DRIVER;
4652 fill_printer_driver_info_1(info, driver, servername, architecture);
4654 free_a_printer(&printer,2);
4659 /********************************************************************
4660 * construct_printer_driver_info_2
4661 * fill a printer_info_2 struct
4662 ********************************************************************/
4664 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4668 info->version=driver.info_3->cversion;
4670 init_unistr( &info->name, driver.info_3->name );
4671 init_unistr( &info->architecture, driver.info_3->environment );
4674 if (strlen(driver.info_3->driverpath)) {
4675 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4676 init_unistr( &info->driverpath, temp );
4678 init_unistr( &info->driverpath, "" );
4680 if (strlen(driver.info_3->datafile)) {
4681 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4682 init_unistr( &info->datafile, temp );
4684 init_unistr( &info->datafile, "" );
4686 if (strlen(driver.info_3->configfile)) {
4687 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4688 init_unistr( &info->configfile, temp );
4690 init_unistr( &info->configfile, "" );
4693 /********************************************************************
4694 * construct_printer_driver_info_2
4695 * fill a printer_info_2 struct
4696 ********************************************************************/
4698 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4700 NT_PRINTER_INFO_LEVEL *printer = NULL;
4701 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4703 ZERO_STRUCT(printer);
4704 ZERO_STRUCT(driver);
4706 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4707 return WERR_INVALID_PRINTER_NAME;
4709 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4710 return WERR_UNKNOWN_PRINTER_DRIVER;
4712 fill_printer_driver_info_2(info, driver, servername);
4714 free_a_printer(&printer,2);
4719 /********************************************************************
4720 * copy a strings array and convert to UNICODE
4722 * convert an array of ascii string to a UNICODE string
4723 ********************************************************************/
4725 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4733 DEBUG(6,("init_unistr_array\n"));
4744 v = ""; /* hack to handle null lists */
4747 /* hack to allow this to be used in places other than when generating
4748 the list of dependent files */
4751 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4755 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4757 if ( (tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4758 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4766 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4771 (*uni_array)[j]=0x0000;
4774 DEBUGADD(6,("last one:done\n"));
4776 /* return size of array in uint16's */
4781 /********************************************************************
4782 * construct_printer_info_3
4783 * fill a printer_info_3 struct
4784 ********************************************************************/
4786 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4792 info->version=driver.info_3->cversion;
4794 init_unistr( &info->name, driver.info_3->name );
4795 init_unistr( &info->architecture, driver.info_3->environment );
4797 if (strlen(driver.info_3->driverpath)) {
4798 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4799 init_unistr( &info->driverpath, temp );
4801 init_unistr( &info->driverpath, "" );
4803 if (strlen(driver.info_3->datafile)) {
4804 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4805 init_unistr( &info->datafile, temp );
4807 init_unistr( &info->datafile, "" );
4809 if (strlen(driver.info_3->configfile)) {
4810 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4811 init_unistr( &info->configfile, temp );
4813 init_unistr( &info->configfile, "" );
4815 if (strlen(driver.info_3->helpfile)) {
4816 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4817 init_unistr( &info->helpfile, temp );
4819 init_unistr( &info->helpfile, "" );
4821 init_unistr( &info->monitorname, driver.info_3->monitorname );
4822 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4824 info->dependentfiles=NULL;
4825 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4828 /********************************************************************
4829 * construct_printer_info_3
4830 * fill a printer_info_3 struct
4831 ********************************************************************/
4833 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4835 NT_PRINTER_INFO_LEVEL *printer = NULL;
4836 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4838 ZERO_STRUCT(driver);
4840 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4841 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4842 if (!W_ERROR_IS_OK(status))
4843 return WERR_INVALID_PRINTER_NAME;
4845 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4846 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4851 * I put this code in during testing. Helpful when commenting out the
4852 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4853 * as win2k always queries the driver using an infor level of 6.
4854 * I've left it in (but ifdef'd out) because I'll probably
4855 * use it in experimentation again in the future. --jerry 22/01/2002
4858 if (!W_ERROR_IS_OK(status)) {
4860 * Is this a W2k client ?
4863 /* Yes - try again with a WinNT driver. */
4865 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4866 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4870 if (!W_ERROR_IS_OK(status)) {
4871 free_a_printer(&printer,2);
4872 return WERR_UNKNOWN_PRINTER_DRIVER;
4880 fill_printer_driver_info_3(info, driver, servername);
4882 free_a_printer(&printer,2);
4887 /********************************************************************
4888 * construct_printer_info_6
4889 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4890 ********************************************************************/
4892 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4898 memset(&nullstr, '\0', sizeof(fstring));
4900 info->version=driver.info_3->cversion;
4902 init_unistr( &info->name, driver.info_3->name );
4903 init_unistr( &info->architecture, driver.info_3->environment );
4905 if (strlen(driver.info_3->driverpath)) {
4906 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4907 init_unistr( &info->driverpath, temp );
4909 init_unistr( &info->driverpath, "" );
4911 if (strlen(driver.info_3->datafile)) {
4912 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4913 init_unistr( &info->datafile, temp );
4915 init_unistr( &info->datafile, "" );
4917 if (strlen(driver.info_3->configfile)) {
4918 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4919 init_unistr( &info->configfile, temp );
4921 init_unistr( &info->configfile, "" );
4923 if (strlen(driver.info_3->helpfile)) {
4924 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4925 init_unistr( &info->helpfile, temp );
4927 init_unistr( &info->helpfile, "" );
4929 init_unistr( &info->monitorname, driver.info_3->monitorname );
4930 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4932 info->dependentfiles = NULL;
4933 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
4935 info->previousdrivernames=NULL;
4936 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4938 info->driver_date.low=0;
4939 info->driver_date.high=0;
4942 info->driver_version_low=0;
4943 info->driver_version_high=0;
4945 init_unistr( &info->mfgname, "");
4946 init_unistr( &info->oem_url, "");
4947 init_unistr( &info->hardware_id, "");
4948 init_unistr( &info->provider, "");
4951 /********************************************************************
4952 * construct_printer_info_6
4953 * fill a printer_info_6 struct
4954 ********************************************************************/
4956 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
4957 fstring servername, fstring architecture, uint32 version)
4959 NT_PRINTER_INFO_LEVEL *printer = NULL;
4960 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4963 ZERO_STRUCT(driver);
4965 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4967 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4969 if (!W_ERROR_IS_OK(status))
4970 return WERR_INVALID_PRINTER_NAME;
4972 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4974 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4976 if (!W_ERROR_IS_OK(status))
4979 * Is this a W2k client ?
4983 free_a_printer(&printer,2);
4984 return WERR_UNKNOWN_PRINTER_DRIVER;
4987 /* Yes - try again with a WinNT driver. */
4989 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4990 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4991 if (!W_ERROR_IS_OK(status)) {
4992 free_a_printer(&printer,2);
4993 return WERR_UNKNOWN_PRINTER_DRIVER;
4997 fill_printer_driver_info_6(info, driver, servername);
4999 free_a_printer(&printer,2);
5004 /****************************************************************************
5005 ****************************************************************************/
5007 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5009 SAFE_FREE(info->dependentfiles);
5012 /****************************************************************************
5013 ****************************************************************************/
5015 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5017 SAFE_FREE(info->dependentfiles);
5021 /****************************************************************************
5022 ****************************************************************************/
5024 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5026 DRIVER_INFO_1 *info=NULL;
5029 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5032 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5033 if (!W_ERROR_IS_OK(status)) {
5038 /* check the required size. */
5039 *needed += spoolss_size_printer_driver_info_1(info);
5041 if (!alloc_buffer_size(buffer, *needed)) {
5043 return WERR_INSUFFICIENT_BUFFER;
5046 /* fill the buffer with the structures */
5047 smb_io_printer_driver_info_1("", buffer, info, 0);
5052 if (*needed > offered)
5053 return WERR_INSUFFICIENT_BUFFER;
5058 /****************************************************************************
5059 ****************************************************************************/
5061 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5063 DRIVER_INFO_2 *info=NULL;
5066 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5069 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5070 if (!W_ERROR_IS_OK(status)) {
5075 /* check the required size. */
5076 *needed += spoolss_size_printer_driver_info_2(info);
5078 if (!alloc_buffer_size(buffer, *needed)) {
5080 return WERR_INSUFFICIENT_BUFFER;
5083 /* fill the buffer with the structures */
5084 smb_io_printer_driver_info_2("", buffer, info, 0);
5089 if (*needed > offered)
5090 return WERR_INSUFFICIENT_BUFFER;
5095 /****************************************************************************
5096 ****************************************************************************/
5098 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5105 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5106 if (!W_ERROR_IS_OK(status)) {
5110 /* check the required size. */
5111 *needed += spoolss_size_printer_driver_info_3(&info);
5113 if (!alloc_buffer_size(buffer, *needed)) {
5114 free_printer_driver_info_3(&info);
5115 return WERR_INSUFFICIENT_BUFFER;
5118 /* fill the buffer with the structures */
5119 smb_io_printer_driver_info_3("", buffer, &info, 0);
5121 free_printer_driver_info_3(&info);
5123 if (*needed > offered)
5124 return WERR_INSUFFICIENT_BUFFER;
5129 /****************************************************************************
5130 ****************************************************************************/
5132 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5139 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5140 if (!W_ERROR_IS_OK(status)) {
5144 /* check the required size. */
5145 *needed += spoolss_size_printer_driver_info_6(&info);
5147 if (!alloc_buffer_size(buffer, *needed)) {
5148 free_printer_driver_info_6(&info);
5149 return WERR_INSUFFICIENT_BUFFER;
5152 /* fill the buffer with the structures */
5153 smb_io_printer_driver_info_6("", buffer, &info, 0);
5155 free_printer_driver_info_6(&info);
5157 if (*needed > offered)
5158 return WERR_INSUFFICIENT_BUFFER;
5163 /****************************************************************************
5164 ****************************************************************************/
5166 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5168 POLICY_HND *handle = &q_u->handle;
5169 UNISTR2 *uni_arch = &q_u->architecture;
5170 uint32 level = q_u->level;
5171 uint32 clientmajorversion = q_u->clientmajorversion;
5172 NEW_BUFFER *buffer = NULL;
5173 uint32 offered = q_u->offered;
5174 uint32 *needed = &r_u->needed;
5175 uint32 *servermajorversion = &r_u->servermajorversion;
5176 uint32 *serverminorversion = &r_u->serverminorversion;
5179 fstring architecture;
5182 /* that's an [in out] buffer */
5183 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5184 buffer = r_u->buffer;
5186 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5189 *servermajorversion = 0;
5190 *serverminorversion = 0;
5192 pstrcpy(servername, get_called_name());
5193 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5195 if (!get_printer_snum(p, handle, &snum))
5200 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5202 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5204 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5206 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5209 return WERR_UNKNOWN_LEVEL;
5212 /****************************************************************************
5213 ****************************************************************************/
5215 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5217 POLICY_HND *handle = &q_u->handle;
5219 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5222 DEBUG(3,("Error in startpageprinter printer handle\n"));
5226 Printer->page_started=True;
5230 /****************************************************************************
5231 ****************************************************************************/
5233 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5235 POLICY_HND *handle = &q_u->handle;
5238 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5241 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5245 if (!get_printer_snum(p, handle, &snum))
5248 Printer->page_started=False;
5249 print_job_endpage(snum, Printer->jobid);
5254 /********************************************************************
5255 * api_spoolss_getprinter
5256 * called from the spoolss dispatcher
5258 ********************************************************************/
5260 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5262 POLICY_HND *handle = &q_u->handle;
5263 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5264 uint32 *jobid = &r_u->jobid;
5266 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5270 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5271 struct current_user user;
5274 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5278 get_current_user(&user, p);
5281 * a nice thing with NT is it doesn't listen to what you tell it.
5282 * when asked to send _only_ RAW datas, it tries to send datas
5285 * So I add checks like in NT Server ...
5287 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
5288 * there's a bug in NT client-side code, so we'll fix it in the
5289 * server-side code. *nnnnnggggh!*
5292 if (info_1->p_datatype != 0) {
5293 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5294 if (strcmp(datatype, "RAW") != 0) {
5296 return WERR_INVALID_DATATYPE;
5300 /* get the share number of the printer */
5301 if (!get_printer_snum(p, handle, &snum)) {
5305 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5307 Printer->jobid = print_job_start(&user, snum, jobname);
5309 /* An error occured in print_job_start() so return an appropriate
5312 if (Printer->jobid == -1) {
5313 return map_werror_from_unix(errno);
5316 Printer->document_started=True;
5317 (*jobid) = Printer->jobid;
5322 /********************************************************************
5323 * api_spoolss_getprinter
5324 * called from the spoolss dispatcher
5326 ********************************************************************/
5328 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5330 POLICY_HND *handle = &q_u->handle;
5332 return _spoolss_enddocprinter_internal(p, handle);
5335 /****************************************************************************
5336 ****************************************************************************/
5338 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5340 POLICY_HND *handle = &q_u->handle;
5341 uint32 buffer_size = q_u->buffer_size;
5342 uint8 *buffer = q_u->buffer;
5343 uint32 *buffer_written = &q_u->buffer_size2;
5345 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5348 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5349 r_u->buffer_written = q_u->buffer_size2;
5353 if (!get_printer_snum(p, handle, &snum))
5356 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5357 if (*buffer_written == -1) {
5358 r_u->buffer_written = 0;
5359 if (errno == ENOSPC)
5360 return WERR_NO_SPOOL_SPACE;
5362 return WERR_ACCESS_DENIED;
5365 r_u->buffer_written = q_u->buffer_size2;
5370 /********************************************************************
5371 * api_spoolss_getprinter
5372 * called from the spoolss dispatcher
5374 ********************************************************************/
5376 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5379 struct current_user user;
5381 WERROR errcode = WERR_BADFUNC;
5382 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5384 get_current_user(&user, p);
5387 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5391 if (!get_printer_snum(p, handle, &snum))
5395 case PRINTER_CONTROL_PAUSE:
5396 if (print_queue_pause(&user, snum, &errcode)) {
5400 case PRINTER_CONTROL_RESUME:
5401 case PRINTER_CONTROL_UNPAUSE:
5402 if (print_queue_resume(&user, snum, &errcode)) {
5406 case PRINTER_CONTROL_PURGE:
5407 if (print_queue_purge(&user, snum, &errcode)) {
5412 return WERR_UNKNOWN_LEVEL;
5418 /********************************************************************
5419 * api_spoolss_abortprinter
5420 ********************************************************************/
5422 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5424 POLICY_HND *handle = &q_u->handle;
5426 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
5429 /********************************************************************
5430 * called by spoolss_api_setprinter
5431 * when updating a printer description
5432 ********************************************************************/
5434 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5435 const SPOOL_PRINTER_INFO_LEVEL *info,
5436 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5438 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5439 struct current_user user;
5443 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5445 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5446 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5447 OUR_HANDLE(handle)));
5449 result = WERR_BADFID;
5453 /* NT seems to like setting the security descriptor even though
5454 nothing may have actually changed. This causes annoying
5455 dialog boxes when the user doesn't have permission to change
5456 the security descriptor. */
5458 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5460 if (DEBUGLEVEL >= 10) {
5464 the_acl = old_secdesc_ctr->sec->dacl;
5465 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5466 PRINTERNAME(snum), the_acl->num_aces));
5468 for (i = 0; i < the_acl->num_aces; i++) {
5471 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5473 DEBUG(10, ("%s 0x%08x\n", sid_str,
5474 the_acl->ace[i].info.mask));
5477 the_acl = secdesc_ctr->sec->dacl;
5480 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5481 PRINTERNAME(snum), the_acl->num_aces));
5483 for (i = 0; i < the_acl->num_aces; i++) {
5486 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5488 DEBUG(10, ("%s 0x%08x\n", sid_str,
5489 the_acl->ace[i].info.mask));
5492 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5496 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5498 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5503 /* Work out which user is performing the operation */
5505 get_current_user(&user, p);
5507 /* Check the user has permissions to change the security
5508 descriptor. By experimentation with two NT machines, the user
5509 requires Full Access to the printer to change security
5512 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5513 result = WERR_ACCESS_DENIED;
5517 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5524 /********************************************************************
5525 Do Samba sanity checks on a printer info struct.
5526 this has changed purpose: it now "canonicalises" printer
5527 info from a client rather than just checking it is correct
5528 ********************************************************************/
5530 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5532 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5533 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5535 /* we force some elements to "correct" values */
5536 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5537 fstrcpy(info->sharename, lp_servicename(snum));
5538 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5539 get_called_name(), info->sharename);
5540 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5545 /****************************************************************************
5546 ****************************************************************************/
5548 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5550 extern userdom_struct current_user_info;
5551 char *cmd = lp_addprinter_cmd();
5554 pstring driverlocation;
5558 fstring remote_machine = "%m";
5560 /* build driver path... only 9X architecture is needed for legacy reasons */
5561 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
5563 /* change \ to \\ for the shell */
5564 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
5565 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5567 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5568 cmd, printer->info_2->printername, printer->info_2->sharename,
5569 printer->info_2->portname, printer->info_2->drivername,
5570 printer->info_2->location, driverlocation, remote_machine);
5572 DEBUG(10,("Running [%s]\n", command));
5573 ret = smbrun(command, &fd);
5574 DEBUGADD(10,("returned [%d]\n", ret));
5583 /* Get lines and convert them back to dos-codepage */
5584 qlines = fd_lines_load(fd, &numlines);
5585 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5589 /* Set the portname to what the script says the portname should be. */
5590 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5591 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5593 /* Send SIGHUP to process group... is there a better way? */
5598 file_lines_free(qlines);
5602 /********************************************************************
5603 * Called by spoolss_api_setprinter
5604 * when updating a printer description.
5605 ********************************************************************/
5607 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5608 const SPOOL_PRINTER_INFO_LEVEL *info,
5609 DEVICEMODE *devmode)
5612 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5613 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5616 DEBUG(8,("update_printer\n"));
5621 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5622 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5623 result = WERR_UNKNOWN_LEVEL;
5628 result = WERR_BADFID;
5632 if (!get_printer_snum(p, handle, &snum)) {
5633 result = WERR_BADFID;
5637 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5638 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5639 result = WERR_BADFID;
5643 DEBUGADD(8,("Converting info_2 struct\n"));
5646 * convert_printer_info converts the incoming
5647 * info from the client and overwrites the info
5648 * just read from the tdb in the pointer 'printer'.
5651 if (!convert_printer_info(info, printer, level)) {
5652 result = WERR_NOMEM;
5657 /* we have a valid devmode
5658 convert it and link it*/
5660 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5661 if (!convert_devicemode(printer->info_2->printername, devmode,
5662 &printer->info_2->devmode)) {
5663 result = WERR_NOMEM;
5668 /* Do sanity check on the requested changes for Samba */
5670 if (!check_printer_ok(printer->info_2, snum)) {
5671 result = WERR_INVALID_PARAM;
5675 /* Check calling user has permission to update printer description */
5677 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5678 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5679 result = WERR_ACCESS_DENIED;
5683 /* Call addprinter hook */
5685 if (*lp_addprinter_cmd()) {
5686 if ( !add_printer_hook(printer) ) {
5687 result = WERR_ACCESS_DENIED;
5693 * When a *new* driver is bound to a printer, the drivername is used to
5694 * lookup previously saved driver initialization info, which is then
5695 * bound to the printer, simulating what happens in the Windows arch.
5697 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5699 if (!set_driver_init(printer, 2))
5701 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5702 printer->info_2->drivername));
5705 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5706 printer->info_2->drivername));
5708 notify_printer_driver(snum, printer->info_2->drivername);
5711 /* Update printer info */
5712 result = mod_a_printer(*printer, 2);
5714 /* flag which changes actually occured. This is a small subset of
5715 all the possible changes */
5717 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5718 notify_printer_comment(snum, printer->info_2->comment);
5720 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5721 notify_printer_sharename(snum, printer->info_2->sharename);
5723 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5724 notify_printer_port(snum, printer->info_2->portname);
5726 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5727 notify_printer_location(snum, printer->info_2->location);
5730 free_a_printer(&printer, 2);
5731 free_a_printer(&old_printer, 2);
5737 /****************************************************************************
5738 ****************************************************************************/
5740 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5742 POLICY_HND *handle = &q_u->handle;
5743 uint32 level = q_u->level;
5744 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5745 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5746 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5747 uint32 command = q_u->command;
5749 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5752 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5756 /* check the level */
5759 return control_printer(handle, command, p);
5761 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5763 return update_printer_sec(handle, level, info, p,
5766 return WERR_UNKNOWN_LEVEL;
5770 /****************************************************************************
5771 ****************************************************************************/
5773 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5775 POLICY_HND *handle = &q_u->handle;
5777 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5780 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5784 if (Printer->notify.client_connected==True)
5785 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5787 Printer->notify.flags=0;
5788 Printer->notify.options=0;
5789 Printer->notify.localmachine[0]='\0';
5790 Printer->notify.printerlocal=0;
5791 if (Printer->notify.option)
5792 free_spool_notify_option(&Printer->notify.option);
5793 Printer->notify.client_connected=False;
5798 /****************************************************************************
5799 ****************************************************************************/
5801 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5803 /* that's an [in out] buffer (despite appearences to the contrary) */
5804 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5807 return WERR_INVALID_PARAM; /* this is what a NT server
5808 returns for AddJob. AddJob
5809 must fail on non-local
5813 /****************************************************************************
5814 ****************************************************************************/
5816 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5817 int position, int snum)
5823 t=gmtime(&queue->time);
5824 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5826 job_info->jobid=queue->job;
5827 init_unistr(&job_info->printername, lp_servicename(snum));
5828 init_unistr(&job_info->machinename, temp_name);
5829 init_unistr(&job_info->username, queue->fs_user);
5830 init_unistr(&job_info->document, queue->fs_file);
5831 init_unistr(&job_info->datatype, "RAW");
5832 init_unistr(&job_info->text_status, "");
5833 job_info->status=nt_printj_status(queue->status);
5834 job_info->priority=queue->priority;
5835 job_info->position=position;
5836 job_info->totalpages=queue->page_count;
5837 job_info->pagesprinted=0;
5839 make_systemtime(&job_info->submitted, t);
5842 /****************************************************************************
5843 ****************************************************************************/
5845 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5846 int position, int snum,
5847 NT_PRINTER_INFO_LEVEL *ntprinter,
5848 DEVICEMODE *devmode)
5854 t=gmtime(&queue->time);
5855 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5857 job_info->jobid=queue->job;
5859 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5861 init_unistr(&job_info->printername, chaine);
5863 init_unistr(&job_info->machinename, temp_name);
5864 init_unistr(&job_info->username, queue->fs_user);
5865 init_unistr(&job_info->document, queue->fs_file);
5866 init_unistr(&job_info->notifyname, queue->fs_user);
5867 init_unistr(&job_info->datatype, "RAW");
5868 init_unistr(&job_info->printprocessor, "winprint");
5869 init_unistr(&job_info->parameters, "");
5870 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5871 init_unistr(&job_info->text_status, "");
5873 /* and here the security descriptor */
5875 job_info->status=nt_printj_status(queue->status);
5876 job_info->priority=queue->priority;
5877 job_info->position=position;
5878 job_info->starttime=0;
5879 job_info->untiltime=0;
5880 job_info->totalpages=queue->page_count;
5881 job_info->size=queue->size;
5882 make_systemtime(&(job_info->submitted), t);
5883 job_info->timeelapsed=0;
5884 job_info->pagesprinted=0;
5886 job_info->devmode = devmode;
5891 /****************************************************************************
5892 Enumjobs at level 1.
5893 ****************************************************************************/
5895 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5896 NEW_BUFFER *buffer, uint32 offered,
5897 uint32 *needed, uint32 *returned)
5902 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5909 for (i=0; i<*returned; i++)
5910 fill_job_info_1(&info[i], &queue[i], i, snum);
5914 /* check the required size. */
5915 for (i=0; i<*returned; i++)
5916 (*needed) += spoolss_size_job_info_1(&info[i]);
5918 if (!alloc_buffer_size(buffer, *needed)) {
5920 return WERR_INSUFFICIENT_BUFFER;
5923 /* fill the buffer with the structures */
5924 for (i=0; i<*returned; i++)
5925 smb_io_job_info_1("", buffer, &info[i], 0);
5930 if (*needed > offered) {
5932 return WERR_INSUFFICIENT_BUFFER;
5938 /****************************************************************************
5939 Enumjobs at level 2.
5940 ****************************************************************************/
5942 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5943 NEW_BUFFER *buffer, uint32 offered,
5944 uint32 *needed, uint32 *returned)
5946 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5947 JOB_INFO_2 *info = NULL;
5950 DEVICEMODE *devmode = NULL;
5952 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5955 result = WERR_NOMEM;
5959 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5960 if (!W_ERROR_IS_OK(result)) {
5965 if (!(devmode = construct_dev_mode(snum))) {
5967 result = WERR_NOMEM;
5971 for (i=0; i<*returned; i++)
5972 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
5975 free_a_printer(&ntprinter, 2);
5978 /* check the required size. */
5979 for (i=0; i<*returned; i++)
5980 (*needed) += spoolss_size_job_info_2(&info[i]);
5982 if (*needed > offered) {
5984 result = WERR_INSUFFICIENT_BUFFER;
5988 if (!alloc_buffer_size(buffer, *needed)) {
5990 result = WERR_INSUFFICIENT_BUFFER;
5994 /* fill the buffer with the structures */
5995 for (i=0; i<*returned; i++)
5996 smb_io_job_info_2("", buffer, &info[i], 0);
6001 free_a_printer(&ntprinter, 2);
6002 free_devmode(devmode);
6010 /****************************************************************************
6012 ****************************************************************************/
6014 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6016 POLICY_HND *handle = &q_u->handle;
6017 uint32 level = q_u->level;
6018 NEW_BUFFER *buffer = NULL;
6019 uint32 offered = q_u->offered;
6020 uint32 *needed = &r_u->needed;
6021 uint32 *returned = &r_u->returned;
6024 print_status_struct prt_status;
6025 print_queue_struct *queue=NULL;
6027 /* that's an [in out] buffer */
6028 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6029 buffer = r_u->buffer;
6031 DEBUG(4,("_spoolss_enumjobs\n"));
6036 if (!get_printer_snum(p, handle, &snum))
6039 *returned = print_queue_status(snum, &queue, &prt_status);
6040 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6042 if (*returned == 0) {
6049 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6051 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6055 return WERR_UNKNOWN_LEVEL;
6059 /****************************************************************************
6060 ****************************************************************************/
6062 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6067 /****************************************************************************
6068 ****************************************************************************/
6070 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6072 POLICY_HND *handle = &q_u->handle;
6073 uint32 jobid = q_u->jobid;
6074 uint32 command = q_u->command;
6076 struct current_user user;
6078 WERROR errcode = WERR_BADFUNC;
6080 if (!get_printer_snum(p, handle, &snum)) {
6084 if (!print_job_exists(snum, jobid)) {
6085 return WERR_INVALID_PRINTER_NAME;
6088 get_current_user(&user, p);
6091 case JOB_CONTROL_CANCEL:
6092 case JOB_CONTROL_DELETE:
6093 if (print_job_delete(&user, snum, jobid, &errcode)) {
6097 case JOB_CONTROL_PAUSE:
6098 if (print_job_pause(&user, snum, jobid, &errcode)) {
6102 case JOB_CONTROL_RESTART:
6103 case JOB_CONTROL_RESUME:
6104 if (print_job_resume(&user, snum, jobid, &errcode)) {
6109 return WERR_UNKNOWN_LEVEL;
6115 /****************************************************************************
6116 Enumerates all printer drivers at level 1.
6117 ****************************************************************************/
6119 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6124 fstring *list = NULL;
6126 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6127 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6131 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6133 ndrivers=get_ntdrivers(&list, architecture, version);
6134 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6140 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6141 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6142 SAFE_FREE(driver_info_1);
6146 else driver_info_1 = tdi1;
6149 for (i=0; i<ndrivers; i++) {
6151 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6152 ZERO_STRUCT(driver);
6153 status = get_a_printer_driver(&driver, 3, list[i],
6154 architecture, version);
6155 if (!W_ERROR_IS_OK(status)) {
6159 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6160 free_a_printer_driver(driver, 3);
6163 *returned+=ndrivers;
6167 /* check the required size. */
6168 for (i=0; i<*returned; i++) {
6169 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6170 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6173 if (!alloc_buffer_size(buffer, *needed)) {
6174 SAFE_FREE(driver_info_1);
6175 return WERR_INSUFFICIENT_BUFFER;
6178 /* fill the buffer with the driver structures */
6179 for (i=0; i<*returned; i++) {
6180 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6181 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6184 SAFE_FREE(driver_info_1);
6186 if (*needed > offered) {
6188 return WERR_INSUFFICIENT_BUFFER;
6194 /****************************************************************************
6195 Enumerates all printer drivers at level 2.
6196 ****************************************************************************/
6198 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6203 fstring *list = NULL;
6205 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6206 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6210 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6212 ndrivers=get_ntdrivers(&list, architecture, version);
6213 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6219 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6220 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6221 SAFE_FREE(driver_info_2);
6225 else driver_info_2 = tdi2;
6228 for (i=0; i<ndrivers; i++) {
6231 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6232 ZERO_STRUCT(driver);
6233 status = get_a_printer_driver(&driver, 3, list[i],
6234 architecture, version);
6235 if (!W_ERROR_IS_OK(status)) {
6239 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6240 free_a_printer_driver(driver, 3);
6243 *returned+=ndrivers;
6247 /* check the required size. */
6248 for (i=0; i<*returned; i++) {
6249 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6250 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6253 if (!alloc_buffer_size(buffer, *needed)) {
6254 SAFE_FREE(driver_info_2);
6255 return WERR_INSUFFICIENT_BUFFER;
6258 /* fill the buffer with the form structures */
6259 for (i=0; i<*returned; i++) {
6260 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6261 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6264 SAFE_FREE(driver_info_2);
6266 if (*needed > offered) {
6268 return WERR_INSUFFICIENT_BUFFER;
6274 /****************************************************************************
6275 Enumerates all printer drivers at level 3.
6276 ****************************************************************************/
6278 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6283 fstring *list = NULL;
6285 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6286 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6290 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6292 ndrivers=get_ntdrivers(&list, architecture, version);
6293 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6299 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6300 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6301 SAFE_FREE(driver_info_3);
6305 else driver_info_3 = tdi3;
6308 for (i=0; i<ndrivers; i++) {
6311 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6312 ZERO_STRUCT(driver);
6313 status = get_a_printer_driver(&driver, 3, list[i],
6314 architecture, version);
6315 if (!W_ERROR_IS_OK(status)) {
6319 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6320 free_a_printer_driver(driver, 3);
6323 *returned+=ndrivers;
6327 /* check the required size. */
6328 for (i=0; i<*returned; i++) {
6329 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6330 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6333 if (!alloc_buffer_size(buffer, *needed)) {
6334 SAFE_FREE(driver_info_3);
6335 return WERR_INSUFFICIENT_BUFFER;
6338 /* fill the buffer with the driver structures */
6339 for (i=0; i<*returned; i++) {
6340 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6341 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6344 for (i=0; i<*returned; i++)
6345 SAFE_FREE(driver_info_3[i].dependentfiles);
6347 SAFE_FREE(driver_info_3);
6349 if (*needed > offered) {
6351 return WERR_INSUFFICIENT_BUFFER;
6357 /****************************************************************************
6358 Enumerates all printer drivers.
6359 ****************************************************************************/
6361 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6363 UNISTR2 *environment = &q_u->environment;
6364 uint32 level = q_u->level;
6365 NEW_BUFFER *buffer = NULL;
6366 uint32 offered = q_u->offered;
6367 uint32 *needed = &r_u->needed;
6368 uint32 *returned = &r_u->returned;
6370 fstring *list = NULL;
6372 fstring architecture;
6374 /* that's an [in out] buffer */
6375 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6376 buffer = r_u->buffer;
6378 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6379 fstrcpy(servername, get_called_name());
6383 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6387 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6389 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6391 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6395 return WERR_UNKNOWN_LEVEL;
6399 /****************************************************************************
6400 ****************************************************************************/
6402 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6404 form->flag=list->flag;
6405 init_unistr(&form->name, list->name);
6406 form->width=list->width;
6407 form->length=list->length;
6408 form->left=list->left;
6409 form->top=list->top;
6410 form->right=list->right;
6411 form->bottom=list->bottom;
6414 /****************************************************************************
6415 ****************************************************************************/
6417 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6419 uint32 level = q_u->level;
6420 NEW_BUFFER *buffer = NULL;
6421 uint32 offered = q_u->offered;
6422 uint32 *needed = &r_u->needed;
6423 uint32 *numofforms = &r_u->numofforms;
6424 uint32 numbuiltinforms;
6426 nt_forms_struct *list=NULL;
6427 nt_forms_struct *builtinlist=NULL;
6432 /* that's an [in out] buffer */
6433 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6434 buffer = r_u->buffer;
6436 DEBUG(4,("_spoolss_enumforms\n"));
6437 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6438 DEBUGADD(5,("Info level [%d]\n", level));
6440 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6441 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6442 *numofforms = get_ntforms(&list);
6443 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6444 *numofforms += numbuiltinforms;
6446 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6450 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6455 /* construct the list of form structures */
6456 for (i=0; i<numbuiltinforms; i++) {
6457 DEBUGADD(6,("Filling form number [%d]\n",i));
6458 fill_form_1(&forms_1[i], &builtinlist[i]);
6461 SAFE_FREE(builtinlist);
6463 for (; i<*numofforms; i++) {
6464 DEBUGADD(6,("Filling form number [%d]\n",i));
6465 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6470 /* check the required size. */
6471 for (i=0; i<numbuiltinforms; i++) {
6472 DEBUGADD(6,("adding form [%d]'s size\n",i));
6473 buffer_size += spoolss_size_form_1(&forms_1[i]);
6475 for (; i<*numofforms; i++) {
6476 DEBUGADD(6,("adding form [%d]'s size\n",i));
6477 buffer_size += spoolss_size_form_1(&forms_1[i]);
6480 *needed=buffer_size;
6482 if (!alloc_buffer_size(buffer, buffer_size)){
6484 return WERR_INSUFFICIENT_BUFFER;
6487 /* fill the buffer with the form structures */
6488 for (i=0; i<numbuiltinforms; i++) {
6489 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6490 smb_io_form_1("", buffer, &forms_1[i], 0);
6492 for (; i<*numofforms; i++) {
6493 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6494 smb_io_form_1("", buffer, &forms_1[i], 0);
6499 if (*needed > offered) {
6501 return WERR_INSUFFICIENT_BUFFER;
6508 SAFE_FREE(builtinlist);
6509 return WERR_UNKNOWN_LEVEL;
6514 /****************************************************************************
6515 ****************************************************************************/
6517 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6519 uint32 level = q_u->level;
6520 UNISTR2 *uni_formname = &q_u->formname;
6521 NEW_BUFFER *buffer = NULL;
6522 uint32 offered = q_u->offered;
6523 uint32 *needed = &r_u->needed;
6525 nt_forms_struct *list=NULL;
6526 nt_forms_struct builtin_form;
6531 int numofforms=0, i=0;
6533 /* that's an [in out] buffer */
6534 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6535 buffer = r_u->buffer;
6537 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6539 DEBUG(4,("_spoolss_getform\n"));
6540 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6541 DEBUGADD(5,("Info level [%d]\n", level));
6543 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6544 if (!foundBuiltin) {
6545 numofforms = get_ntforms(&list);
6546 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6548 if (numofforms == 0)
6555 fill_form_1(&form_1, &builtin_form);
6558 /* Check if the requested name is in the list of form structures */
6559 for (i=0; i<numofforms; i++) {
6561 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6563 if (strequal(form_name, list[i].name)) {
6564 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6565 fill_form_1(&form_1, &list[i]);
6571 if (i == numofforms) {
6575 /* check the required size. */
6577 *needed=spoolss_size_form_1(&form_1);
6579 if (!alloc_buffer_size(buffer, buffer_size)){
6580 return WERR_INSUFFICIENT_BUFFER;
6583 if (*needed > offered) {
6584 return WERR_INSUFFICIENT_BUFFER;
6587 /* fill the buffer with the form structures */
6588 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6589 smb_io_form_1("", buffer, &form_1, 0);
6595 return WERR_UNKNOWN_LEVEL;
6599 /****************************************************************************
6600 ****************************************************************************/
6602 static void fill_port_1(PORT_INFO_1 *port, char *name)
6604 init_unistr(&port->port_name, name);
6607 /****************************************************************************
6608 ****************************************************************************/
6610 static void fill_port_2(PORT_INFO_2 *port, char *name)
6612 init_unistr(&port->port_name, name);
6613 init_unistr(&port->monitor_name, "Local Monitor");
6614 init_unistr(&port->description, "Local Port");
6615 #define PORT_TYPE_WRITE 1
6616 port->port_type=PORT_TYPE_WRITE;
6620 /****************************************************************************
6622 ****************************************************************************/
6624 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6626 PORT_INFO_1 *ports=NULL;
6629 if (*lp_enumports_cmd()) {
6630 char *cmd = lp_enumports_cmd();
6637 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6639 DEBUG(10,("Running [%s]\n", command));
6640 ret = smbrun(command, &fd);
6641 DEBUG(10,("Returned [%d]\n", ret));
6645 /* Is this the best error to return here? */
6646 return WERR_ACCESS_DENIED;
6650 qlines = fd_lines_load(fd, &numlines);
6651 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6655 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6656 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6657 dos_errstr(WERR_NOMEM)));
6658 file_lines_free(qlines);
6662 for (i=0; i<numlines; i++) {
6663 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6664 fill_port_1(&ports[i], qlines[i]);
6667 file_lines_free(qlines);
6670 *returned = numlines;
6673 *returned = 1; /* Sole Samba port returned. */
6675 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6678 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6680 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6683 /* check the required size. */
6684 for (i=0; i<*returned; i++) {
6685 DEBUGADD(6,("adding port [%d]'s size\n", i));
6686 *needed += spoolss_size_port_info_1(&ports[i]);
6689 if (!alloc_buffer_size(buffer, *needed)) {
6691 return WERR_INSUFFICIENT_BUFFER;
6694 /* fill the buffer with the ports structures */
6695 for (i=0; i<*returned; i++) {
6696 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6697 smb_io_port_1("", buffer, &ports[i], 0);
6702 if (*needed > offered) {
6704 return WERR_INSUFFICIENT_BUFFER;
6710 /****************************************************************************
6712 ****************************************************************************/
6714 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6716 PORT_INFO_2 *ports=NULL;
6719 if (*lp_enumports_cmd()) {
6720 char *cmd = lp_enumports_cmd();
6729 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6730 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6732 path = lp_lockdir();
6734 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6735 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6738 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6739 ret = smbrun(command, &fd);
6740 DEBUGADD(10,("returned [%d]\n", ret));
6744 /* Is this the best error to return here? */
6745 return WERR_ACCESS_DENIED;
6749 qlines = fd_lines_load(fd, &numlines);
6750 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6754 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6755 file_lines_free(qlines);
6759 for (i=0; i<numlines; i++) {
6760 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6761 fill_port_2(&(ports[i]), qlines[i]);
6764 file_lines_free(qlines);
6767 *returned = numlines;
6773 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6776 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6778 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6781 /* check the required size. */
6782 for (i=0; i<*returned; i++) {
6783 DEBUGADD(6,("adding port [%d]'s size\n", i));
6784 *needed += spoolss_size_port_info_2(&ports[i]);
6787 if (!alloc_buffer_size(buffer, *needed)) {
6789 return WERR_INSUFFICIENT_BUFFER;
6792 /* fill the buffer with the ports structures */
6793 for (i=0; i<*returned; i++) {
6794 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6795 smb_io_port_2("", buffer, &ports[i], 0);
6800 if (*needed > offered) {
6802 return WERR_INSUFFICIENT_BUFFER;
6808 /****************************************************************************
6810 ****************************************************************************/
6812 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6814 uint32 level = q_u->level;
6815 NEW_BUFFER *buffer = NULL;
6816 uint32 offered = q_u->offered;
6817 uint32 *needed = &r_u->needed;
6818 uint32 *returned = &r_u->returned;
6820 /* that's an [in out] buffer */
6821 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6822 buffer = r_u->buffer;
6824 DEBUG(4,("_spoolss_enumports\n"));
6831 return enumports_level_1(buffer, offered, needed, returned);
6833 return enumports_level_2(buffer, offered, needed, returned);
6835 return WERR_UNKNOWN_LEVEL;
6839 /****************************************************************************
6840 ****************************************************************************/
6842 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6843 const SPOOL_PRINTER_INFO_LEVEL *info,
6844 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6845 uint32 user_switch, const SPOOL_USER_CTR *user,
6848 NT_PRINTER_INFO_LEVEL *printer = NULL;
6851 WERROR err = WERR_OK;
6853 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6854 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6858 ZERO_STRUCTP(printer);
6860 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6861 if (!convert_printer_info(info, printer, 2)) {
6862 free_a_printer(&printer, 2);
6866 /* check to see if the printer already exists */
6868 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6869 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6870 printer->info_2->sharename));
6871 free_a_printer(&printer, 2);
6872 return WERR_PRINTER_ALREADY_EXISTS;
6875 if (*lp_addprinter_cmd() )
6876 if ( !add_printer_hook(printer) ) {
6877 free_a_printer(&printer,2);
6878 return WERR_ACCESS_DENIED;
6881 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6882 printer->info_2->sharename);
6884 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6885 free_a_printer(&printer,2);
6886 return WERR_ACCESS_DENIED;
6889 /* you must be a printer admin to add a new printer */
6890 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6891 free_a_printer(&printer,2);
6892 return WERR_ACCESS_DENIED;
6896 * Do sanity check on the requested changes for Samba.
6899 if (!check_printer_ok(printer->info_2, snum)) {
6900 free_a_printer(&printer,2);
6901 return WERR_INVALID_PARAM;
6905 * When a printer is created, the drivername bound to the printer is used
6906 * to lookup previously saved driver initialization info, which is then
6907 * bound to the new printer, simulating what happens in the Windows arch.
6912 set_driver_init(printer, 2);
6916 /* A valid devmode was included, convert and link it
6918 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6920 if (!convert_devicemode(printer->info_2->printername, devmode,
6921 &printer->info_2->devmode))
6925 /* write the ASCII on disk */
6926 err = mod_a_printer(*printer, 2);
6927 if (!W_ERROR_IS_OK(err)) {
6928 free_a_printer(&printer,2);
6932 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6933 /* Handle open failed - remove addition. */
6934 del_a_printer(printer->info_2->sharename);
6935 free_a_printer(&printer,2);
6936 return WERR_ACCESS_DENIED;
6939 update_c_setprinter(False);
6940 free_a_printer(&printer,2);
6945 /****************************************************************************
6946 ****************************************************************************/
6948 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6950 UNISTR2 *uni_srv_name = &q_u->server_name;
6951 uint32 level = q_u->level;
6952 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6953 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6954 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6955 uint32 user_switch = q_u->user_switch;
6956 SPOOL_USER_CTR *user = &q_u->user_ctr;
6957 POLICY_HND *handle = &r_u->handle;
6961 /* we don't handle yet */
6962 /* but I know what to do ... */
6963 return WERR_UNKNOWN_LEVEL;
6965 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6967 user_switch, user, handle);
6969 return WERR_UNKNOWN_LEVEL;
6973 /****************************************************************************
6974 ****************************************************************************/
6976 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6978 uint32 level = q_u->level;
6979 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6980 WERROR err = WERR_OK;
6981 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6982 struct current_user user;
6983 fstring driver_name;
6986 ZERO_STRUCT(driver);
6988 get_current_user(&user, p);
6990 if (!convert_printer_driver_info(info, &driver, level)) {
6995 DEBUG(5,("Cleaning driver's information\n"));
6996 err = clean_up_driver_struct(driver, level, &user);
6997 if (!W_ERROR_IS_OK(err))
7000 DEBUG(5,("Moving driver to final destination\n"));
7001 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7002 if (W_ERROR_IS_OK(err))
7003 err = WERR_ACCESS_DENIED;
7007 if (add_a_printer_driver(driver, level)!=0) {
7008 err = WERR_ACCESS_DENIED;
7012 /* BEGIN_ADMIN_LOG */
7015 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7016 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7017 fstrcpy(driver_name, driver.info_3->name);
7020 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7021 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7022 fstrcpy(driver_name, driver.info_6->name);
7028 * I think this is where he DrvUpgradePrinter() hook would be
7029 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7030 * server. Right now, we just need to send ourselves a message
7031 * to update each printer bound to this driver. --jerry
7034 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7035 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7040 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7041 * decide if the driver init data should be deleted. The rules are:
7042 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7043 * 2) delete init data only if there is no 2k/Xp driver
7044 * 3) always delete init data
7045 * The generalized rule is always use init data from the highest order driver.
7046 * It is necessary to follow the driver install by an initialization step to
7047 * finish off this process.
7050 version = driver.info_3->cversion;
7051 else if (level == 6)
7052 version = driver.info_6->version;
7057 * 9x printer driver - never delete init data
7060 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7065 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7066 * there is no 2k/Xp driver init data for this driver name.
7070 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7072 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7074 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7076 if (!del_driver_init(driver_name))
7077 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7080 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7082 free_a_printer_driver(driver1,3);
7083 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7090 * 2k or Xp printer driver - always delete init data
7093 if (!del_driver_init(driver_name))
7094 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7098 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7104 free_a_printer_driver(driver, level);
7108 /********************************************************************
7109 * spoolss_addprinterdriverex
7110 ********************************************************************/
7112 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7114 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7115 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7118 * we only support the semantics of AddPrinterDriver()
7119 * i.e. only copy files that are newer than existing ones
7122 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7123 return WERR_ACCESS_DENIED;
7125 ZERO_STRUCT(q_u_local);
7126 ZERO_STRUCT(r_u_local);
7128 /* just pass the information off to _spoolss_addprinterdriver() */
7129 q_u_local.server_name_ptr = q_u->server_name_ptr;
7130 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7131 q_u_local.level = q_u->level;
7132 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7134 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7137 /****************************************************************************
7138 ****************************************************************************/
7140 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7142 init_unistr(&info->name, name);
7145 /****************************************************************************
7146 ****************************************************************************/
7148 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7152 pstring short_archi;
7153 DRIVER_DIRECTORY_1 *info=NULL;
7155 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7157 if (get_short_archi(short_archi, long_archi)==False)
7158 return WERR_INVALID_ENVIRONMENT;
7160 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7163 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7165 DEBUG(4,("printer driver directory: [%s]\n", path));
7167 fill_driverdir_1(info, path);
7169 *needed += spoolss_size_driverdir_info_1(info);
7171 if (!alloc_buffer_size(buffer, *needed)) {
7173 return WERR_INSUFFICIENT_BUFFER;
7176 smb_io_driverdir_1("", buffer, info, 0);
7180 if (*needed > offered)
7181 return WERR_INSUFFICIENT_BUFFER;
7186 /****************************************************************************
7187 ****************************************************************************/
7189 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7191 UNISTR2 *name = &q_u->name;
7192 UNISTR2 *uni_environment = &q_u->environment;
7193 uint32 level = q_u->level;
7194 NEW_BUFFER *buffer = NULL;
7195 uint32 offered = q_u->offered;
7196 uint32 *needed = &r_u->needed;
7198 /* that's an [in out] buffer */
7199 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7200 buffer = r_u->buffer;
7202 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7208 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7210 return WERR_UNKNOWN_LEVEL;
7214 /****************************************************************************
7215 ****************************************************************************/
7217 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7219 POLICY_HND *handle = &q_u->handle;
7220 uint32 idx = q_u->index;
7221 uint32 in_value_len = q_u->valuesize;
7222 uint32 in_data_len = q_u->datasize;
7223 uint32 *out_max_value_len = &r_u->valuesize;
7224 uint16 **out_value = &r_u->value;
7225 uint32 *out_value_len = &r_u->realvaluesize;
7226 uint32 *out_type = &r_u->type;
7227 uint32 *out_max_data_len = &r_u->datasize;
7228 uint8 **data_out = &r_u->data;
7229 uint32 *out_data_len = &r_u->realdatasize;
7231 NT_PRINTER_INFO_LEVEL *printer = NULL;
7234 uint32 biggest_valuesize;
7235 uint32 biggest_datasize;
7237 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7240 REGISTRY_VALUE *val;
7241 NT_PRINTER_DATA *p_data;
7242 int i, key_index, num_values;
7245 ZERO_STRUCT( printer );
7249 *out_max_data_len = 0;
7253 DEBUG(5,("spoolss_enumprinterdata\n"));
7256 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7260 if (!get_printer_snum(p,handle, &snum))
7263 result = get_a_printer(&printer, 2, lp_servicename(snum));
7264 if (!W_ERROR_IS_OK(result))
7267 p_data = &printer->info_2->data;
7268 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7273 * The NT machine wants to know the biggest size of value and data
7275 * cf: MSDN EnumPrinterData remark section
7278 if ( !in_value_len && !in_data_len )
7280 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7283 biggest_valuesize = 0;
7284 biggest_datasize = 0;
7286 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7288 for ( i=0; i<num_values; i++ )
7290 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7292 name_length = strlen(val->valuename);
7293 if ( strlen(val->valuename) > biggest_valuesize )
7294 biggest_valuesize = name_length;
7296 if ( val->size > biggest_datasize )
7297 biggest_datasize = val->size;
7299 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7303 /* the value is an UNICODE string but real_value_size is the length
7304 in bytes including the trailing 0 */
7306 *out_value_len = 2 * (1+biggest_valuesize);
7307 *out_data_len = biggest_datasize;
7309 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7315 * the value len is wrong in NT sp3
7316 * that's the number of bytes not the number of unicode chars
7319 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7324 /* out_value should default to "" or else NT4 has
7325 problems unmarshalling the response */
7327 *out_max_value_len = (in_value_len/sizeof(uint16));
7329 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7331 result = WERR_NOMEM;
7335 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7337 /* the data is counted in bytes */
7339 *out_max_data_len = in_data_len;
7340 *out_data_len = in_data_len;
7342 /* only allocate when given a non-zero data_len */
7344 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7346 result = WERR_NOMEM;
7350 result = WERR_NO_MORE_ITEMS;
7356 * - counted in bytes in the request
7357 * - counted in UNICODE chars in the max reply
7358 * - counted in bytes in the real size
7360 * take a pause *before* coding not *during* coding
7364 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7365 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7367 result = WERR_NOMEM;
7371 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7375 *out_type = regval_type( val );
7377 /* data - counted in bytes */
7379 *out_max_data_len = in_data_len;
7380 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7382 result = WERR_NOMEM;
7385 data_len = (size_t)regval_size(val);
7386 memcpy( *data_out, regval_data_p(val), data_len );
7387 *out_data_len = data_len;
7391 free_a_printer(&printer, 2);
7395 /****************************************************************************
7396 ****************************************************************************/
7398 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7400 POLICY_HND *handle = &q_u->handle;
7401 UNISTR2 *value = &q_u->value;
7402 uint32 type = q_u->type;
7403 uint8 *data = q_u->data;
7404 uint32 real_len = q_u->real_len;
7406 NT_PRINTER_INFO_LEVEL *printer = NULL;
7408 WERROR status = WERR_OK;
7409 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7412 DEBUG(5,("spoolss_setprinterdata\n"));
7415 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7419 if (!get_printer_snum(p,handle, &snum))
7423 * Access check : NT returns "access denied" if you make a
7424 * SetPrinterData call without the necessary privildge.
7425 * we were originally returning OK if nothing changed
7426 * which made Win2k issue **a lot** of SetPrinterData
7427 * when connecting to a printer --jerry
7430 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7432 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7433 status = WERR_ACCESS_DENIED;
7437 status = get_a_printer(&printer, 2, lp_servicename(snum));
7438 if (!W_ERROR_IS_OK(status))
7441 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7444 * When client side code sets a magic printer data key, detect it and save
7445 * the current printer data and the magic key's data (its the DEVMODE) for
7446 * future printer/driver initializations.
7448 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7450 /* Set devmode and printer initialization info */
7451 status = save_driver_init( printer, 2, data, real_len );
7453 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7457 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7458 type, data, real_len );
7459 if ( W_ERROR_IS_OK(status) )
7460 status = mod_a_printer(*printer, 2);
7464 free_a_printer(&printer, 2);
7469 /****************************************************************************
7470 ****************************************************************************/
7472 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7474 POLICY_HND *handle = &q_u->handle;
7475 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7478 DEBUG(5,("_spoolss_resetprinter\n"));
7481 * All we do is to check to see if the handle and queue is valid.
7482 * This call really doesn't mean anything to us because we only
7483 * support RAW printing. --jerry
7487 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7491 if (!get_printer_snum(p,handle, &snum))
7495 /* blindly return success */
7500 /****************************************************************************
7501 ****************************************************************************/
7503 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7505 POLICY_HND *handle = &q_u->handle;
7506 UNISTR2 *value = &q_u->valuename;
7508 NT_PRINTER_INFO_LEVEL *printer = NULL;
7510 WERROR status = WERR_OK;
7511 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7514 DEBUG(5,("spoolss_deleteprinterdata\n"));
7517 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7521 if (!get_printer_snum(p, handle, &snum))
7524 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7525 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7526 return WERR_ACCESS_DENIED;
7529 status = get_a_printer(&printer, 2, lp_servicename(snum));
7530 if (!W_ERROR_IS_OK(status))
7533 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7535 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7537 free_a_printer(&printer, 2);
7542 /****************************************************************************
7543 ****************************************************************************/
7545 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7547 POLICY_HND *handle = &q_u->handle;
7548 FORM *form = &q_u->form;
7549 nt_forms_struct tmpForm;
7551 WERROR status = WERR_OK;
7552 NT_PRINTER_INFO_LEVEL *printer = NULL;
7555 nt_forms_struct *list=NULL;
7556 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7558 DEBUG(5,("spoolss_addform\n"));
7561 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7566 /* forms can be added on printer of on the print server handle */
7568 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7570 if (!get_printer_snum(p,handle, &snum))
7573 status = get_a_printer(&printer, 2, lp_servicename(snum));
7574 if (!W_ERROR_IS_OK(status))
7578 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7579 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7580 status = WERR_ACCESS_DENIED;
7584 /* can't add if builtin */
7586 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7587 status = WERR_ALREADY_EXISTS;
7591 count = get_ntforms(&list);
7593 if(!add_a_form(&list, form, &count)) {
7594 status = WERR_NOMEM;
7598 write_ntforms(&list, count);
7601 * ChangeID must always be set if this is a printer
7604 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7605 status = mod_a_printer(*printer, 2);
7609 free_a_printer(&printer, 2);
7615 /****************************************************************************
7616 ****************************************************************************/
7618 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7620 POLICY_HND *handle = &q_u->handle;
7621 UNISTR2 *form_name = &q_u->name;
7622 nt_forms_struct tmpForm;
7624 nt_forms_struct *list=NULL;
7625 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7627 WERROR status = WERR_OK;
7628 NT_PRINTER_INFO_LEVEL *printer = NULL;
7630 DEBUG(5,("spoolss_deleteform\n"));
7633 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7637 /* forms can be deleted on printer of on the print server handle */
7639 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7641 if (!get_printer_snum(p,handle, &snum))
7644 status = get_a_printer(&printer, 2, lp_servicename(snum));
7645 if (!W_ERROR_IS_OK(status))
7649 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7650 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7651 status = WERR_ACCESS_DENIED;
7655 /* can't delete if builtin */
7657 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7658 status = WERR_INVALID_PARAM;
7662 count = get_ntforms(&list);
7664 if ( !delete_a_form(&list, form_name, &count, &status ))
7668 * ChangeID must always be set if this is a printer
7671 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7672 status = mod_a_printer(*printer, 2);
7676 free_a_printer(&printer, 2);
7682 /****************************************************************************
7683 ****************************************************************************/
7685 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7687 POLICY_HND *handle = &q_u->handle;
7688 FORM *form = &q_u->form;
7689 nt_forms_struct tmpForm;
7691 WERROR status = WERR_OK;
7692 NT_PRINTER_INFO_LEVEL *printer = NULL;
7695 nt_forms_struct *list=NULL;
7696 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7698 DEBUG(5,("spoolss_setform\n"));
7701 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7705 /* forms can be modified on printer of on the print server handle */
7707 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7709 if (!get_printer_snum(p,handle, &snum))
7712 status = get_a_printer(&printer, 2, lp_servicename(snum));
7713 if (!W_ERROR_IS_OK(status))
7717 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7718 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7719 status = WERR_ACCESS_DENIED;
7723 /* can't set if builtin */
7724 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7725 status = WERR_INVALID_PARAM;
7729 count = get_ntforms(&list);
7730 update_a_form(&list, form, count);
7731 write_ntforms(&list, count);
7734 * ChangeID must always be set if this is a printer
7737 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7738 status = mod_a_printer(*printer, 2);
7743 free_a_printer(&printer, 2);
7749 /****************************************************************************
7750 enumprintprocessors level 1.
7751 ****************************************************************************/
7753 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7755 PRINTPROCESSOR_1 *info_1=NULL;
7757 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7762 init_unistr(&info_1->name, "winprint");
7764 *needed += spoolss_size_printprocessor_info_1(info_1);
7766 if (!alloc_buffer_size(buffer, *needed))
7767 return WERR_INSUFFICIENT_BUFFER;
7769 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7773 if (*needed > offered) {
7775 return WERR_INSUFFICIENT_BUFFER;
7781 /****************************************************************************
7782 ****************************************************************************/
7784 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7786 uint32 level = q_u->level;
7787 NEW_BUFFER *buffer = NULL;
7788 uint32 offered = q_u->offered;
7789 uint32 *needed = &r_u->needed;
7790 uint32 *returned = &r_u->returned;
7792 /* that's an [in out] buffer */
7793 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7794 buffer = r_u->buffer;
7796 DEBUG(5,("spoolss_enumprintprocessors\n"));
7799 * Enumerate the print processors ...
7801 * Just reply with "winprint", to keep NT happy
7802 * and I can use my nice printer checker.
7810 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7812 return WERR_UNKNOWN_LEVEL;
7816 /****************************************************************************
7817 enumprintprocdatatypes level 1.
7818 ****************************************************************************/
7820 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7822 PRINTPROCDATATYPE_1 *info_1=NULL;
7824 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7829 init_unistr(&info_1->name, "RAW");
7831 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7833 if (!alloc_buffer_size(buffer, *needed))
7834 return WERR_INSUFFICIENT_BUFFER;
7836 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7840 if (*needed > offered) {
7842 return WERR_INSUFFICIENT_BUFFER;
7848 /****************************************************************************
7849 ****************************************************************************/
7851 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7853 uint32 level = q_u->level;
7854 NEW_BUFFER *buffer = NULL;
7855 uint32 offered = q_u->offered;
7856 uint32 *needed = &r_u->needed;
7857 uint32 *returned = &r_u->returned;
7859 /* that's an [in out] buffer */
7860 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7861 buffer = r_u->buffer;
7863 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7870 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7872 return WERR_UNKNOWN_LEVEL;
7876 /****************************************************************************
7877 enumprintmonitors level 1.
7878 ****************************************************************************/
7880 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7882 PRINTMONITOR_1 *info_1=NULL;
7884 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7889 init_unistr(&info_1->name, "Local Port");
7891 *needed += spoolss_size_printmonitor_info_1(info_1);
7893 if (!alloc_buffer_size(buffer, *needed))
7894 return WERR_INSUFFICIENT_BUFFER;
7896 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7900 if (*needed > offered) {
7902 return WERR_INSUFFICIENT_BUFFER;
7908 /****************************************************************************
7909 enumprintmonitors level 2.
7910 ****************************************************************************/
7912 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7914 PRINTMONITOR_2 *info_2=NULL;
7916 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7921 init_unistr(&info_2->name, "Local Port");
7922 init_unistr(&info_2->environment, "Windows NT X86");
7923 init_unistr(&info_2->dll_name, "localmon.dll");
7925 *needed += spoolss_size_printmonitor_info_2(info_2);
7927 if (!alloc_buffer_size(buffer, *needed))
7928 return WERR_INSUFFICIENT_BUFFER;
7930 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7934 if (*needed > offered) {
7936 return WERR_INSUFFICIENT_BUFFER;
7942 /****************************************************************************
7943 ****************************************************************************/
7945 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7947 uint32 level = q_u->level;
7948 NEW_BUFFER *buffer = NULL;
7949 uint32 offered = q_u->offered;
7950 uint32 *needed = &r_u->needed;
7951 uint32 *returned = &r_u->returned;
7953 /* that's an [in out] buffer */
7954 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7955 buffer = r_u->buffer;
7957 DEBUG(5,("spoolss_enumprintmonitors\n"));
7960 * Enumerate the print monitors ...
7962 * Just reply with "Local Port", to keep NT happy
7963 * and I can use my nice printer checker.
7971 return enumprintmonitors_level_1(buffer, offered, needed, returned);
7973 return enumprintmonitors_level_2(buffer, offered, needed, returned);
7975 return WERR_UNKNOWN_LEVEL;
7979 /****************************************************************************
7980 ****************************************************************************/
7982 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7986 JOB_INFO_1 *info_1=NULL;
7988 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
7990 if (info_1 == NULL) {
7995 for (i=0; i<count && found==False; i++) {
7996 if (queue[i].job==(int)jobid)
8003 /* NT treats not found as bad param... yet another bad choice */
8004 return WERR_INVALID_PARAM;
8007 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8011 *needed += spoolss_size_job_info_1(info_1);
8013 if (!alloc_buffer_size(buffer, *needed)) {
8015 return WERR_INSUFFICIENT_BUFFER;
8018 smb_io_job_info_1("", buffer, info_1, 0);
8022 if (*needed > offered)
8023 return WERR_INSUFFICIENT_BUFFER;
8028 /****************************************************************************
8029 ****************************************************************************/
8031 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8036 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8038 DEVICEMODE *devmode = NULL;
8040 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8042 ZERO_STRUCTP(info_2);
8044 if (info_2 == NULL) {
8049 for (i=0; i<count && found==False; i++) {
8050 if (queue[i].job==(int)jobid)
8055 /* NT treats not found as bad param... yet another bad
8057 ret = WERR_INVALID_PARAM;
8061 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
8062 if (!W_ERROR_IS_OK(ret))
8064 if (construct_dev_mode(snum) == NULL) {
8069 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8071 *needed += spoolss_size_job_info_2(info_2);
8073 if (!alloc_buffer_size(buffer, *needed)) {
8074 ret = WERR_INSUFFICIENT_BUFFER;
8078 smb_io_job_info_2("", buffer, info_2, 0);
8080 if (*needed > offered) {
8081 ret = WERR_INSUFFICIENT_BUFFER;
8088 /* Cleanup allocated memory */
8091 free_job_info_2(info_2); /* Also frees devmode */
8093 free_a_printer(&ntprinter, 2);
8098 /****************************************************************************
8099 ****************************************************************************/
8101 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8103 POLICY_HND *handle = &q_u->handle;
8104 uint32 jobid = q_u->jobid;
8105 uint32 level = q_u->level;
8106 NEW_BUFFER *buffer = NULL;
8107 uint32 offered = q_u->offered;
8108 uint32 *needed = &r_u->needed;
8112 print_queue_struct *queue=NULL;
8113 print_status_struct prt_status;
8115 /* that's an [in out] buffer */
8116 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8117 buffer = r_u->buffer;
8119 DEBUG(5,("spoolss_getjob\n"));
8123 if (!get_printer_snum(p, handle, &snum))
8126 count = print_queue_status(snum, &queue, &prt_status);
8128 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8129 count, prt_status.status, prt_status.message));
8133 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
8135 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
8138 return WERR_UNKNOWN_LEVEL;
8142 /********************************************************************
8143 spoolss_getprinterdataex
8145 From MSDN documentation of GetPrinterDataEx: pass request
8146 to GetPrinterData if key is "PrinterDriverData".
8147 ********************************************************************/
8149 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8151 POLICY_HND *handle = &q_u->handle;
8152 uint32 in_size = q_u->size;
8153 uint32 *type = &r_u->type;
8154 uint32 *out_size = &r_u->size;
8155 uint8 **data = &r_u->data;
8156 uint32 *needed = &r_u->needed;
8157 fstring keyname, valuename;
8159 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8161 NT_PRINTER_INFO_LEVEL *printer = NULL;
8163 WERROR status = WERR_OK;
8165 DEBUG(4,("_spoolss_getprinterdataex\n"));
8167 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8168 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8170 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8171 keyname, valuename));
8173 /* in case of problem, return some default values */
8177 *out_size = in_size;
8180 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8181 status = WERR_BADFID;
8185 /* Is the handle to a printer or to the server? */
8187 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8188 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8189 status = WERR_INVALID_PARAM;
8193 if ( !get_printer_snum(p,handle, &snum) )
8196 status = get_a_printer(&printer, 2, lp_servicename(snum));
8197 if ( !W_ERROR_IS_OK(status) )
8200 /* check to see if the keyname is valid */
8201 if ( !strlen(keyname) ) {
8202 status = WERR_INVALID_PARAM;
8206 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8207 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8208 free_a_printer( &printer, 2 );
8209 status = WERR_BADFILE;
8213 /* When given a new keyname, we should just create it */
8215 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8217 if (*needed > *out_size)
8218 status = WERR_MORE_DATA;
8221 if ( !W_ERROR_IS_OK(status) )
8223 DEBUG(5, ("error: allocating %d\n", *out_size));
8225 /* reply this param doesn't exist */
8229 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8230 status = WERR_NOMEM;
8240 free_a_printer( &printer, 2 );
8245 /********************************************************************
8246 * spoolss_setprinterdataex
8247 ********************************************************************/
8249 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8251 POLICY_HND *handle = &q_u->handle;
8252 uint32 type = q_u->type;
8253 uint8 *data = q_u->data;
8254 uint32 real_len = q_u->real_len;
8256 NT_PRINTER_INFO_LEVEL *printer = NULL;
8258 WERROR status = WERR_OK;
8259 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8264 DEBUG(4,("_spoolss_setprinterdataex\n"));
8266 /* From MSDN documentation of SetPrinterDataEx: pass request to
8267 SetPrinterData if key is "PrinterDriverData" */
8270 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8274 if ( !get_printer_snum(p,handle, &snum) )
8278 * Access check : NT returns "access denied" if you make a
8279 * SetPrinterData call without the necessary privildge.
8280 * we were originally returning OK if nothing changed
8281 * which made Win2k issue **a lot** of SetPrinterData
8282 * when connecting to a printer --jerry
8285 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8287 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8288 return WERR_ACCESS_DENIED;
8291 status = get_a_printer(&printer, 2, lp_servicename(snum));
8292 if (!W_ERROR_IS_OK(status))
8295 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8296 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8298 /* check for OID in valuename */
8300 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8306 /* save the registry data */
8308 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8310 /* save the OID if one was specified and the previous set call succeeded */
8312 if ( W_ERROR_IS_OK(status) && oid_string )
8315 fstrcat( keyname, "\\" );
8316 fstrcat( keyname, SPOOL_OID_KEY );
8319 * I'm not checking the status here on purpose. Don't know
8320 * if this is right, but I'm returning the status from the
8321 * previous set_printer_dataex() call. I have no idea if
8322 * this is right. --jerry
8325 set_printer_dataex( printer, keyname, valuename,
8326 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8329 free_a_printer(&printer, 2);
8335 /********************************************************************
8336 * spoolss_deleteprinterdataex
8337 ********************************************************************/
8339 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8341 POLICY_HND *handle = &q_u->handle;
8342 UNISTR2 *value = &q_u->valuename;
8343 UNISTR2 *key = &q_u->keyname;
8345 NT_PRINTER_INFO_LEVEL *printer = NULL;
8347 WERROR status = WERR_OK;
8348 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8349 pstring valuename, keyname;
8351 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8354 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8358 if (!get_printer_snum(p, handle, &snum))
8361 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8362 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8363 return WERR_ACCESS_DENIED;
8366 status = get_a_printer(&printer, 2, lp_servicename(snum));
8367 if (!W_ERROR_IS_OK(status))
8370 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8371 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8373 status = delete_printer_dataex( printer, keyname, valuename );
8375 free_a_printer(&printer, 2);
8380 /********************************************************************
8381 * spoolss_enumprinterkey
8382 ********************************************************************/
8385 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8388 fstring *keynames = NULL;
8389 uint16 *enumkeys = NULL;
8392 POLICY_HND *handle = &q_u->handle;
8393 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8394 NT_PRINTER_DATA *data;
8395 NT_PRINTER_INFO_LEVEL *printer = NULL;
8397 WERROR status = WERR_BADFILE;
8400 DEBUG(4,("_spoolss_enumprinterkey\n"));
8403 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8407 if ( !get_printer_snum(p,handle, &snum) )
8410 status = get_a_printer(&printer, 2, lp_servicename(snum));
8411 if (!W_ERROR_IS_OK(status))
8414 /* get the list of subkey names */
8416 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8417 data = &printer->info_2->data;
8419 num_keys = get_printer_subkeys( data, key, &keynames );
8421 if ( num_keys == -1 ) {
8422 status = WERR_BADFILE;
8426 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8428 r_u->needed = printerkey_len*2;
8430 if ( q_u->size < r_u->needed ) {
8431 status = WERR_MORE_DATA;
8435 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8436 status = WERR_NOMEM;
8442 if ( q_u->size < r_u->needed )
8443 status = WERR_MORE_DATA;
8446 free_a_printer( &printer, 2 );
8447 SAFE_FREE( keynames );
8452 /********************************************************************
8453 * spoolss_deleteprinterkey
8454 ********************************************************************/
8456 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8458 POLICY_HND *handle = &q_u->handle;
8459 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8461 NT_PRINTER_INFO_LEVEL *printer = NULL;
8465 DEBUG(5,("spoolss_deleteprinterkey\n"));
8468 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8472 /* if keyname == NULL, return error */
8474 if ( !q_u->keyname.buffer )
8475 return WERR_INVALID_PARAM;
8477 if (!get_printer_snum(p, handle, &snum))
8480 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8481 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8482 return WERR_ACCESS_DENIED;
8485 status = get_a_printer(&printer, 2, lp_servicename(snum));
8486 if (!W_ERROR_IS_OK(status))
8489 /* delete the key and all subneys */
8491 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8493 status = delete_all_printer_data( printer->info_2, key );
8495 if ( W_ERROR_IS_OK(status) )
8496 status = mod_a_printer(*printer, 2);
8498 free_a_printer( &printer, 2 );
8504 /********************************************************************
8505 * spoolss_enumprinterdataex
8506 ********************************************************************/
8508 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8510 POLICY_HND *handle = &q_u->handle;
8511 uint32 in_size = q_u->size;
8514 NT_PRINTER_INFO_LEVEL *printer = NULL;
8515 PRINTER_ENUM_VALUES *enum_values = NULL;
8516 NT_PRINTER_DATA *p_data;
8518 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8523 REGISTRY_VALUE *val;
8528 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8531 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8535 /* first get the printer off of disk */
8537 if (!get_printer_snum(p,handle, &snum))
8540 ZERO_STRUCT(printer);
8541 result = get_a_printer(&printer, 2, lp_servicename(snum));
8542 if (!W_ERROR_IS_OK(result))
8545 /* now look for a match on the key name */
8547 p_data = &printer->info_2->data;
8549 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8550 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8552 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8553 result = WERR_INVALID_PARAM;
8560 /* allocate the memory for the array of pointers -- if necessary */
8562 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8565 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8567 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8568 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8569 result = WERR_NOMEM;
8573 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8577 * loop through all params and build the array to pass
8578 * back to the client
8581 for ( i=0; i<num_entries; i++ )
8583 /* lookup the registry value */
8585 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8586 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8590 value_name = regval_name( val );
8591 init_unistr( &enum_values[i].valuename, value_name );
8592 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8593 enum_values[i].type = regval_type( val );
8595 data_len = regval_size( val );
8597 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8599 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8601 result = WERR_NOMEM;
8605 enum_values[i].data_len = data_len;
8607 /* keep track of the size of the array in bytes */
8609 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8612 /* housekeeping information in the reply */
8614 r_u->needed = needed;
8615 r_u->returned = num_entries;
8617 if (needed > in_size) {
8618 result = WERR_MORE_DATA;
8622 /* copy data into the reply */
8624 r_u->ctr.size = r_u->needed;
8625 r_u->ctr.size_of_array = r_u->returned;
8626 r_u->ctr.values = enum_values;
8631 free_a_printer(&printer, 2);
8636 /****************************************************************************
8637 ****************************************************************************/
8639 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8641 init_unistr(&info->name, name);
8644 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8645 UNISTR2 *environment,
8652 pstring short_archi;
8653 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8655 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8657 if (get_short_archi(short_archi, long_archi)==False)
8658 return WERR_INVALID_ENVIRONMENT;
8660 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8663 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8665 fill_printprocessordirectory_1(info, path);
8667 *needed += spoolss_size_printprocessordirectory_info_1(info);
8669 if (!alloc_buffer_size(buffer, *needed)) {
8671 return WERR_INSUFFICIENT_BUFFER;
8674 smb_io_printprocessordirectory_1("", buffer, info, 0);
8678 if (*needed > offered)
8679 return WERR_INSUFFICIENT_BUFFER;
8684 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8686 uint32 level = q_u->level;
8687 NEW_BUFFER *buffer = NULL;
8688 uint32 offered = q_u->offered;
8689 uint32 *needed = &r_u->needed;
8692 /* that's an [in out] buffer */
8693 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8694 buffer = r_u->buffer;
8696 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8702 result = getprintprocessordirectory_level_1
8703 (&q_u->name, &q_u->environment, buffer, offered, needed);
8705 result = WERR_UNKNOWN_LEVEL;
8713 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
8714 SPOOL_R_REPLYOPENPRINTER *r_u)
8716 DEBUG(5,("_spoolss_replyopenprinter\n"));
8718 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
8723 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
8724 SPOOL_R_REPLYCLOSEPRINTER *r_u)
8726 DEBUG(5,("_spoolss_replycloseprinter\n"));