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,
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);
204 /****************************************************************************
205 Functions to free a printer entry datastruct.
206 ****************************************************************************/
208 static void free_printer_entry(void *ptr)
210 Printer_entry *Printer = (Printer_entry *)ptr;
212 if (Printer->notify.client_connected==True)
213 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
215 Printer->notify.flags=0;
216 Printer->notify.options=0;
217 Printer->notify.localmachine[0]='\0';
218 Printer->notify.printerlocal=0;
219 free_spool_notify_option(&Printer->notify.option);
220 Printer->notify.option=NULL;
221 Printer->notify.client_connected=False;
223 /* Remove from the internal list. */
224 DLIST_REMOVE(printers_list, Printer);
229 /****************************************************************************
230 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
231 ****************************************************************************/
233 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
235 SPOOL_NOTIFY_OPTION *new_sp = NULL;
240 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
247 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
249 if (!new_sp->ctr.type) {
258 /****************************************************************************
259 find printer index by handle
260 ****************************************************************************/
262 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
264 Printer_entry *find_printer = NULL;
266 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
267 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
274 /****************************************************************************
275 Close printer index by handle.
276 ****************************************************************************/
278 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
280 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
283 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
287 close_policy_hnd(p, hnd);
292 /****************************************************************************
293 Delete a printer given a handle.
294 ****************************************************************************/
296 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
298 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
301 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
305 if (del_a_printer(Printer->dev.handlename) != 0) {
306 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
310 /* Check calling user has permission to delete printer. Note that
311 since we set the snum parameter to -1 only administrators can
312 delete the printer. This stops people with the Full Control
313 permission from deleting the printer. */
315 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
316 DEBUG(3, ("printer delete denied by security descriptor\n"));
317 return WERR_ACCESS_DENIED;
320 if (*lp_deleteprinter_cmd()) {
322 char *cmd = lp_deleteprinter_cmd();
327 /* Printer->dev.handlename equals portname equals sharename */
328 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
329 Printer->dev.handlename);
331 DEBUG(10,("Running [%s]\n", command));
332 ret = smbrun(command, NULL);
334 return WERR_BADFID; /* What to return here? */
336 DEBUGADD(10,("returned [%d]\n", ret));
338 /* Send SIGHUP to process group... is there a better way? */
341 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
345 return WERR_ACCESS_DENIED;
351 /****************************************************************************
352 Return the snum of a printer corresponding to an handle.
353 ****************************************************************************/
355 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
357 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
360 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
364 switch (Printer->printer_type) {
365 case PRINTER_HANDLE_IS_PRINTER:
366 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
367 *number = print_queue_snum(Printer->dev.handlename);
368 return (*number != -1);
369 case PRINTER_HANDLE_IS_PRINTSERVER:
376 /****************************************************************************
377 Set printer handle type.
378 Check if it's \\server or \\server\printer
379 ****************************************************************************/
381 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
383 DEBUG(3,("Setting printer type=%s\n", handlename));
385 if ( strlen(handlename) < 3 ) {
386 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
390 /* it's a print server */
391 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
392 DEBUGADD(4,("Printer is a print server\n"));
393 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
397 DEBUGADD(4,("Printer is a printer\n"));
398 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
404 /****************************************************************************
405 Set printer handle name.
406 ****************************************************************************/
408 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
411 int n_services=lp_numservices();
416 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
418 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
419 ZERO_STRUCT(Printer->dev.printerservername);
420 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
424 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
427 if (*handlename=='\\') {
428 aprinter=strchr_m(handlename+2, '\\');
435 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
438 * The original code allowed smbd to store a printer name that
439 * was different from the share name. This is not possible
440 * anymore, so I've simplified this loop greatly. Here
441 * we are just verifying that the printer name is a valid
442 * printer service defined in smb.conf
443 * --jerry [Fri Feb 15 11:17:46 CST 2002]
446 for (snum=0; snum<n_services; snum++) {
448 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
451 fstrcpy(sname, lp_servicename(snum));
453 DEBUGADD(5,("share:%s\n",sname));
455 if (! StrCaseCmp(sname, aprinter)) {
464 DEBUGADD(4,("Printer not found\n"));
468 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
470 ZERO_STRUCT(Printer->dev.handlename);
471 fstrcpy(Printer->dev.handlename, sname);
476 /****************************************************************************
477 Find first available printer slot. creates a printer handle for you.
478 ****************************************************************************/
480 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
482 Printer_entry *new_printer;
484 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
486 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
489 ZERO_STRUCTP(new_printer);
491 new_printer->notify.option=NULL;
493 /* Add to the internal list. */
494 DLIST_ADD(printers_list, new_printer);
496 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
497 SAFE_FREE(new_printer);
501 if (!set_printer_hnd_printertype(new_printer, name)) {
502 close_printer_handle(p, hnd);
506 if (!set_printer_hnd_name(new_printer, name)) {
507 close_printer_handle(p, hnd);
511 new_printer->access_granted = access_granted;
513 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
518 /****************************************************************************
519 Allocate more memory for a BUFFER.
520 ****************************************************************************/
522 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
530 /* damn, I'm doing the reverse operation of prs_grow() :) */
531 if (buffer_size < prs_data_size(ps))
534 extra_space = buffer_size - prs_data_size(ps);
537 * save the offset and move to the end of the buffer
538 * prs_grow() checks the extra_space against the offset
540 old_offset=prs_offset(ps);
541 prs_set_offset(ps, prs_data_size(ps));
543 if (!prs_grow(ps, extra_space))
546 prs_set_offset(ps, old_offset);
548 buffer->string_at_end=prs_data_size(ps);
553 /***************************************************************************
554 check to see if the client motify handle is monitoring the notification
555 given by (notify_type, notify_field).
556 **************************************************************************/
558 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
564 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
567 SPOOL_NOTIFY_OPTION *option = p->notify.option;
571 return is_monitoring_event_flags(
572 p->notify.flags, notify_type, notify_field);
574 for (i = 0; i < option->count; i++) {
576 /* Check match for notify_type */
578 if (option->ctr.type[i].type != notify_type)
581 /* Check match for field */
583 for (j = 0; j < option->ctr.type[i].count; j++) {
584 if (option->ctr.type[i].fields[j] == notify_field) {
590 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
591 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
592 p->dev.handlename : p->dev.printerservername,
593 notify_type, notify_field));
598 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
600 static void notify_one_value(struct spoolss_notify_msg *msg,
601 SPOOL_NOTIFY_INFO_DATA *data,
604 data->notify_data.value[0] = msg->notify.value[0];
605 data->notify_data.value[1] = 0;
608 static void notify_string(struct spoolss_notify_msg *msg,
609 SPOOL_NOTIFY_INFO_DATA *data,
614 /* The length of the message includes the trailing \0 */
616 init_unistr2(&unistr, msg->notify.data, msg->len);
618 data->notify_data.data.length = msg->len * 2;
619 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
621 if (!data->notify_data.data.string) {
622 data->notify_data.data.length = 0;
626 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
629 static void notify_system_time(struct spoolss_notify_msg *msg,
630 SPOOL_NOTIFY_INFO_DATA *data,
636 if (msg->len != sizeof(time_t)) {
637 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
642 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
643 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
647 if (!make_systemtime(&systime, localtime((time_t *)msg->notify.data))) {
648 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
652 if (!spoolss_io_system_time("", &ps, 0, &systime))
655 data->notify_data.data.length = prs_offset(&ps);
656 data->notify_data.data.string =
657 talloc(mem_ctx, prs_offset(&ps));
659 memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
664 struct notify2_message_table {
666 void (*fn)(struct spoolss_notify_msg *msg,
667 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
670 static struct notify2_message_table printer_notify_table[] = {
671 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
672 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
673 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
674 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
675 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
676 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
677 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
678 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
679 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
680 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
681 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
682 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
683 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
684 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
685 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
686 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
687 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
688 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
689 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
692 static struct notify2_message_table job_notify_table[] = {
693 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
694 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
695 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
696 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
697 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
698 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
699 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
700 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
701 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
702 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
703 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
704 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
705 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
706 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
707 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
708 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
709 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
710 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
711 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
712 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
713 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
714 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
715 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
716 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
719 /***********************************************************************
720 Send a change notication message on all handles which have a call
722 **********************************************************************/
724 static void process_notify2_message(struct spoolss_notify_msg *msg,
729 DEBUG(8,("process_notify2_message: Enter...[%s]\n", msg->printer));
731 for (p = printers_list; p; p = p->next) {
732 SPOOL_NOTIFY_INFO_DATA *data;
736 /* Is there notification on this handle? */
738 if (!p->notify.client_connected)
741 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
743 /* For this printer? Print servers always receive
746 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
747 ( !strequal(msg->printer, p->dev.handlename) ) )
750 DEBUG(10,("Our printer\n"));
752 /* Are we monitoring this event? */
754 if (!is_monitoring_event(p, msg->type, msg->field))
757 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
758 msg->type, msg->field, p->dev.handlename));
760 /* OK - send the event to the client */
762 data = talloc(mem_ctx, sizeof(SPOOL_NOTIFY_INFO_DATA));
767 * if the is a printer notification handle and not a job notification
768 * type, then set the id to 0. Other wise just use what was specified
771 * When registering change notification on a print server handle
772 * we always need to send back the id (snum) matching the printer
773 * for which the change took place. For change notify registered
774 * on a printer handle, this does not matter and the id should be 0.
779 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
785 /* Convert unix jobid to smb jobid */
787 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
789 id = sysjob_to_jobid(msg->id);
792 DEBUG(3, ("no such unix jobid %d\n", msg->id));
797 construct_info_data(data, msg->type, msg->field, id);
800 case PRINTER_NOTIFY_TYPE:
801 if ( !printer_notify_table[msg->field].fn )
804 printer_notify_table[msg->field].fn(msg, data, mem_ctx);
808 case JOB_NOTIFY_TYPE:
809 if ( !job_notify_table[msg->field].fn )
812 job_notify_table[msg->field].fn(msg, data, mem_ctx);
817 DEBUG(5, ("Unknown notification type %d\n", msg->type));
821 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
822 data_len, data, p->notify.change, 0 );
825 DEBUG(8,("process_notify2_message: Exit...\n"));
829 /* Receive a notify2 message */
831 static void receive_notify2_message(int msg_type, pid_t src, void *buf,
834 struct spoolss_notify_msg msg;
836 TALLOC_CTX *mem_ctx = talloc_init();
842 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
845 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
846 &msg.type, &msg.field, &msg.id, &msg.len, &msg.flags);
849 tdb_unpack((char *)buf + offset, len - offset, "dd",
850 &msg.notify.value[0], &msg.notify.value[1]);
852 tdb_unpack((char *)buf + offset, len - offset, "B",
853 &msg.len, &msg.notify.data);
855 DEBUG(3, ("got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
856 msg.type, msg.field, msg.flags));
859 DEBUG(3, ("value1 = %d, value2 = %d\n", msg.notify.value[0],
860 msg.notify.value[1]));
862 dump_data(3, msg.notify.data, msg.len);
864 /* Process message */
866 process_notify2_message(&msg, mem_ctx);
871 free(msg.notify.data);
873 talloc_destroy(mem_ctx);
876 /********************************************************************
877 Send a message to ourself about new driver being installed
878 so we can upgrade the information for each printer bound to this
880 ********************************************************************/
882 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
884 int len = strlen(drivername);
889 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
892 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
897 /**********************************************************************
898 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
899 over all printers, upgrading ones as neessary
900 **********************************************************************/
902 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
906 int n_services = lp_numservices();
908 len = MIN(len,sizeof(drivername)-1);
909 strncpy(drivername, buf, len);
911 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
913 /* Iterate the printer list */
915 for (snum=0; snum<n_services; snum++)
917 if (lp_snum_ok(snum) && lp_print_ok(snum) )
920 NT_PRINTER_INFO_LEVEL *printer = NULL;
922 result = get_a_printer(&printer, 2, lp_servicename(snum));
923 if (!W_ERROR_IS_OK(result))
926 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
928 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
930 /* all we care about currently is the change_id */
932 result = mod_a_printer(*printer, 2);
933 if (!W_ERROR_IS_OK(result)) {
934 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
935 dos_errstr(result)));
939 free_a_printer(&printer, 2);
946 /********************************************************************
947 Send a message to ourself about new driver being installed
948 so we can upgrade the information for each printer bound to this
950 ********************************************************************/
952 static BOOL srv_spoolss_reset_printerdata(char* drivername)
954 int len = strlen(drivername);
959 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
962 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
967 /**********************************************************************
968 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
969 over all printers, resetting printer data as neessary
970 **********************************************************************/
972 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
976 int n_services = lp_numservices();
978 len = MIN( len, sizeof(drivername)-1 );
979 strncpy( drivername, buf, len );
981 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
983 /* Iterate the printer list */
985 for ( snum=0; snum<n_services; snum++ )
987 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
990 NT_PRINTER_INFO_LEVEL *printer = NULL;
992 result = get_a_printer( &printer, 2, lp_servicename(snum) );
993 if ( !W_ERROR_IS_OK(result) )
997 * if the printer is bound to the driver,
998 * then reset to the new driver initdata
1001 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1003 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1005 if ( !set_driver_init(printer, 2) ) {
1006 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1007 printer->info_2->printername, printer->info_2->drivername));
1011 free_a_printer( &printer, 2 );
1020 /********************************************************************
1021 Copy routines used by convert_to_openprinterex()
1022 *******************************************************************/
1024 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1032 DEBUG (8,("dup_devmode\n"));
1034 /* bulk copy first */
1036 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1040 /* dup the pointer members separately */
1042 len = unistrlen(devmode->devicename.buffer);
1044 d->devicename.buffer = talloc(ctx, len*2);
1045 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1050 len = unistrlen(devmode->formname.buffer);
1052 d->devicename.buffer = talloc(ctx, len*2);
1053 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1057 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1062 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1064 if (!new_ctr || !ctr)
1067 DEBUG(8,("copy_devmode_ctr\n"));
1069 new_ctr->size = ctr->size;
1070 new_ctr->devmode_ptr = ctr->devmode_ptr;
1072 if(ctr->devmode_ptr)
1073 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1076 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1078 if (!new_def || !def)
1081 DEBUG(8,("copy_printer_defaults\n"));
1083 new_def->datatype_ptr = def->datatype_ptr;
1085 if (def->datatype_ptr)
1086 copy_unistr2(&new_def->datatype, &def->datatype);
1088 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1090 new_def->access_required = def->access_required;
1093 /********************************************************************
1094 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1095 * SPOOL_Q_OPEN_PRINTER_EX structure
1096 ********************************************************************/
1098 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1100 if (!q_u_ex || !q_u)
1103 DEBUG(8,("convert_to_openprinterex\n"));
1105 q_u_ex->printername_ptr = q_u->printername_ptr;
1107 if (q_u->printername_ptr)
1108 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1110 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1113 /********************************************************************
1114 * spoolss_open_printer
1116 * called from the spoolss dispatcher
1117 ********************************************************************/
1119 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1121 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1122 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1127 ZERO_STRUCT(q_u_ex);
1128 ZERO_STRUCT(r_u_ex);
1130 /* convert the OpenPrinter() call to OpenPrinterEx() */
1132 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1134 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1136 /* convert back to OpenPrinter() */
1138 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1143 /********************************************************************
1144 * spoolss_open_printer
1146 * called from the spoolss dispatcher
1147 ********************************************************************/
1149 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1151 UNISTR2 *printername = NULL;
1152 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1153 POLICY_HND *handle = &r_u->handle;
1157 struct current_user user;
1158 Printer_entry *Printer=NULL;
1160 if (q_u->printername_ptr != 0)
1161 printername = &q_u->printername;
1163 if (printername == NULL)
1164 return WERR_INVALID_PRINTER_NAME;
1166 /* some sanity check because you can open a printer or a print server */
1167 /* aka: \\server\printer or \\server */
1168 unistr2_to_ascii(name, printername, sizeof(name)-1);
1170 DEBUGADD(3,("checking name: %s\n",name));
1172 if (!open_printer_hnd(p, handle, name, 0))
1173 return WERR_INVALID_PRINTER_NAME;
1175 Printer=find_printer_index_by_hnd(p, handle);
1177 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1178 Can't find printer handle we created for printer %s\n", name ));
1179 close_printer_handle(p,handle);
1180 return WERR_INVALID_PRINTER_NAME;
1184 First case: the user is opening the print server:
1186 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1187 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1189 Then both Win2k and WinNT clients try an OpenPrinterEx with
1190 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1191 or if the user is listed in the smb.conf printer admin parameter.
1193 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1194 client view printer folder, but does not show the MSAPW.
1196 Note: this test needs code to check access rights here too. Jeremy
1197 could you look at this?
1200 Second case: the user is opening a printer:
1201 NT doesn't let us connect to a printer if the connecting user
1202 doesn't have print permission.
1206 get_current_user(&user, p);
1208 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
1210 /* Printserver handles use global struct... */
1214 /* Map standard access rights to object specific access
1217 se_map_standard(&printer_default->access_required,
1218 &printserver_std_mapping);
1220 /* Deny any object specific bits that don't apply to print
1221 servers (i.e printer and job specific bits) */
1223 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1225 if (printer_default->access_required &
1226 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1227 DEBUG(3, ("access DENIED for non-printserver bits"));
1228 close_printer_handle(p, handle);
1229 return WERR_ACCESS_DENIED;
1232 /* Allow admin access */
1234 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1237 if (!lp_ms_add_printer_wizard()) {
1238 close_printer_handle(p, handle);
1239 return WERR_ACCESS_DENIED;
1242 if (user.uid == 0 ||
1243 user_in_list(uidtoname(user.uid),
1244 lp_printer_admin(snum)))
1247 close_printer_handle(p, handle);
1248 return WERR_ACCESS_DENIED;
1251 /* We fall through to return WERR_OK */
1256 /* NT doesn't let us connect to a printer if the connecting user
1257 doesn't have print permission. */
1259 if (!get_printer_snum(p, handle, &snum))
1262 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1264 /* map an empty access mask to the minimum access mask */
1265 if (printer_default->access_required == 0x0)
1266 printer_default->access_required = PRINTER_ACCESS_USE;
1269 * If we are not serving the printer driver for this printer,
1270 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1271 * will keep NT clients happy --jerry
1274 if (lp_use_client_driver(snum)
1275 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1277 printer_default->access_required = PRINTER_ACCESS_USE;
1280 /* check smb.conf parameters and the the sec_desc */
1282 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1283 DEBUG(3, ("access DENIED for printer open\n"));
1284 close_printer_handle(p, handle);
1285 return WERR_ACCESS_DENIED;
1288 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1289 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1290 close_printer_handle(p, handle);
1291 return WERR_ACCESS_DENIED;
1294 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1295 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1297 printer_default->access_required = PRINTER_ACCESS_USE;
1299 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1300 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1302 Printer->access_granted = printer_default->access_required;
1305 * If we have a default device pointer in the
1306 * printer_default struct, then we need to get
1307 * the printer info from the tdb and if there is
1308 * no default devicemode there then we do a *SET*
1309 * here ! This is insanity.... JRA.
1313 * If the openprinterex rpc call contains a devmode,
1314 * it's a per-user one. This per-user devmode is derivated
1315 * from the global devmode. Openprinterex() contains a per-user
1316 * devmode for when you do EMF printing and spooling.
1317 * In the EMF case, the NT workstation is only doing half the job
1318 * of rendering the page. The other half is done by running the printer
1319 * driver on the server.
1320 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1321 * The EMF file only contains what is to be printed on the page.
1322 * So in order for the server to know how to print, the NT client sends
1323 * a devicemode attached to the openprinterex call.
1324 * But this devicemode is short lived, it's only valid for the current print job.
1326 * If Samba would have supported EMF spooling, this devicemode would
1327 * have been attached to the handle, to sent it to the driver to correctly
1328 * rasterize the EMF file.
1330 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1331 * we just act as a pass-thru between windows and the printer.
1333 * In order to know that Samba supports only RAW spooling, NT has to call
1334 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1335 * and until NT sends a RAW job, we refuse it.
1337 * But to call getprinter() or startdoc(), you first need a valid handle,
1338 * and to get an handle you have to call openprintex(). Hence why you have
1339 * a devicemode in the openprinterex() call.
1342 * Differences between NT4 and NT 2000.
1345 * On NT4, you only have a global devicemode. This global devicemode can be changed
1346 * by the administrator (or by a user with enough privs). Everytime a user
1347 * wants to print, the devicemode is resetted to the default. In Word, everytime
1348 * you print, the printer's characteristics are always reset to the global devicemode.
1352 * In W2K, there is the notion of per-user devicemode. The first time you use
1353 * a printer, a per-user devicemode is build from the global devicemode.
1354 * If you change your per-user devicemode, it is saved in the registry, under the
1355 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1356 * printer preferences available.
1358 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1359 * on the General Tab of the printer properties windows.
1361 * To change the global devicemode: it's the "Printing Defaults..." button
1362 * on the Advanced Tab of the printer properties window.
1370 if (printer_default->devmode_cont.devmode != NULL) {
1371 result = printer_write_default_dev( snum, printer_default);
1373 close_printer_handle(p, handle);
1383 /****************************************************************************
1384 ****************************************************************************/
1386 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1387 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1393 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1402 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1403 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1409 printer->info_3=NULL;
1410 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1414 printer->info_6=NULL;
1415 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1425 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1426 NT_DEVICEMODE **pp_nt_devmode)
1428 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1431 * Ensure nt_devmode is a valid pointer
1432 * as we will be overwriting it.
1435 if (nt_devmode == NULL) {
1436 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1437 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1441 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1442 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1444 nt_devmode->specversion=devmode->specversion;
1445 nt_devmode->driverversion=devmode->driverversion;
1446 nt_devmode->size=devmode->size;
1447 nt_devmode->fields=devmode->fields;
1448 nt_devmode->orientation=devmode->orientation;
1449 nt_devmode->papersize=devmode->papersize;
1450 nt_devmode->paperlength=devmode->paperlength;
1451 nt_devmode->paperwidth=devmode->paperwidth;
1452 nt_devmode->scale=devmode->scale;
1453 nt_devmode->copies=devmode->copies;
1454 nt_devmode->defaultsource=devmode->defaultsource;
1455 nt_devmode->printquality=devmode->printquality;
1456 nt_devmode->color=devmode->color;
1457 nt_devmode->duplex=devmode->duplex;
1458 nt_devmode->yresolution=devmode->yresolution;
1459 nt_devmode->ttoption=devmode->ttoption;
1460 nt_devmode->collate=devmode->collate;
1462 nt_devmode->logpixels=devmode->logpixels;
1463 nt_devmode->bitsperpel=devmode->bitsperpel;
1464 nt_devmode->pelswidth=devmode->pelswidth;
1465 nt_devmode->pelsheight=devmode->pelsheight;
1466 nt_devmode->displayflags=devmode->displayflags;
1467 nt_devmode->displayfrequency=devmode->displayfrequency;
1468 nt_devmode->icmmethod=devmode->icmmethod;
1469 nt_devmode->icmintent=devmode->icmintent;
1470 nt_devmode->mediatype=devmode->mediatype;
1471 nt_devmode->dithertype=devmode->dithertype;
1472 nt_devmode->reserved1=devmode->reserved1;
1473 nt_devmode->reserved2=devmode->reserved2;
1474 nt_devmode->panningwidth=devmode->panningwidth;
1475 nt_devmode->panningheight=devmode->panningheight;
1478 * Only change private and driverextra if the incoming devmode
1479 * has a new one. JRA.
1482 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1483 SAFE_FREE(nt_devmode->private);
1484 nt_devmode->driverextra=devmode->driverextra;
1485 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1487 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1490 *pp_nt_devmode = nt_devmode;
1495 /********************************************************************
1496 * _spoolss_enddocprinter_internal.
1497 ********************************************************************/
1499 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1501 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1505 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1509 if (!get_printer_snum(p, handle, &snum))
1512 Printer->document_started=False;
1513 print_job_end(snum, Printer->jobid,True);
1514 /* error codes unhandled so far ... */
1519 /********************************************************************
1520 * api_spoolss_closeprinter
1521 ********************************************************************/
1523 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1525 POLICY_HND *handle = &q_u->handle;
1527 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1529 if (Printer && Printer->document_started)
1530 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1532 if (!close_printer_handle(p, handle))
1535 /* clear the returned printer handle. Observed behavior
1536 from Win2k server. Don't think this really matters.
1537 Previous code just copied the value of the closed
1540 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1545 /********************************************************************
1546 * api_spoolss_deleteprinter
1548 ********************************************************************/
1550 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1552 POLICY_HND *handle = &q_u->handle;
1553 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1556 if (Printer && Printer->document_started)
1557 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1559 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1561 result = delete_printer_handle(p, handle);
1563 update_c_setprinter(False);
1568 /*******************************************************************
1569 * static function to lookup the version id corresponding to an
1570 * long architecture string
1571 ******************************************************************/
1573 static int get_version_id (char * arch)
1576 struct table_node archi_table[]= {
1578 {"Windows 4.0", "WIN40", 0 },
1579 {"Windows NT x86", "W32X86", 2 },
1580 {"Windows NT R4000", "W32MIPS", 2 },
1581 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1582 {"Windows NT PowerPC", "W32PPC", 2 },
1586 for (i=0; archi_table[i].long_archi != NULL; i++)
1588 if (strcmp(arch, archi_table[i].long_archi) == 0)
1589 return (archi_table[i].version);
1595 /********************************************************************
1596 * _spoolss_deleteprinterdriver
1597 ********************************************************************/
1599 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1603 NT_PRINTER_DRIVER_INFO_LEVEL info;
1605 struct current_user user;
1607 get_current_user(&user, p);
1609 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1610 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1612 /* check that we have a valid driver name first */
1613 if ((version=get_version_id(arch)) == -1) {
1614 /* this is what NT returns */
1615 return WERR_INVALID_ENVIRONMENT;
1618 /* if they said "Windows NT x86", then try for version 2 & 3 */
1621 version = DRIVER_ANY_VERSION;
1625 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1626 return WERR_UNKNOWN_PRINTER_DRIVER;
1628 if (printer_driver_in_use(info.info_3))
1629 return WERR_PRINTER_DRIVER_IN_USE;
1631 return delete_printer_driver(info.info_3, &user, DRIVER_ANY_VERSION, False);
1634 /********************************************************************
1635 * spoolss_deleteprinterdriverex
1636 ********************************************************************/
1638 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1642 NT_PRINTER_DRIVER_INFO_LEVEL info;
1644 uint32 flags = q_u->delete_flags;
1646 struct current_user user;
1648 get_current_user(&user, p);
1650 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1651 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1653 /* check that we have a valid driver name first */
1654 if ((version=get_version_id(arch)) == -1) {
1655 /* this is what NT returns */
1656 return WERR_INVALID_ENVIRONMENT;
1659 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
1660 version = q_u->version;
1661 else if ( version == 2 )
1662 /* if they said "Windows NT x86", then try for version 2 & 3 */
1663 version = DRIVER_ANY_VERSION;
1667 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1668 return WERR_UNKNOWN_PRINTER_DRIVER;
1670 if ( printer_driver_in_use(info.info_3) )
1671 return WERR_PRINTER_DRIVER_IN_USE;
1674 * we have a couple of cases to consider.
1675 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1676 * then the delete should fail if **any** files overlap with
1678 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1679 * non-overlapping files
1680 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1681 * is set, the do not delete any files
1682 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1685 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1689 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1691 if ( printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) )
1692 /* no idea of the correct error here */
1693 return WERR_ACCESS_DENIED;
1696 return delete_printer_driver(info.info_3, &user, version, delete_files);
1700 /****************************************************************************
1701 Internal routine for retreiving printerdata
1702 ***************************************************************************/
1704 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
1705 char *key, char *value, uint32 *type, uint8 **data,
1706 uint32 *needed, uint32 in_size )
1708 REGISTRY_VALUE *val;
1711 if ( !(val = get_printer_data( printer->info_2, key, value)) )
1712 return WERR_BADFILE;
1714 *type = regval_type( val );
1716 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
1718 size = regval_size( val );
1720 /* copy the min(in_size, len) */
1723 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
1724 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
1732 DEBUG(5,("get_printer_dataex: copy done\n"));
1737 /****************************************************************************
1738 Internal routine for storing printerdata
1739 ***************************************************************************/
1741 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value,
1742 uint32 type, uint8 *data, int real_len )
1744 delete_printer_data( printer->info_2, key, value );
1746 add_printer_data( printer->info_2, key, value, type, data, real_len );
1748 return mod_a_printer(*printer, 2);
1751 /********************************************************************
1752 GetPrinterData on a printer server Handle.
1753 ********************************************************************/
1755 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1759 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1761 if (!strcmp(value, "W3SvcInstalled")) {
1763 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
1769 if (!strcmp(value, "BeepEnabled")) {
1771 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1773 SIVAL(*data, 0, 0x00);
1778 if (!strcmp(value, "EventLog")) {
1780 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1782 /* formally was 0x1b */
1783 SIVAL(*data, 0, 0x0);
1788 if (!strcmp(value, "NetPopup")) {
1790 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1792 SIVAL(*data, 0, 0x00);
1797 if (!strcmp(value, "MajorVersion")) {
1799 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1801 #ifndef EMULATE_WIN2K_HACK /* JERRY */
1810 if (!strcmp(value, "DefaultSpoolDirectory")) {
1813 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1815 *needed = 2*(strlen(string)+1);
1816 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1818 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1820 /* it's done by hand ready to go on the wire */
1821 for (i=0; i<strlen(string); i++) {
1822 (*data)[2*i]=string[i];
1823 (*data)[2*i+1]='\0';
1828 if (!strcmp(value, "Architecture")) {
1829 pstring string="Windows NT x86";
1831 *needed = 2*(strlen(string)+1);
1832 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1834 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1835 for (i=0; i<strlen(string); i++) {
1836 (*data)[2*i]=string[i];
1837 (*data)[2*i+1]='\0';
1842 return WERR_INVALID_PARAM;
1845 /********************************************************************
1846 * spoolss_getprinterdata
1847 ********************************************************************/
1849 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1851 POLICY_HND *handle = &q_u->handle;
1852 UNISTR2 *valuename = &q_u->valuename;
1853 uint32 in_size = q_u->size;
1854 uint32 *type = &r_u->type;
1855 uint32 *out_size = &r_u->size;
1856 uint8 **data = &r_u->data;
1857 uint32 *needed = &r_u->needed;
1860 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1861 NT_PRINTER_INFO_LEVEL *printer = NULL;
1865 * Reminder: when it's a string, the length is in BYTES
1866 * even if UNICODE is negociated.
1871 *out_size = in_size;
1873 /* in case of problem, return some default values */
1878 DEBUG(4,("_spoolss_getprinterdata\n"));
1881 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1883 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1887 if ( !get_printer_snum(p,handle, &snum) )
1890 status = get_a_printer(&printer, 2, lp_servicename(snum));
1891 if ( !W_ERROR_IS_OK(status) )
1894 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1896 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
1897 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
1899 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, in_size );
1901 if ( !W_ERROR_IS_OK(status) )
1903 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1905 /* reply this param doesn't exist */
1908 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1915 if (*needed > *out_size)
1916 status = WERR_MORE_DATA;
1918 /* cleanup & exit */
1920 free_a_printer( &printer, 2 );
1925 /*********************************************************
1926 Connect to the client machine.
1927 **********************************************************/
1929 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, char *remote_machine)
1931 extern pstring global_myname;
1933 ZERO_STRUCTP(the_cli);
1934 if(cli_initialise(the_cli) == NULL) {
1935 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
1939 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
1940 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
1941 cli_shutdown(the_cli);
1945 if (ismyip(the_cli->dest_ip)) {
1946 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
1947 cli_shutdown(the_cli);
1951 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
1952 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1953 cli_shutdown(the_cli);
1957 if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
1958 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
1963 the_cli->protocol = PROTOCOL_NT1;
1965 if (!cli_negprot(the_cli)) {
1966 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1967 cli_shutdown(the_cli);
1971 if (the_cli->protocol != PROTOCOL_NT1) {
1972 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
1973 cli_shutdown(the_cli);
1978 * Do an anonymous session setup.
1981 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
1982 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1983 cli_shutdown(the_cli);
1987 if (!(the_cli->sec_mode & 1)) {
1988 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
1989 cli_shutdown(the_cli);
1993 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
1994 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1995 cli_shutdown(the_cli);
2000 * Ok - we have an anonymous connection to the IPC$ share.
2001 * Now start the NT Domain stuff :-).
2004 if(cli_nt_session_open(the_cli, PIPE_SPOOLSS) == False) {
2005 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)));
2006 cli_nt_session_close(the_cli);
2007 cli_ulogoff(the_cli);
2008 cli_shutdown(the_cli);
2015 /***************************************************************************
2016 Connect to the client.
2017 ****************************************************************************/
2019 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2024 * If it's the first connection, contact the client
2025 * and connect to the IPC$ share anonumously
2027 if (smb_connections==0) {
2028 fstring unix_printer;
2030 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2032 if(!spoolss_connect_to_client(¬ify_cli, unix_printer))
2035 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message);
2040 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2043 if (!W_ERROR_IS_OK(result))
2044 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2045 dos_errstr(result)));
2047 return (W_ERROR_IS_OK(result));
2050 /********************************************************************
2052 * ReplyFindFirstPrinterChangeNotifyEx
2054 * before replying OK: status=0 a rpc call is made to the workstation
2055 * asking ReplyOpenPrinter
2057 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2058 * called from api_spoolss_rffpcnex
2059 ********************************************************************/
2061 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2063 POLICY_HND *handle = &q_u->handle;
2064 uint32 flags = q_u->flags;
2065 uint32 options = q_u->options;
2066 UNISTR2 *localmachine = &q_u->localmachine;
2067 uint32 printerlocal = q_u->printerlocal;
2068 SPOOL_NOTIFY_OPTION *option = q_u->option;
2070 /* store the notify value in the printer struct */
2072 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2075 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2079 Printer->notify.flags=flags;
2080 Printer->notify.options=options;
2081 Printer->notify.printerlocal=printerlocal;
2083 if (Printer->notify.option)
2084 free_spool_notify_option(&Printer->notify.option);
2086 Printer->notify.option=dup_spool_notify_option(option);
2088 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2089 sizeof(Printer->notify.localmachine)-1);
2091 /* Connect to the client machine and send a ReplyOpenPrinter */
2093 if(!srv_spoolss_replyopenprinter(Printer->notify.localmachine,
2094 Printer->notify.printerlocal, 1,
2095 &Printer->notify.client_hnd))
2096 return WERR_SERVER_UNAVAILABLE;
2098 Printer->notify.client_connected=True;
2103 /*******************************************************************
2104 * fill a notify_info_data with the servername
2105 ********************************************************************/
2107 void spoolss_notify_server_name(int snum,
2108 SPOOL_NOTIFY_INFO_DATA *data,
2109 print_queue_struct *queue,
2110 NT_PRINTER_INFO_LEVEL *printer,
2111 TALLOC_CTX *mem_ctx)
2113 pstring temp_name, temp;
2116 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2118 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2120 data->notify_data.data.length = len;
2121 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2123 if (!data->notify_data.data.string) {
2124 data->notify_data.data.length = 0;
2128 memcpy(data->notify_data.data.string, temp, len);
2131 /*******************************************************************
2132 * fill a notify_info_data with the printername (not including the servername).
2133 ********************************************************************/
2135 void spoolss_notify_printer_name(int snum,
2136 SPOOL_NOTIFY_INFO_DATA *data,
2137 print_queue_struct *queue,
2138 NT_PRINTER_INFO_LEVEL *printer,
2139 TALLOC_CTX *mem_ctx)
2144 /* the notify name should not contain the \\server\ part */
2145 char *p = strrchr(printer->info_2->printername, '\\');
2148 p = printer->info_2->printername;
2153 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2155 data->notify_data.data.length = len;
2156 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2158 if (!data->notify_data.data.string) {
2159 data->notify_data.data.length = 0;
2163 memcpy(data->notify_data.data.string, temp, len);
2166 /*******************************************************************
2167 * fill a notify_info_data with the servicename
2168 ********************************************************************/
2170 void spoolss_notify_share_name(int snum,
2171 SPOOL_NOTIFY_INFO_DATA *data,
2172 print_queue_struct *queue,
2173 NT_PRINTER_INFO_LEVEL *printer,
2174 TALLOC_CTX *mem_ctx)
2179 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2181 data->notify_data.data.length = len;
2182 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2184 if (!data->notify_data.data.string) {
2185 data->notify_data.data.length = 0;
2189 memcpy(data->notify_data.data.string, temp, len);
2192 /*******************************************************************
2193 * fill a notify_info_data with the port name
2194 ********************************************************************/
2196 void spoolss_notify_port_name(int snum,
2197 SPOOL_NOTIFY_INFO_DATA *data,
2198 print_queue_struct *queue,
2199 NT_PRINTER_INFO_LEVEL *printer,
2200 TALLOC_CTX *mem_ctx)
2205 /* even if it's strange, that's consistant in all the code */
2207 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2209 data->notify_data.data.length = len;
2210 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2212 if (!data->notify_data.data.string) {
2213 data->notify_data.data.length = 0;
2217 memcpy(data->notify_data.data.string, temp, len);
2220 /*******************************************************************
2221 * fill a notify_info_data with the printername
2222 * but it doesn't exist, have to see what to do
2223 ********************************************************************/
2225 void spoolss_notify_driver_name(int snum,
2226 SPOOL_NOTIFY_INFO_DATA *data,
2227 print_queue_struct *queue,
2228 NT_PRINTER_INFO_LEVEL *printer,
2229 TALLOC_CTX *mem_ctx)
2234 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2236 data->notify_data.data.length = len;
2237 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2239 if (!data->notify_data.data.string) {
2240 data->notify_data.data.length = 0;
2244 memcpy(data->notify_data.data.string, temp, len);
2247 /*******************************************************************
2248 * fill a notify_info_data with the comment
2249 ********************************************************************/
2251 void spoolss_notify_comment(int snum,
2252 SPOOL_NOTIFY_INFO_DATA *data,
2253 print_queue_struct *queue,
2254 NT_PRINTER_INFO_LEVEL *printer,
2255 TALLOC_CTX *mem_ctx)
2260 if (*printer->info_2->comment == '\0')
2261 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2263 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2265 data->notify_data.data.length = len;
2266 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2268 if (!data->notify_data.data.string) {
2269 data->notify_data.data.length = 0;
2273 memcpy(data->notify_data.data.string, temp, len);
2276 /*******************************************************************
2277 * fill a notify_info_data with the comment
2278 * location = "Room 1, floor 2, building 3"
2279 ********************************************************************/
2281 void spoolss_notify_location(int snum,
2282 SPOOL_NOTIFY_INFO_DATA *data,
2283 print_queue_struct *queue,
2284 NT_PRINTER_INFO_LEVEL *printer,
2285 TALLOC_CTX *mem_ctx)
2290 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2292 data->notify_data.data.length = len;
2293 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2295 if (!data->notify_data.data.string) {
2296 data->notify_data.data.length = 0;
2300 memcpy(data->notify_data.data.string, temp, len);
2303 /*******************************************************************
2304 * fill a notify_info_data with the device mode
2305 * jfm:xxxx don't to it for know but that's a real problem !!!
2306 ********************************************************************/
2308 static void spoolss_notify_devmode(int snum,
2309 SPOOL_NOTIFY_INFO_DATA *data,
2310 print_queue_struct *queue,
2311 NT_PRINTER_INFO_LEVEL *printer,
2312 TALLOC_CTX *mem_ctx)
2316 /*******************************************************************
2317 * fill a notify_info_data with the separator file name
2318 ********************************************************************/
2320 void spoolss_notify_sepfile(int snum,
2321 SPOOL_NOTIFY_INFO_DATA *data,
2322 print_queue_struct *queue,
2323 NT_PRINTER_INFO_LEVEL *printer,
2324 TALLOC_CTX *mem_ctx)
2329 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2331 data->notify_data.data.length = len;
2332 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2334 if (!data->notify_data.data.string) {
2335 data->notify_data.data.length = 0;
2339 memcpy(data->notify_data.data.string, temp, len);
2342 /*******************************************************************
2343 * fill a notify_info_data with the print processor
2344 * jfm:xxxx return always winprint to indicate we don't do anything to it
2345 ********************************************************************/
2347 void spoolss_notify_print_processor(int snum,
2348 SPOOL_NOTIFY_INFO_DATA *data,
2349 print_queue_struct *queue,
2350 NT_PRINTER_INFO_LEVEL *printer,
2351 TALLOC_CTX *mem_ctx)
2356 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2358 data->notify_data.data.length = len;
2359 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2361 if (!data->notify_data.data.string) {
2362 data->notify_data.data.length = 0;
2366 memcpy(data->notify_data.data.string, temp, len);
2369 /*******************************************************************
2370 * fill a notify_info_data with the print processor options
2371 * jfm:xxxx send an empty string
2372 ********************************************************************/
2374 void spoolss_notify_parameters(int snum,
2375 SPOOL_NOTIFY_INFO_DATA *data,
2376 print_queue_struct *queue,
2377 NT_PRINTER_INFO_LEVEL *printer,
2378 TALLOC_CTX *mem_ctx)
2383 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2385 data->notify_data.data.length = len;
2386 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2388 if (!data->notify_data.data.string) {
2389 data->notify_data.data.length = 0;
2393 memcpy(data->notify_data.data.string, temp, len);
2396 /*******************************************************************
2397 * fill a notify_info_data with the data type
2398 * jfm:xxxx always send RAW as data type
2399 ********************************************************************/
2401 void spoolss_notify_datatype(int snum,
2402 SPOOL_NOTIFY_INFO_DATA *data,
2403 print_queue_struct *queue,
2404 NT_PRINTER_INFO_LEVEL *printer,
2405 TALLOC_CTX *mem_ctx)
2410 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2412 data->notify_data.data.length = len;
2413 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2415 if (!data->notify_data.data.string) {
2416 data->notify_data.data.length = 0;
2420 memcpy(data->notify_data.data.string, temp, len);
2423 /*******************************************************************
2424 * fill a notify_info_data with the security descriptor
2425 * jfm:xxxx send an null pointer to say no security desc
2426 * have to implement security before !
2427 ********************************************************************/
2429 static void spoolss_notify_security_desc(int snum,
2430 SPOOL_NOTIFY_INFO_DATA *data,
2431 print_queue_struct *queue,
2432 NT_PRINTER_INFO_LEVEL *printer,
2433 TALLOC_CTX *mem_ctx)
2435 data->notify_data.data.string = NULL;
2436 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2437 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2440 /*******************************************************************
2441 * fill a notify_info_data with the attributes
2442 * jfm:xxxx a samba printer is always shared
2443 ********************************************************************/
2445 void spoolss_notify_attributes(int snum,
2446 SPOOL_NOTIFY_INFO_DATA *data,
2447 print_queue_struct *queue,
2448 NT_PRINTER_INFO_LEVEL *printer,
2449 TALLOC_CTX *mem_ctx)
2451 data->notify_data.value[0] = printer->info_2->attributes;
2452 data->notify_data.value[1] = 0;
2455 /*******************************************************************
2456 * fill a notify_info_data with the priority
2457 ********************************************************************/
2459 static void spoolss_notify_priority(int snum,
2460 SPOOL_NOTIFY_INFO_DATA *data,
2461 print_queue_struct *queue,
2462 NT_PRINTER_INFO_LEVEL *printer,
2463 TALLOC_CTX *mem_ctx)
2465 data->notify_data.value[0] = printer->info_2->priority;
2466 data->notify_data.value[1] = 0;
2469 /*******************************************************************
2470 * fill a notify_info_data with the default priority
2471 ********************************************************************/
2473 static void spoolss_notify_default_priority(int snum,
2474 SPOOL_NOTIFY_INFO_DATA *data,
2475 print_queue_struct *queue,
2476 NT_PRINTER_INFO_LEVEL *printer,
2477 TALLOC_CTX *mem_ctx)
2479 data->notify_data.value[0] = printer->info_2->default_priority;
2480 data->notify_data.value[1] = 0;
2483 /*******************************************************************
2484 * fill a notify_info_data with the start time
2485 ********************************************************************/
2487 static void spoolss_notify_start_time(int snum,
2488 SPOOL_NOTIFY_INFO_DATA *data,
2489 print_queue_struct *queue,
2490 NT_PRINTER_INFO_LEVEL *printer,
2491 TALLOC_CTX *mem_ctx)
2493 data->notify_data.value[0] = printer->info_2->starttime;
2494 data->notify_data.value[1] = 0;
2497 /*******************************************************************
2498 * fill a notify_info_data with the until time
2499 ********************************************************************/
2501 static void spoolss_notify_until_time(int snum,
2502 SPOOL_NOTIFY_INFO_DATA *data,
2503 print_queue_struct *queue,
2504 NT_PRINTER_INFO_LEVEL *printer,
2505 TALLOC_CTX *mem_ctx)
2507 data->notify_data.value[0] = printer->info_2->untiltime;
2508 data->notify_data.value[1] = 0;
2511 /*******************************************************************
2512 * fill a notify_info_data with the status
2513 ********************************************************************/
2515 static void spoolss_notify_status(int snum,
2516 SPOOL_NOTIFY_INFO_DATA *data,
2517 print_queue_struct *queue,
2518 NT_PRINTER_INFO_LEVEL *printer,
2519 TALLOC_CTX *mem_ctx)
2521 print_status_struct status;
2523 print_queue_length(snum, &status);
2524 data->notify_data.value[0]=(uint32) status.status;
2525 data->notify_data.value[1] = 0;
2528 /*******************************************************************
2529 * fill a notify_info_data with the number of jobs queued
2530 ********************************************************************/
2532 void spoolss_notify_cjobs(int snum,
2533 SPOOL_NOTIFY_INFO_DATA *data,
2534 print_queue_struct *queue,
2535 NT_PRINTER_INFO_LEVEL *printer,
2536 TALLOC_CTX *mem_ctx)
2538 data->notify_data.value[0] = print_queue_length(snum, NULL);
2539 data->notify_data.value[1] = 0;
2542 /*******************************************************************
2543 * fill a notify_info_data with the average ppm
2544 ********************************************************************/
2546 static void spoolss_notify_average_ppm(int snum,
2547 SPOOL_NOTIFY_INFO_DATA *data,
2548 print_queue_struct *queue,
2549 NT_PRINTER_INFO_LEVEL *printer,
2550 TALLOC_CTX *mem_ctx)
2552 /* always respond 8 pages per minutes */
2553 /* a little hard ! */
2554 data->notify_data.value[0] = printer->info_2->averageppm;
2555 data->notify_data.value[1] = 0;
2558 /*******************************************************************
2559 * fill a notify_info_data with username
2560 ********************************************************************/
2562 static void spoolss_notify_username(int snum,
2563 SPOOL_NOTIFY_INFO_DATA *data,
2564 print_queue_struct *queue,
2565 NT_PRINTER_INFO_LEVEL *printer,
2566 TALLOC_CTX *mem_ctx)
2571 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2573 data->notify_data.data.length = len;
2574 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2576 if (!data->notify_data.data.string) {
2577 data->notify_data.data.length = 0;
2581 memcpy(data->notify_data.data.string, temp, len);
2584 /*******************************************************************
2585 * fill a notify_info_data with job status
2586 ********************************************************************/
2588 static void spoolss_notify_job_status(int snum,
2589 SPOOL_NOTIFY_INFO_DATA *data,
2590 print_queue_struct *queue,
2591 NT_PRINTER_INFO_LEVEL *printer,
2592 TALLOC_CTX *mem_ctx)
2594 data->notify_data.value[0]=nt_printj_status(queue->status);
2595 data->notify_data.value[1] = 0;
2598 /*******************************************************************
2599 * fill a notify_info_data with job name
2600 ********************************************************************/
2602 static void spoolss_notify_job_name(int snum,
2603 SPOOL_NOTIFY_INFO_DATA *data,
2604 print_queue_struct *queue,
2605 NT_PRINTER_INFO_LEVEL *printer,
2606 TALLOC_CTX *mem_ctx)
2611 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
2613 data->notify_data.data.length = len;
2614 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2616 if (!data->notify_data.data.string) {
2617 data->notify_data.data.length = 0;
2621 memcpy(data->notify_data.data.string, temp, len);
2624 /*******************************************************************
2625 * fill a notify_info_data with job status
2626 ********************************************************************/
2628 static void spoolss_notify_job_status_string(int snum,
2629 SPOOL_NOTIFY_INFO_DATA *data,
2630 print_queue_struct *queue,
2631 NT_PRINTER_INFO_LEVEL *printer,
2632 TALLOC_CTX *mem_ctx)
2635 * Now we're returning job status codes we just return a "" here. JRA.
2642 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2645 switch (queue->status) {
2650 p = ""; /* NT provides the paused string */
2659 #endif /* NO LONGER NEEDED. */
2661 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
2663 data->notify_data.data.length = len;
2664 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2666 if (!data->notify_data.data.string) {
2667 data->notify_data.data.length = 0;
2671 memcpy(data->notify_data.data.string, temp, len);
2674 /*******************************************************************
2675 * fill a notify_info_data with job time
2676 ********************************************************************/
2678 static void spoolss_notify_job_time(int snum,
2679 SPOOL_NOTIFY_INFO_DATA *data,
2680 print_queue_struct *queue,
2681 NT_PRINTER_INFO_LEVEL *printer,
2682 TALLOC_CTX *mem_ctx)
2684 data->notify_data.value[0]=0x0;
2685 data->notify_data.value[1]=0;
2688 /*******************************************************************
2689 * fill a notify_info_data with job size
2690 ********************************************************************/
2692 static void spoolss_notify_job_size(int snum,
2693 SPOOL_NOTIFY_INFO_DATA *data,
2694 print_queue_struct *queue,
2695 NT_PRINTER_INFO_LEVEL *printer,
2696 TALLOC_CTX *mem_ctx)
2698 data->notify_data.value[0]=queue->size;
2699 data->notify_data.value[1]=0;
2702 /*******************************************************************
2703 * fill a notify_info_data with page info
2704 ********************************************************************/
2705 static void spoolss_notify_total_pages(int snum,
2706 SPOOL_NOTIFY_INFO_DATA *data,
2707 print_queue_struct *queue,
2708 NT_PRINTER_INFO_LEVEL *printer,
2709 TALLOC_CTX *mem_ctx)
2711 data->notify_data.value[0]=queue->page_count;
2712 data->notify_data.value[1]=0;
2715 /*******************************************************************
2716 * fill a notify_info_data with pages printed info.
2717 ********************************************************************/
2718 static void spoolss_notify_pages_printed(int snum,
2719 SPOOL_NOTIFY_INFO_DATA *data,
2720 print_queue_struct *queue,
2721 NT_PRINTER_INFO_LEVEL *printer,
2722 TALLOC_CTX *mem_ctx)
2724 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
2725 data->notify_data.value[1]=0;
2728 /*******************************************************************
2729 Fill a notify_info_data with job position.
2730 ********************************************************************/
2732 static void spoolss_notify_job_position(int snum,
2733 SPOOL_NOTIFY_INFO_DATA *data,
2734 print_queue_struct *queue,
2735 NT_PRINTER_INFO_LEVEL *printer,
2736 TALLOC_CTX *mem_ctx)
2738 data->notify_data.value[0]=queue->job;
2739 data->notify_data.value[1]=0;
2742 /*******************************************************************
2743 Fill a notify_info_data with submitted time.
2744 ********************************************************************/
2746 static void spoolss_notify_submitted_time(int snum,
2747 SPOOL_NOTIFY_INFO_DATA *data,
2748 print_queue_struct *queue,
2749 NT_PRINTER_INFO_LEVEL *printer,
2750 TALLOC_CTX *mem_ctx)
2757 t=gmtime(&queue->time);
2759 len = sizeof(SYSTEMTIME);
2761 data->notify_data.data.length = len;
2762 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2764 if (!data->notify_data.data.string) {
2765 data->notify_data.data.length = 0;
2769 make_systemtime(&st, t);
2772 * Systemtime must be linearized as a set of UINT16's.
2773 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2776 p = (char *)data->notify_data.data.string;
2777 SSVAL(p, 0, st.year);
2778 SSVAL(p, 2, st.month);
2779 SSVAL(p, 4, st.dayofweek);
2780 SSVAL(p, 6, st.day);
2781 SSVAL(p, 8, st.hour);
2782 SSVAL(p, 10, st.minute);
2783 SSVAL(p, 12, st.second);
2784 SSVAL(p, 14, st.milliseconds);
2787 struct s_notify_info_data_table
2793 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2794 print_queue_struct *queue,
2795 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2798 /* A table describing the various print notification constants and
2799 whether the notification data is a pointer to a variable sized
2800 buffer, a one value uint32 or a two value uint32. */
2802 struct s_notify_info_data_table notify_info_data_table[] =
2804 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
2805 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
2806 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
2807 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
2808 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
2809 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
2810 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
2811 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
2812 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
2813 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
2814 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
2815 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
2816 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
2817 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
2818 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
2819 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
2820 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
2821 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
2822 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
2823 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
2824 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
2825 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
2826 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
2827 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
2828 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
2829 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
2830 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
2831 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
2832 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
2833 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
2834 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
2835 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
2836 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
2837 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
2838 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
2839 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
2840 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
2841 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
2842 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
2843 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
2844 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
2845 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
2846 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
2847 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
2848 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
2849 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
2850 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
2851 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
2852 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
2855 /*******************************************************************
2856 Return the size of info_data structure.
2857 ********************************************************************/
2859 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2863 for (i = 0; i < sizeof(notify_info_data_table); i++)
2865 if ( (notify_info_data_table[i].type == type)
2866 && (notify_info_data_table[i].field == field) )
2868 switch(notify_info_data_table[i].size)
2870 case NOTIFY_ONE_VALUE:
2871 case NOTIFY_TWO_VALUE:
2876 /* The only pointer notify data I have seen on
2877 the wire is the submitted time and this has
2878 the notify size set to 4. -tpot */
2880 case NOTIFY_POINTER:
2883 case NOTIFY_SECDESC:
2889 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
2894 /*******************************************************************
2895 Return the type of notify_info_data.
2896 ********************************************************************/
2898 static int type_of_notify_info_data(uint16 type, uint16 field)
2902 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2903 if (notify_info_data_table[i].type == type &&
2904 notify_info_data_table[i].field == field)
2905 return notify_info_data_table[i].size;
2911 /****************************************************************************
2912 ****************************************************************************/
2914 static int search_notify(uint16 type, uint16 field, int *value)
2918 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2919 if (notify_info_data_table[i].type == type &&
2920 notify_info_data_table[i].field == field &&
2921 notify_info_data_table[i].fn != NULL) {
2930 /****************************************************************************
2931 ****************************************************************************/
2933 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2935 info_data->type = type;
2936 info_data->field = field;
2937 info_data->reserved = 0;
2939 info_data->size = size_of_notify_info_data(type, field);
2940 info_data->enc_type = type_of_notify_info_data(type, field);
2947 /*******************************************************************
2949 * fill a notify_info struct with info asked
2951 ********************************************************************/
2953 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2954 snum, SPOOL_NOTIFY_OPTION_TYPE
2955 *option_type, uint32 id,
2956 TALLOC_CTX *mem_ctx)
2962 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2963 NT_PRINTER_INFO_LEVEL *printer = NULL;
2964 print_queue_struct *queue=NULL;
2966 type=option_type->type;
2968 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2969 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2970 option_type->count, lp_servicename(snum)));
2972 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2975 for(field_num=0; field_num<option_type->count; field_num++)
2977 field = option_type->fields[field_num];
2979 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2981 if (!search_notify(type, field, &j) )
2984 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
2986 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2992 current_data = &info->data[info->count];
2994 construct_info_data(current_data, type, field, id);
2996 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2997 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2999 notify_info_data_table[j].fn(snum, current_data, queue,
3005 free_a_printer(&printer, 2);
3009 /*******************************************************************
3011 * fill a notify_info struct with info asked
3013 ********************************************************************/
3015 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3016 SPOOL_NOTIFY_INFO *info,
3017 NT_PRINTER_INFO_LEVEL *printer,
3018 int snum, SPOOL_NOTIFY_OPTION_TYPE
3019 *option_type, uint32 id,
3020 TALLOC_CTX *mem_ctx)
3026 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3028 DEBUG(4,("construct_notify_jobs_info\n"));
3030 type = option_type->type;
3032 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3033 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3034 option_type->count));
3036 for(field_num=0; field_num<option_type->count; field_num++) {
3037 field = option_type->fields[field_num];
3039 if (!search_notify(type, field, &j) )
3042 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3043 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3046 else info->data = tid;
3048 current_data=&(info->data[info->count]);
3050 construct_info_data(current_data, type, field, id);
3051 notify_info_data_table[j].fn(snum, current_data, queue,
3060 * JFM: The enumeration is not that simple, it's even non obvious.
3062 * let's take an example: I want to monitor the PRINTER SERVER for
3063 * the printer's name and the number of jobs currently queued.
3064 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3065 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3067 * I have 3 printers on the back of my server.
3069 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3072 * 1 printer 1 name 1
3073 * 2 printer 1 cjob 1
3074 * 3 printer 2 name 2
3075 * 4 printer 2 cjob 2
3076 * 5 printer 3 name 3
3077 * 6 printer 3 name 3
3079 * that's the print server case, the printer case is even worse.
3082 /*******************************************************************
3084 * enumerate all printers on the printserver
3085 * fill a notify_info struct with info asked
3087 ********************************************************************/
3089 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3090 SPOOL_NOTIFY_INFO *info,
3091 TALLOC_CTX *mem_ctx)
3094 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3095 int n_services=lp_numservices();
3098 SPOOL_NOTIFY_OPTION *option;
3099 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3101 DEBUG(4,("printserver_notify_info\n"));
3106 option=Printer->notify.option;
3112 for (i=0; i<option->count; i++) {
3113 option_type=&(option->ctr.type[i]);
3115 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3118 for (snum=0; snum<n_services; snum++)
3120 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3121 construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
3127 * Debugging information, don't delete.
3130 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3131 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3132 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3134 for (i=0; i<info->count; i++) {
3135 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3136 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3137 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3144 /*******************************************************************
3146 * fill a notify_info struct with info asked
3148 ********************************************************************/
3150 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3151 TALLOC_CTX *mem_ctx)
3154 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3157 SPOOL_NOTIFY_OPTION *option;
3158 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3160 print_queue_struct *queue=NULL;
3161 print_status_struct status;
3163 DEBUG(4,("printer_notify_info\n"));
3168 option=Printer->notify.option;
3174 get_printer_snum(p, hnd, &snum);
3176 for (i=0; i<option->count; i++) {
3177 option_type=&option->ctr.type[i];
3179 switch ( option_type->type ) {
3180 case PRINTER_NOTIFY_TYPE:
3181 if(construct_notify_printer_info(info, snum,
3187 case JOB_NOTIFY_TYPE: {
3188 NT_PRINTER_INFO_LEVEL *printer = NULL;
3190 count = print_queue_status(snum, &queue, &status);
3192 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3193 lp_servicename(snum))))
3196 for (j=0; j<count; j++) {
3197 construct_notify_jobs_info(&queue[j], info,
3204 free_a_printer(&printer, 2);
3214 * Debugging information, don't delete.
3217 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3218 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3219 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3221 for (i=0; i<info->count; i++) {
3222 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3223 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3224 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3230 /********************************************************************
3232 ********************************************************************/
3234 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3236 POLICY_HND *handle = &q_u->handle;
3237 SPOOL_NOTIFY_INFO *info = &r_u->info;
3239 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3240 WERROR result = WERR_BADFID;
3242 /* we always have a NOTIFY_INFO struct */
3246 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3247 OUR_HANDLE(handle)));
3251 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3254 * We are now using the change value, and
3255 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3256 * I don't have a global notification system, I'm sending back all the
3257 * informations even when _NOTHING_ has changed.
3260 /* We need to keep track of the change value to send back in
3261 RRPCN replies otherwise our updates are ignored. */
3263 if (Printer->notify.client_connected) {
3264 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3265 Printer->notify.change = q_u->change;
3268 /* just ignore the SPOOL_NOTIFY_OPTION */
3270 switch (Printer->printer_type) {
3271 case PRINTER_HANDLE_IS_PRINTSERVER:
3272 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3275 case PRINTER_HANDLE_IS_PRINTER:
3276 result = printer_notify_info(p, handle, info, p->mem_ctx);
3284 /********************************************************************
3285 * construct_printer_info_0
3286 * fill a printer_info_0 struct
3287 ********************************************************************/
3289 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3293 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3294 counter_printer_0 *session_counter;
3295 uint32 global_counter;
3298 print_status_struct status;
3300 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3303 count = print_queue_length(snum, &status);
3305 /* check if we already have a counter for this printer */
3306 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3308 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3309 if (session_counter->snum == snum)
3313 /* it's the first time, add it to the list */
3314 if (session_counter==NULL) {
3315 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3316 free_a_printer(&ntprinter, 2);
3319 ZERO_STRUCTP(session_counter);
3320 session_counter->snum=snum;
3321 session_counter->counter=0;
3322 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3326 session_counter->counter++;
3329 * the global_counter should be stored in a TDB as it's common to all the clients
3330 * and should be zeroed on samba startup
3332 global_counter=session_counter->counter;
3334 pstrcpy(chaine,ntprinter->info_2->printername);
3336 init_unistr(&printer->printername, chaine);
3338 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3339 init_unistr(&printer->servername, chaine);
3341 printer->cjobs = count;
3342 printer->total_jobs = 0;
3343 printer->total_bytes = 0;
3345 setuptime = (time_t)ntprinter->info_2->setuptime;
3346 t=gmtime(&setuptime);
3348 printer->year = t->tm_year+1900;
3349 printer->month = t->tm_mon+1;
3350 printer->dayofweek = t->tm_wday;
3351 printer->day = t->tm_mday;
3352 printer->hour = t->tm_hour;
3353 printer->minute = t->tm_min;
3354 printer->second = t->tm_sec;
3355 printer->milliseconds = 0;
3357 printer->global_counter = global_counter;
3358 printer->total_pages = 0;
3359 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3360 printer->major_version = 0x0004; /* NT 4 */
3361 printer->build_version = 0x0565; /* build 1381 */
3363 printer->major_version = 0x0005; /* NT 5 */
3364 printer->build_version = 0x0893; /* build 2195 */
3366 printer->unknown7 = 0x1;
3367 printer->unknown8 = 0x0;
3368 printer->unknown9 = 0x0;
3369 printer->session_counter = session_counter->counter;
3370 printer->unknown11 = 0x0;
3371 printer->printer_errors = 0x0; /* number of print failure */
3372 printer->unknown13 = 0x0;
3373 printer->unknown14 = 0x1;
3374 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3375 printer->unknown16 = 0x0;
3376 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3377 printer->unknown18 = 0x0;
3378 printer->status = nt_printq_status(status.status);
3379 printer->unknown20 = 0x0;
3380 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3381 printer->unknown22 = 0x0;
3382 printer->unknown23 = 0x6; /* 6 ???*/
3383 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3384 printer->unknown25 = 0;
3385 printer->unknown26 = 0;
3386 printer->unknown27 = 0;
3387 printer->unknown28 = 0;
3388 printer->unknown29 = 0;
3390 free_a_printer(&ntprinter,2);
3394 /********************************************************************
3395 * construct_printer_info_1
3396 * fill a printer_info_1 struct
3397 ********************************************************************/
3398 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3402 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3404 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3407 printer->flags=flags;
3409 if (*ntprinter->info_2->comment == '\0') {
3410 init_unistr(&printer->comment, lp_comment(snum));
3411 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3412 ntprinter->info_2->drivername, lp_comment(snum));
3415 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3416 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3417 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3420 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3422 init_unistr(&printer->description, chaine);
3423 init_unistr(&printer->name, chaine2);
3425 free_a_printer(&ntprinter,2);
3430 /****************************************************************************
3431 Free a DEVMODE struct.
3432 ****************************************************************************/
3434 static void free_dev_mode(DEVICEMODE *dev)
3439 SAFE_FREE(dev->private);
3443 /****************************************************************************
3444 Create a DEVMODE struct. Returns malloced memory.
3445 ****************************************************************************/
3447 DEVICEMODE *construct_dev_mode(int snum)
3451 NT_PRINTER_INFO_LEVEL *printer = NULL;
3452 NT_DEVICEMODE *ntdevmode = NULL;
3453 DEVICEMODE *devmode = NULL;
3455 DEBUG(7,("construct_dev_mode\n"));
3457 DEBUGADD(8,("getting printer characteristics\n"));
3459 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3460 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3464 ZERO_STRUCTP(devmode);
3466 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3469 if (printer->info_2->devmode)
3470 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
3472 if (ntdevmode == NULL) {
3473 DEBUG(5, ("BONG! There was no device mode!\n"));
3477 DEBUGADD(8,("loading DEVICEMODE\n"));
3479 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
3480 init_unistr(&devmode->devicename, adevice);
3482 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
3483 init_unistr(&devmode->formname, aform);
3485 devmode->specversion = ntdevmode->specversion;
3486 devmode->driverversion = ntdevmode->driverversion;
3487 devmode->size = ntdevmode->size;
3488 devmode->driverextra = ntdevmode->driverextra;
3489 devmode->fields = ntdevmode->fields;
3491 devmode->orientation = ntdevmode->orientation;
3492 devmode->papersize = ntdevmode->papersize;
3493 devmode->paperlength = ntdevmode->paperlength;
3494 devmode->paperwidth = ntdevmode->paperwidth;
3495 devmode->scale = ntdevmode->scale;
3496 devmode->copies = ntdevmode->copies;
3497 devmode->defaultsource = ntdevmode->defaultsource;
3498 devmode->printquality = ntdevmode->printquality;
3499 devmode->color = ntdevmode->color;
3500 devmode->duplex = ntdevmode->duplex;
3501 devmode->yresolution = ntdevmode->yresolution;
3502 devmode->ttoption = ntdevmode->ttoption;
3503 devmode->collate = ntdevmode->collate;
3504 devmode->icmmethod = ntdevmode->icmmethod;
3505 devmode->icmintent = ntdevmode->icmintent;
3506 devmode->mediatype = ntdevmode->mediatype;
3507 devmode->dithertype = ntdevmode->dithertype;
3509 if (ntdevmode->private != NULL) {
3510 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3514 free_nt_devicemode(&ntdevmode);
3515 free_a_printer(&printer,2);
3522 free_nt_devicemode(&ntdevmode);
3524 free_a_printer(&printer,2);
3525 free_dev_mode(devmode);
3530 /********************************************************************
3531 * construct_printer_info_2
3532 * fill a printer_info_2 struct
3533 ********************************************************************/
3535 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3538 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3540 print_status_struct status;
3542 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3545 count = print_queue_length(snum, &status);
3547 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3548 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3549 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3550 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3551 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3553 if (*ntprinter->info_2->comment == '\0')
3554 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3556 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3558 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3559 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3560 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3561 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3562 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3564 printer->attributes = ntprinter->info_2->attributes;
3566 printer->priority = ntprinter->info_2->priority; /* priority */
3567 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3568 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3569 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3570 printer->status = nt_printq_status(status.status); /* status */
3571 printer->cjobs = count; /* jobs */
3572 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3574 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3575 DEBUG(8, ("Returning NULL Devicemode!\n"));
3578 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3579 /* steal the printer info sec_desc structure. [badly done]. */
3580 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3581 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3582 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3583 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3586 printer->secdesc = NULL;
3589 free_a_printer(&ntprinter, 2);
3593 /********************************************************************
3594 * construct_printer_info_3
3595 * fill a printer_info_3 struct
3596 ********************************************************************/
3598 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3600 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3601 PRINTER_INFO_3 *printer = NULL;
3603 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3607 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3608 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3612 ZERO_STRUCTP(printer);
3614 printer->flags = 4; /* These are the components of the SD we are returning. */
3615 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3616 /* steal the printer info sec_desc structure. [badly done]. */
3617 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3621 * Set the flags for the components we are returning.
3624 if (printer->secdesc->owner_sid)
3625 printer->flags |= OWNER_SECURITY_INFORMATION;
3627 if (printer->secdesc->grp_sid)
3628 printer->flags |= GROUP_SECURITY_INFORMATION;
3630 if (printer->secdesc->dacl)
3631 printer->flags |= DACL_SECURITY_INFORMATION;
3633 if (printer->secdesc->sacl)
3634 printer->flags |= SACL_SECURITY_INFORMATION;
3637 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
3638 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
3639 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
3642 free_a_printer(&ntprinter, 2);
3644 *pp_printer = printer;
3648 /********************************************************************
3649 * construct_printer_info_4
3650 * fill a printer_info_4 struct
3651 ********************************************************************/
3653 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
3655 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3657 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3660 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3661 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3662 printer->attributes = ntprinter->info_2->attributes;
3664 free_a_printer(&ntprinter, 2);
3668 /********************************************************************
3669 * construct_printer_info_5
3670 * fill a printer_info_5 struct
3671 ********************************************************************/
3673 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
3675 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3677 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3680 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3681 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
3682 printer->attributes = ntprinter->info_2->attributes;
3683 printer->device_not_selected_timeout = 0x3a98;
3684 printer->transmission_retry_timeout = 0xafc8;
3686 free_a_printer(&ntprinter, 2);
3690 /********************************************************************
3691 Spoolss_enumprinters.
3692 ********************************************************************/
3694 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3698 int n_services=lp_numservices();
3699 PRINTER_INFO_1 *tp, *printers=NULL;
3700 PRINTER_INFO_1 current_prt;
3702 DEBUG(4,("enum_all_printers_info_1\n"));
3704 for (snum=0; snum<n_services; snum++) {
3705 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3706 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3708 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
3709 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
3710 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3711 SAFE_FREE(printers);
3716 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
3718 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
3724 /* check the required size. */
3725 for (i=0; i<*returned; i++)
3726 (*needed) += spoolss_size_printer_info_1(&printers[i]);
3728 if (!alloc_buffer_size(buffer, *needed))
3729 return WERR_INSUFFICIENT_BUFFER;
3731 /* fill the buffer with the structures */
3732 for (i=0; i<*returned; i++)
3733 smb_io_printer_info_1("", buffer, &printers[i], 0);
3736 SAFE_FREE(printers);
3738 if (*needed > offered) {
3740 return WERR_INSUFFICIENT_BUFFER;
3746 /********************************************************************
3747 enum_all_printers_info_1_local.
3748 *********************************************************************/
3750 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3752 DEBUG(4,("enum_all_printers_info_1_local\n"));
3754 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3757 /********************************************************************
3758 enum_all_printers_info_1_name.
3759 *********************************************************************/
3761 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3765 DEBUG(4,("enum_all_printers_info_1_name\n"));
3767 if ((name[0] == '\\') && (name[1] == '\\'))
3770 if (is_myname_or_ipaddr(s)) {
3771 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3774 return WERR_INVALID_NAME;
3777 /********************************************************************
3778 enum_all_printers_info_1_remote.
3779 *********************************************************************/
3781 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3783 PRINTER_INFO_1 *printer;
3784 fstring printername;
3787 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3789 /* JFM: currently it's more a place holder than anything else.
3790 * In the spooler world there is a notion of server registration.
3791 * the print servers are registring (sp ?) on the PDC (in the same domain)
3793 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3796 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3801 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3802 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3803 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3805 init_unistr(&printer->description, desc);
3806 init_unistr(&printer->name, printername);
3807 init_unistr(&printer->comment, comment);
3808 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3810 /* check the required size. */
3811 *needed += spoolss_size_printer_info_1(printer);
3813 if (!alloc_buffer_size(buffer, *needed)) {
3815 return WERR_INSUFFICIENT_BUFFER;
3818 /* fill the buffer with the structures */
3819 smb_io_printer_info_1("", buffer, printer, 0);
3824 if (*needed > offered) {
3826 return WERR_INSUFFICIENT_BUFFER;
3832 /********************************************************************
3833 enum_all_printers_info_1_network.
3834 *********************************************************************/
3836 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3840 DEBUG(4,("enum_all_printers_info_1_network\n"));
3842 /* If we respond to a enum_printers level 1 on our name with flags
3843 set to PRINTER_ENUM_REMOTE with a list of printers then these
3844 printers incorrectly appear in the APW browse list.
3845 Specifically the printers for the server appear at the workgroup
3846 level where all the other servers in the domain are
3847 listed. Windows responds to this call with a
3848 WERR_CAN_NOT_COMPLETE so we should do the same. */
3850 if (name[0] == '\\' && name[1] == '\\')
3853 if (is_myname_or_ipaddr(s))
3854 return WERR_CAN_NOT_COMPLETE;
3856 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3859 /********************************************************************
3860 * api_spoolss_enumprinters
3862 * called from api_spoolss_enumprinters (see this to understand)
3863 ********************************************************************/
3865 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3869 int n_services=lp_numservices();
3870 PRINTER_INFO_2 *tp, *printers=NULL;
3871 PRINTER_INFO_2 current_prt;
3873 for (snum=0; snum<n_services; snum++) {
3874 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3875 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3877 if (construct_printer_info_2(¤t_prt, snum)) {
3878 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3879 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3880 SAFE_FREE(printers);
3885 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3886 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
3892 /* check the required size. */
3893 for (i=0; i<*returned; i++)
3894 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3896 if (!alloc_buffer_size(buffer, *needed)) {
3897 for (i=0; i<*returned; i++) {
3898 free_devmode(printers[i].devmode);
3900 SAFE_FREE(printers);
3901 return WERR_INSUFFICIENT_BUFFER;
3904 /* fill the buffer with the structures */
3905 for (i=0; i<*returned; i++)
3906 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3909 for (i=0; i<*returned; i++) {
3910 free_devmode(printers[i].devmode);
3912 SAFE_FREE(printers);
3914 if (*needed > offered) {
3916 return WERR_INSUFFICIENT_BUFFER;
3922 /********************************************************************
3923 * handle enumeration of printers at level 1
3924 ********************************************************************/
3926 static WERROR enumprinters_level1( uint32 flags, fstring name,
3927 NEW_BUFFER *buffer, uint32 offered,
3928 uint32 *needed, uint32 *returned)
3930 /* Not all the flags are equals */
3932 if (flags & PRINTER_ENUM_LOCAL)
3933 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3935 if (flags & PRINTER_ENUM_NAME)
3936 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3938 if (flags & PRINTER_ENUM_REMOTE)
3939 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3941 if (flags & PRINTER_ENUM_NETWORK)
3942 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
3944 return WERR_OK; /* NT4sp5 does that */
3947 /********************************************************************
3948 * handle enumeration of printers at level 2
3949 ********************************************************************/
3951 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3952 NEW_BUFFER *buffer, uint32 offered,
3953 uint32 *needed, uint32 *returned)
3955 char *s = servername;
3957 if (flags & PRINTER_ENUM_LOCAL) {
3958 return enum_all_printers_info_2(buffer, offered, needed, returned);
3961 if (flags & PRINTER_ENUM_NAME) {
3962 if ((servername[0] == '\\') && (servername[1] == '\\'))
3964 if (is_myname_or_ipaddr(s))
3965 return enum_all_printers_info_2(buffer, offered, needed, returned);
3967 return WERR_INVALID_NAME;
3970 if (flags & PRINTER_ENUM_REMOTE)
3971 return WERR_UNKNOWN_LEVEL;
3976 /********************************************************************
3977 * handle enumeration of printers at level 5
3978 ********************************************************************/
3980 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3981 NEW_BUFFER *buffer, uint32 offered,
3982 uint32 *needed, uint32 *returned)
3984 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3988 /********************************************************************
3989 * api_spoolss_enumprinters
3991 * called from api_spoolss_enumprinters (see this to understand)
3992 ********************************************************************/
3994 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3996 uint32 flags = q_u->flags;
3997 UNISTR2 *servername = &q_u->servername;
3998 uint32 level = q_u->level;
3999 NEW_BUFFER *buffer = NULL;
4000 uint32 offered = q_u->offered;
4001 uint32 *needed = &r_u->needed;
4002 uint32 *returned = &r_u->returned;
4006 /* that's an [in out] buffer */
4007 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4008 buffer = r_u->buffer;
4010 DEBUG(4,("_spoolss_enumprinters\n"));
4017 * flags==PRINTER_ENUM_NAME
4018 * if name=="" then enumerates all printers
4019 * if name!="" then enumerate the printer
4020 * flags==PRINTER_ENUM_REMOTE
4021 * name is NULL, enumerate printers
4022 * Level 2: name!="" enumerates printers, name can't be NULL
4023 * Level 3: doesn't exist
4024 * Level 4: does a local registry lookup
4025 * Level 5: same as Level 2
4028 unistr2_to_ascii(name, servername, sizeof(name)-1);
4033 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4035 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4037 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4042 return WERR_UNKNOWN_LEVEL;
4045 /****************************************************************************
4046 ****************************************************************************/
4048 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4050 PRINTER_INFO_0 *printer=NULL;
4052 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4055 construct_printer_info_0(printer, snum);
4057 /* check the required size. */
4058 *needed += spoolss_size_printer_info_0(printer);
4060 if (!alloc_buffer_size(buffer, *needed)) {
4062 return WERR_INSUFFICIENT_BUFFER;
4065 /* fill the buffer with the structures */
4066 smb_io_printer_info_0("", buffer, printer, 0);
4071 if (*needed > offered) {
4072 return WERR_INSUFFICIENT_BUFFER;
4078 /****************************************************************************
4079 ****************************************************************************/
4081 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4083 PRINTER_INFO_1 *printer=NULL;
4085 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4088 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4090 /* check the required size. */
4091 *needed += spoolss_size_printer_info_1(printer);
4093 if (!alloc_buffer_size(buffer, *needed)) {
4095 return WERR_INSUFFICIENT_BUFFER;
4098 /* fill the buffer with the structures */
4099 smb_io_printer_info_1("", buffer, printer, 0);
4104 if (*needed > offered) {
4105 return WERR_INSUFFICIENT_BUFFER;
4111 /****************************************************************************
4112 ****************************************************************************/
4114 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4116 PRINTER_INFO_2 *printer=NULL;
4118 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4121 construct_printer_info_2(printer, snum);
4123 /* check the required size. */
4124 *needed += spoolss_size_printer_info_2(printer);
4126 if (!alloc_buffer_size(buffer, *needed)) {
4127 free_printer_info_2(printer);
4128 return WERR_INSUFFICIENT_BUFFER;
4131 /* fill the buffer with the structures */
4132 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4133 free_printer_info_2(printer);
4138 free_printer_info_2(printer);
4140 if (*needed > offered) {
4141 return WERR_INSUFFICIENT_BUFFER;
4147 /****************************************************************************
4148 ****************************************************************************/
4150 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4152 PRINTER_INFO_3 *printer=NULL;
4154 if (!construct_printer_info_3(&printer, snum))
4157 /* check the required size. */
4158 *needed += spoolss_size_printer_info_3(printer);
4160 if (!alloc_buffer_size(buffer, *needed)) {
4161 free_printer_info_3(printer);
4162 return WERR_INSUFFICIENT_BUFFER;
4165 /* fill the buffer with the structures */
4166 smb_io_printer_info_3("", buffer, printer, 0);
4169 free_printer_info_3(printer);
4171 if (*needed > offered) {
4172 return WERR_INSUFFICIENT_BUFFER;
4178 /****************************************************************************
4179 ****************************************************************************/
4181 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4183 PRINTER_INFO_4 *printer=NULL;
4185 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4188 if (!construct_printer_info_4(printer, snum))
4191 /* check the required size. */
4192 *needed += spoolss_size_printer_info_4(printer);
4194 if (!alloc_buffer_size(buffer, *needed)) {
4195 free_printer_info_4(printer);
4196 return WERR_INSUFFICIENT_BUFFER;
4199 /* fill the buffer with the structures */
4200 smb_io_printer_info_4("", buffer, printer, 0);
4203 free_printer_info_4(printer);
4205 if (*needed > offered) {
4206 return WERR_INSUFFICIENT_BUFFER;
4212 /****************************************************************************
4213 ****************************************************************************/
4215 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4217 PRINTER_INFO_5 *printer=NULL;
4219 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4222 if (!construct_printer_info_5(printer, snum))
4225 /* check the required size. */
4226 *needed += spoolss_size_printer_info_5(printer);
4228 if (!alloc_buffer_size(buffer, *needed)) {
4229 free_printer_info_5(printer);
4230 return WERR_INSUFFICIENT_BUFFER;
4233 /* fill the buffer with the structures */
4234 smb_io_printer_info_5("", buffer, printer, 0);
4237 free_printer_info_5(printer);
4239 if (*needed > offered) {
4240 return WERR_INSUFFICIENT_BUFFER;
4246 /****************************************************************************
4247 ****************************************************************************/
4249 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4251 POLICY_HND *handle = &q_u->handle;
4252 uint32 level = q_u->level;
4253 NEW_BUFFER *buffer = NULL;
4254 uint32 offered = q_u->offered;
4255 uint32 *needed = &r_u->needed;
4259 /* that's an [in out] buffer */
4260 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4261 buffer = r_u->buffer;
4265 if (!get_printer_snum(p, handle, &snum))
4270 return getprinter_level_0(snum, buffer, offered, needed);
4272 return getprinter_level_1(snum, buffer, offered, needed);
4274 return getprinter_level_2(snum, buffer, offered, needed);
4276 return getprinter_level_3(snum, buffer, offered, needed);
4278 return getprinter_level_4(snum, buffer, offered, needed);
4280 return getprinter_level_5(snum, buffer, offered, needed);
4282 return WERR_UNKNOWN_LEVEL;
4285 /********************************************************************
4286 * fill a DRIVER_INFO_1 struct
4287 ********************************************************************/
4289 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4291 init_unistr( &info->name, driver.info_3->name);
4294 /********************************************************************
4295 * construct_printer_driver_info_1
4296 ********************************************************************/
4298 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4300 NT_PRINTER_INFO_LEVEL *printer = NULL;
4301 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4303 ZERO_STRUCT(driver);
4305 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4306 return WERR_INVALID_PRINTER_NAME;
4308 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4309 return WERR_UNKNOWN_PRINTER_DRIVER;
4311 fill_printer_driver_info_1(info, driver, servername, architecture);
4313 free_a_printer(&printer,2);
4318 /********************************************************************
4319 * construct_printer_driver_info_2
4320 * fill a printer_info_2 struct
4321 ********************************************************************/
4323 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4327 info->version=driver.info_3->cversion;
4329 init_unistr( &info->name, driver.info_3->name );
4330 init_unistr( &info->architecture, driver.info_3->environment );
4333 if (strlen(driver.info_3->driverpath)) {
4334 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4335 init_unistr( &info->driverpath, temp );
4337 init_unistr( &info->driverpath, "" );
4339 if (strlen(driver.info_3->datafile)) {
4340 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4341 init_unistr( &info->datafile, temp );
4343 init_unistr( &info->datafile, "" );
4345 if (strlen(driver.info_3->configfile)) {
4346 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4347 init_unistr( &info->configfile, temp );
4349 init_unistr( &info->configfile, "" );
4352 /********************************************************************
4353 * construct_printer_driver_info_2
4354 * fill a printer_info_2 struct
4355 ********************************************************************/
4357 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4359 NT_PRINTER_INFO_LEVEL *printer = NULL;
4360 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4362 ZERO_STRUCT(printer);
4363 ZERO_STRUCT(driver);
4365 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4366 return WERR_INVALID_PRINTER_NAME;
4368 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4369 return WERR_UNKNOWN_PRINTER_DRIVER;
4371 fill_printer_driver_info_2(info, driver, servername);
4373 free_a_printer(&printer,2);
4378 /********************************************************************
4379 * copy a strings array and convert to UNICODE
4381 * convert an array of ascii string to a UNICODE string
4382 ********************************************************************/
4384 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4392 DEBUG(6,("init_unistr_array\n"));
4403 v = ""; /* hack to handle null lists */
4406 /* hack to allow this to be used in places other than when generating
4407 the list of dependent files */
4410 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4414 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4416 if ( (tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4417 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4425 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4430 (*uni_array)[j]=0x0000;
4433 DEBUGADD(6,("last one:done\n"));
4435 /* return size of array in uint16's */
4440 /********************************************************************
4441 * construct_printer_info_3
4442 * fill a printer_info_3 struct
4443 ********************************************************************/
4445 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4451 info->version=driver.info_3->cversion;
4453 init_unistr( &info->name, driver.info_3->name );
4454 init_unistr( &info->architecture, driver.info_3->environment );
4456 if (strlen(driver.info_3->driverpath)) {
4457 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4458 init_unistr( &info->driverpath, temp );
4460 init_unistr( &info->driverpath, "" );
4462 if (strlen(driver.info_3->datafile)) {
4463 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4464 init_unistr( &info->datafile, temp );
4466 init_unistr( &info->datafile, "" );
4468 if (strlen(driver.info_3->configfile)) {
4469 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4470 init_unistr( &info->configfile, temp );
4472 init_unistr( &info->configfile, "" );
4474 if (strlen(driver.info_3->helpfile)) {
4475 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4476 init_unistr( &info->helpfile, temp );
4478 init_unistr( &info->helpfile, "" );
4480 init_unistr( &info->monitorname, driver.info_3->monitorname );
4481 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4483 info->dependentfiles=NULL;
4484 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4487 /********************************************************************
4488 * construct_printer_info_3
4489 * fill a printer_info_3 struct
4490 ********************************************************************/
4492 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4494 NT_PRINTER_INFO_LEVEL *printer = NULL;
4495 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4497 ZERO_STRUCT(driver);
4499 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4500 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4501 if (!W_ERROR_IS_OK(status))
4502 return WERR_INVALID_PRINTER_NAME;
4504 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4505 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4510 * I put this code in during testing. Helpful when commenting out the
4511 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4512 * as win2k always queries the driver using an infor level of 6.
4513 * I've left it in (but ifdef'd out) because I'll probably
4514 * use it in experimentation again in the future. --jerry 22/01/2002
4517 if (!W_ERROR_IS_OK(status)) {
4519 * Is this a W2k client ?
4522 /* Yes - try again with a WinNT driver. */
4524 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4525 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4529 if (!W_ERROR_IS_OK(status)) {
4530 free_a_printer(&printer,2);
4531 return WERR_UNKNOWN_PRINTER_DRIVER;
4539 fill_printer_driver_info_3(info, driver, servername);
4541 free_a_printer(&printer,2);
4546 /********************************************************************
4547 * construct_printer_info_6
4548 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4549 ********************************************************************/
4551 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4557 memset(&nullstr, '\0', sizeof(fstring));
4559 info->version=driver.info_3->cversion;
4561 init_unistr( &info->name, driver.info_3->name );
4562 init_unistr( &info->architecture, driver.info_3->environment );
4564 if (strlen(driver.info_3->driverpath)) {
4565 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4566 init_unistr( &info->driverpath, temp );
4568 init_unistr( &info->driverpath, "" );
4570 if (strlen(driver.info_3->datafile)) {
4571 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4572 init_unistr( &info->datafile, temp );
4574 init_unistr( &info->datafile, "" );
4576 if (strlen(driver.info_3->configfile)) {
4577 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4578 init_unistr( &info->configfile, temp );
4580 init_unistr( &info->configfile, "" );
4582 if (strlen(driver.info_3->helpfile)) {
4583 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4584 init_unistr( &info->helpfile, temp );
4586 init_unistr( &info->helpfile, "" );
4588 init_unistr( &info->monitorname, driver.info_3->monitorname );
4589 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4591 info->dependentfiles = NULL;
4592 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
4594 info->previousdrivernames=NULL;
4595 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4597 info->driver_date.low=0;
4598 info->driver_date.high=0;
4601 info->driver_version_low=0;
4602 info->driver_version_high=0;
4604 init_unistr( &info->mfgname, "");
4605 init_unistr( &info->oem_url, "");
4606 init_unistr( &info->hardware_id, "");
4607 init_unistr( &info->provider, "");
4610 /********************************************************************
4611 * construct_printer_info_6
4612 * fill a printer_info_6 struct
4613 ********************************************************************/
4615 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
4616 fstring servername, fstring architecture, uint32 version)
4618 NT_PRINTER_INFO_LEVEL *printer = NULL;
4619 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4622 ZERO_STRUCT(driver);
4624 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4626 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4628 if (!W_ERROR_IS_OK(status))
4629 return WERR_INVALID_PRINTER_NAME;
4631 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4633 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4635 if (!W_ERROR_IS_OK(status))
4638 * Is this a W2k client ?
4642 free_a_printer(&printer,2);
4643 return WERR_UNKNOWN_PRINTER_DRIVER;
4646 /* Yes - try again with a WinNT driver. */
4648 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4649 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4650 if (!W_ERROR_IS_OK(status)) {
4651 free_a_printer(&printer,2);
4652 return WERR_UNKNOWN_PRINTER_DRIVER;
4656 fill_printer_driver_info_6(info, driver, servername);
4658 free_a_printer(&printer,2);
4663 /****************************************************************************
4664 ****************************************************************************/
4666 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
4668 SAFE_FREE(info->dependentfiles);
4671 /****************************************************************************
4672 ****************************************************************************/
4674 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
4676 SAFE_FREE(info->dependentfiles);
4680 /****************************************************************************
4681 ****************************************************************************/
4683 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4685 DRIVER_INFO_1 *info=NULL;
4688 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
4691 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
4692 if (!W_ERROR_IS_OK(status)) {
4697 /* check the required size. */
4698 *needed += spoolss_size_printer_driver_info_1(info);
4700 if (!alloc_buffer_size(buffer, *needed)) {
4702 return WERR_INSUFFICIENT_BUFFER;
4705 /* fill the buffer with the structures */
4706 smb_io_printer_driver_info_1("", buffer, info, 0);
4711 if (*needed > offered)
4712 return WERR_INSUFFICIENT_BUFFER;
4717 /****************************************************************************
4718 ****************************************************************************/
4720 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4722 DRIVER_INFO_2 *info=NULL;
4725 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
4728 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
4729 if (!W_ERROR_IS_OK(status)) {
4734 /* check the required size. */
4735 *needed += spoolss_size_printer_driver_info_2(info);
4737 if (!alloc_buffer_size(buffer, *needed)) {
4739 return WERR_INSUFFICIENT_BUFFER;
4742 /* fill the buffer with the structures */
4743 smb_io_printer_driver_info_2("", buffer, info, 0);
4748 if (*needed > offered)
4749 return WERR_INSUFFICIENT_BUFFER;
4754 /****************************************************************************
4755 ****************************************************************************/
4757 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4764 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
4765 if (!W_ERROR_IS_OK(status)) {
4769 /* check the required size. */
4770 *needed += spoolss_size_printer_driver_info_3(&info);
4772 if (!alloc_buffer_size(buffer, *needed)) {
4773 free_printer_driver_info_3(&info);
4774 return WERR_INSUFFICIENT_BUFFER;
4777 /* fill the buffer with the structures */
4778 smb_io_printer_driver_info_3("", buffer, &info, 0);
4780 free_printer_driver_info_3(&info);
4782 if (*needed > offered)
4783 return WERR_INSUFFICIENT_BUFFER;
4788 /****************************************************************************
4789 ****************************************************************************/
4791 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4798 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
4799 if (!W_ERROR_IS_OK(status)) {
4803 /* check the required size. */
4804 *needed += spoolss_size_printer_driver_info_6(&info);
4806 if (!alloc_buffer_size(buffer, *needed)) {
4807 free_printer_driver_info_6(&info);
4808 return WERR_INSUFFICIENT_BUFFER;
4811 /* fill the buffer with the structures */
4812 smb_io_printer_driver_info_6("", buffer, &info, 0);
4814 free_printer_driver_info_6(&info);
4816 if (*needed > offered)
4817 return WERR_INSUFFICIENT_BUFFER;
4822 /****************************************************************************
4823 ****************************************************************************/
4825 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
4827 POLICY_HND *handle = &q_u->handle;
4828 UNISTR2 *uni_arch = &q_u->architecture;
4829 uint32 level = q_u->level;
4830 uint32 clientmajorversion = q_u->clientmajorversion;
4831 NEW_BUFFER *buffer = NULL;
4832 uint32 offered = q_u->offered;
4833 uint32 *needed = &r_u->needed;
4834 uint32 *servermajorversion = &r_u->servermajorversion;
4835 uint32 *serverminorversion = &r_u->serverminorversion;
4838 fstring architecture;
4841 /* that's an [in out] buffer */
4842 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4843 buffer = r_u->buffer;
4845 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4848 *servermajorversion = 0;
4849 *serverminorversion = 0;
4851 pstrcpy(servername, get_called_name());
4852 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4854 if (!get_printer_snum(p, handle, &snum))
4859 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4861 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4863 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4865 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4868 return WERR_UNKNOWN_LEVEL;
4871 /****************************************************************************
4872 ****************************************************************************/
4874 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4876 POLICY_HND *handle = &q_u->handle;
4878 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4881 DEBUG(3,("Error in startpageprinter printer handle\n"));
4885 Printer->page_started=True;
4889 /****************************************************************************
4890 ****************************************************************************/
4892 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4894 POLICY_HND *handle = &q_u->handle;
4897 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4900 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
4904 if (!get_printer_snum(p, handle, &snum))
4907 Printer->page_started=False;
4908 print_job_endpage(snum, Printer->jobid);
4913 /********************************************************************
4914 * api_spoolss_getprinter
4915 * called from the spoolss dispatcher
4917 ********************************************************************/
4919 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4921 POLICY_HND *handle = &q_u->handle;
4922 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4923 uint32 *jobid = &r_u->jobid;
4925 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4929 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4930 struct current_user user;
4933 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4937 get_current_user(&user, p);
4940 * a nice thing with NT is it doesn't listen to what you tell it.
4941 * when asked to send _only_ RAW datas, it tries to send datas
4944 * So I add checks like in NT Server ...
4946 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4947 * there's a bug in NT client-side code, so we'll fix it in the
4948 * server-side code. *nnnnnggggh!*
4951 if (info_1->p_datatype != 0) {
4952 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4953 if (strcmp(datatype, "RAW") != 0) {
4955 return WERR_INVALID_DATATYPE;
4959 /* get the share number of the printer */
4960 if (!get_printer_snum(p, handle, &snum)) {
4964 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4966 Printer->jobid = print_job_start(&user, snum, jobname);
4968 /* An error occured in print_job_start() so return an appropriate
4971 if (Printer->jobid == -1) {
4972 return map_werror_from_unix(errno);
4975 Printer->document_started=True;
4976 (*jobid) = Printer->jobid;
4981 /********************************************************************
4982 * api_spoolss_getprinter
4983 * called from the spoolss dispatcher
4985 ********************************************************************/
4987 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4989 POLICY_HND *handle = &q_u->handle;
4991 return _spoolss_enddocprinter_internal(p, handle);
4994 /****************************************************************************
4995 ****************************************************************************/
4997 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4999 POLICY_HND *handle = &q_u->handle;
5000 uint32 buffer_size = q_u->buffer_size;
5001 uint8 *buffer = q_u->buffer;
5002 uint32 *buffer_written = &q_u->buffer_size2;
5004 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5007 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5008 r_u->buffer_written = q_u->buffer_size2;
5012 if (!get_printer_snum(p, handle, &snum))
5015 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5017 r_u->buffer_written = q_u->buffer_size2;
5022 /********************************************************************
5023 * api_spoolss_getprinter
5024 * called from the spoolss dispatcher
5026 ********************************************************************/
5028 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5031 struct current_user user;
5033 WERROR errcode = WERR_BADFUNC;
5034 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5036 get_current_user(&user, p);
5039 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5043 if (!get_printer_snum(p, handle, &snum))
5047 case PRINTER_CONTROL_PAUSE:
5048 if (print_queue_pause(&user, snum, &errcode)) {
5052 case PRINTER_CONTROL_RESUME:
5053 case PRINTER_CONTROL_UNPAUSE:
5054 if (print_queue_resume(&user, snum, &errcode)) {
5058 case PRINTER_CONTROL_PURGE:
5059 if (print_queue_purge(&user, snum, &errcode)) {
5064 return WERR_UNKNOWN_LEVEL;
5070 /********************************************************************
5071 * api_spoolss_abortprinter
5072 ********************************************************************/
5074 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5076 POLICY_HND *handle = &q_u->handle;
5078 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
5081 /********************************************************************
5082 * called by spoolss_api_setprinter
5083 * when updating a printer description
5084 ********************************************************************/
5086 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5087 const SPOOL_PRINTER_INFO_LEVEL *info,
5088 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5090 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5091 struct current_user user;
5095 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5097 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5098 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5099 OUR_HANDLE(handle)));
5101 result = WERR_BADFID;
5105 /* NT seems to like setting the security descriptor even though
5106 nothing may have actually changed. This causes annoying
5107 dialog boxes when the user doesn't have permission to change
5108 the security descriptor. */
5110 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5112 if (DEBUGLEVEL >= 10) {
5116 the_acl = old_secdesc_ctr->sec->dacl;
5117 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5118 PRINTERNAME(snum), the_acl->num_aces));
5120 for (i = 0; i < the_acl->num_aces; i++) {
5123 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5125 DEBUG(10, ("%s 0x%08x\n", sid_str,
5126 the_acl->ace[i].info.mask));
5129 the_acl = secdesc_ctr->sec->dacl;
5132 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5133 PRINTERNAME(snum), the_acl->num_aces));
5135 for (i = 0; i < the_acl->num_aces; i++) {
5138 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5140 DEBUG(10, ("%s 0x%08x\n", sid_str,
5141 the_acl->ace[i].info.mask));
5144 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5148 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5150 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5155 /* Work out which user is performing the operation */
5157 get_current_user(&user, p);
5159 /* Check the user has permissions to change the security
5160 descriptor. By experimentation with two NT machines, the user
5161 requires Full Access to the printer to change security
5164 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5165 result = WERR_ACCESS_DENIED;
5169 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5176 /********************************************************************
5177 Do Samba sanity checks on a printer info struct.
5178 this has changed purpose: it now "canonicalises" printer
5179 info from a client rather than just checking it is correct
5180 ********************************************************************/
5182 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5184 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5185 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5187 /* we force some elements to "correct" values */
5188 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5189 fstrcpy(info->sharename, lp_servicename(snum));
5190 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5191 get_called_name(), info->sharename);
5192 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5197 /****************************************************************************
5198 ****************************************************************************/
5200 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5202 extern userdom_struct current_user_info;
5203 char *cmd = lp_addprinter_cmd();
5206 pstring driverlocation;
5210 fstring remote_machine = "%m";
5212 /* build driver path... only 9X architecture is needed for legacy reasons */
5213 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
5215 /* change \ to \\ for the shell */
5216 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
5217 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5219 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5220 cmd, printer->info_2->printername, printer->info_2->sharename,
5221 printer->info_2->portname, printer->info_2->drivername,
5222 printer->info_2->location, driverlocation, remote_machine);
5224 DEBUG(10,("Running [%s]\n", command));
5225 ret = smbrun(command, &fd);
5226 DEBUGADD(10,("returned [%d]\n", ret));
5235 /* Get lines and convert them back to dos-codepage */
5236 qlines = fd_lines_load(fd, &numlines);
5237 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5241 /* Set the portname to what the script says the portname should be. */
5242 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5243 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5245 /* Send SIGHUP to process group... is there a better way? */
5250 file_lines_free(qlines);
5254 /********************************************************************
5255 * Called by spoolss_api_setprinter
5256 * when updating a printer description.
5257 ********************************************************************/
5259 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5260 const SPOOL_PRINTER_INFO_LEVEL *info,
5261 DEVICEMODE *devmode)
5264 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5265 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5268 DEBUG(8,("update_printer\n"));
5273 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5274 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5275 result = WERR_UNKNOWN_LEVEL;
5280 result = WERR_BADFID;
5284 if (!get_printer_snum(p, handle, &snum)) {
5285 result = WERR_BADFID;
5289 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5290 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5291 result = WERR_BADFID;
5295 DEBUGADD(8,("Converting info_2 struct\n"));
5298 * convert_printer_info converts the incoming
5299 * info from the client and overwrites the info
5300 * just read from the tdb in the pointer 'printer'.
5303 if (!convert_printer_info(info, printer, level)) {
5304 result = WERR_NOMEM;
5309 /* we have a valid devmode
5310 convert it and link it*/
5312 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5313 if (!convert_devicemode(printer->info_2->printername, devmode,
5314 &printer->info_2->devmode)) {
5315 result = WERR_NOMEM;
5320 /* Do sanity check on the requested changes for Samba */
5322 if (!check_printer_ok(printer->info_2, snum)) {
5323 result = WERR_INVALID_PARAM;
5330 * Another one of those historical misunderstandings...
5331 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5332 * I'm leaving it here as a reminder. --jerry
5335 if (nt_printer_info_level_equal(printer, old_printer)) {
5336 DEBUG(3, ("update_printer: printer info has not changed\n"));
5343 /* Check calling user has permission to update printer description */
5345 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5346 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5347 result = WERR_ACCESS_DENIED;
5351 /* Call addprinter hook */
5353 if (*lp_addprinter_cmd()) {
5354 if ( !add_printer_hook(printer) ) {
5355 result = WERR_ACCESS_DENIED;
5361 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5362 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5363 * requires Win32 client code (see other notes elsewhere in the code).
5365 if (printer->info_2->devmode &&
5366 printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY)
5369 DEBUG(10,("update_printer: Save printer driver init data\n"));
5370 printer->info_2->devmode->displayfrequency = 0;
5372 if (update_driver_init(*printer, 2)!=0) {
5373 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5374 result = WERR_ACCESS_DENIED;
5378 /* we need to reset all driver init data for all printers
5379 bound to this driver */
5381 srv_spoolss_reset_printerdata( printer->info_2->drivername );
5387 * When a *new* driver is bound to a printer, the drivername is used to
5388 * lookup previously saved driver initialization info, which is then
5389 * bound to the printer, simulating what happens in the Windows arch.
5391 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5393 if (!set_driver_init(printer, 2))
5395 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5396 printer->info_2->drivername));
5399 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5400 printer->info_2->drivername));
5402 notify_printer_driver(snum, printer->info_2->drivername);
5406 /* Update printer info */
5407 result = mod_a_printer(*printer, 2);
5409 /* flag which changes actually occured. This is a small subset of
5410 all the possible changes */
5412 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5413 notify_printer_comment(snum, printer->info_2->comment);
5415 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5416 notify_printer_sharename(snum, printer->info_2->sharename);
5418 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5419 notify_printer_port(snum, printer->info_2->portname);
5421 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5422 notify_printer_location(snum, printer->info_2->location);
5425 free_a_printer(&printer, 2);
5426 free_a_printer(&old_printer, 2);
5432 /****************************************************************************
5433 ****************************************************************************/
5435 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5437 POLICY_HND *handle = &q_u->handle;
5438 uint32 level = q_u->level;
5439 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5440 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5441 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5442 uint32 command = q_u->command;
5444 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5447 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5451 /* check the level */
5454 return control_printer(handle, command, p);
5456 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5458 return update_printer_sec(handle, level, info, p,
5461 return WERR_UNKNOWN_LEVEL;
5465 /****************************************************************************
5466 ****************************************************************************/
5468 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5470 POLICY_HND *handle = &q_u->handle;
5472 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5475 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5479 if (Printer->notify.client_connected==True)
5480 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5482 Printer->notify.flags=0;
5483 Printer->notify.options=0;
5484 Printer->notify.localmachine[0]='\0';
5485 Printer->notify.printerlocal=0;
5486 if (Printer->notify.option)
5487 free_spool_notify_option(&Printer->notify.option);
5488 Printer->notify.client_connected=False;
5493 /****************************************************************************
5494 ****************************************************************************/
5496 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5498 /* that's an [in out] buffer (despite appearences to the contrary) */
5499 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5502 return WERR_INVALID_PARAM; /* this is what a NT server
5503 returns for AddJob. AddJob
5504 must fail on non-local
5508 /****************************************************************************
5509 ****************************************************************************/
5511 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5512 int position, int snum)
5518 t=gmtime(&queue->time);
5519 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5521 job_info->jobid=queue->job;
5522 init_unistr(&job_info->printername, lp_servicename(snum));
5523 init_unistr(&job_info->machinename, temp_name);
5524 init_unistr(&job_info->username, queue->fs_user);
5525 init_unistr(&job_info->document, queue->fs_file);
5526 init_unistr(&job_info->datatype, "RAW");
5527 init_unistr(&job_info->text_status, "");
5528 job_info->status=nt_printj_status(queue->status);
5529 job_info->priority=queue->priority;
5530 job_info->position=position;
5531 job_info->totalpages=queue->page_count;
5532 job_info->pagesprinted=0;
5534 make_systemtime(&job_info->submitted, t);
5537 /****************************************************************************
5538 ****************************************************************************/
5540 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5541 int position, int snum,
5542 NT_PRINTER_INFO_LEVEL *ntprinter,
5543 DEVICEMODE *devmode)
5549 t=gmtime(&queue->time);
5550 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5552 job_info->jobid=queue->job;
5554 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5556 init_unistr(&job_info->printername, chaine);
5558 init_unistr(&job_info->machinename, temp_name);
5559 init_unistr(&job_info->username, queue->fs_user);
5560 init_unistr(&job_info->document, queue->fs_file);
5561 init_unistr(&job_info->notifyname, queue->fs_user);
5562 init_unistr(&job_info->datatype, "RAW");
5563 init_unistr(&job_info->printprocessor, "winprint");
5564 init_unistr(&job_info->parameters, "");
5565 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5566 init_unistr(&job_info->text_status, "");
5568 /* and here the security descriptor */
5570 job_info->status=nt_printj_status(queue->status);
5571 job_info->priority=queue->priority;
5572 job_info->position=position;
5573 job_info->starttime=0;
5574 job_info->untiltime=0;
5575 job_info->totalpages=queue->page_count;
5576 job_info->size=queue->size;
5577 make_systemtime(&(job_info->submitted), t);
5578 job_info->timeelapsed=0;
5579 job_info->pagesprinted=0;
5581 job_info->devmode = devmode;
5586 /****************************************************************************
5587 Enumjobs at level 1.
5588 ****************************************************************************/
5590 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5591 NEW_BUFFER *buffer, uint32 offered,
5592 uint32 *needed, uint32 *returned)
5597 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5604 for (i=0; i<*returned; i++)
5605 fill_job_info_1(&info[i], &queue[i], i, snum);
5609 /* check the required size. */
5610 for (i=0; i<*returned; i++)
5611 (*needed) += spoolss_size_job_info_1(&info[i]);
5613 if (!alloc_buffer_size(buffer, *needed)) {
5615 return WERR_INSUFFICIENT_BUFFER;
5618 /* fill the buffer with the structures */
5619 for (i=0; i<*returned; i++)
5620 smb_io_job_info_1("", buffer, &info[i], 0);
5625 if (*needed > offered) {
5627 return WERR_INSUFFICIENT_BUFFER;
5633 /****************************************************************************
5634 Enumjobs at level 2.
5635 ****************************************************************************/
5637 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5638 NEW_BUFFER *buffer, uint32 offered,
5639 uint32 *needed, uint32 *returned)
5641 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5642 JOB_INFO_2 *info = NULL;
5645 DEVICEMODE *devmode = NULL;
5647 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5650 result = WERR_NOMEM;
5654 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5655 if (!W_ERROR_IS_OK(result)) {
5660 if (!(devmode = construct_dev_mode(snum))) {
5662 result = WERR_NOMEM;
5666 for (i=0; i<*returned; i++)
5667 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
5670 free_a_printer(&ntprinter, 2);
5673 /* check the required size. */
5674 for (i=0; i<*returned; i++)
5675 (*needed) += spoolss_size_job_info_2(&info[i]);
5677 if (*needed > offered) {
5679 result = WERR_INSUFFICIENT_BUFFER;
5683 if (!alloc_buffer_size(buffer, *needed)) {
5685 result = WERR_INSUFFICIENT_BUFFER;
5689 /* fill the buffer with the structures */
5690 for (i=0; i<*returned; i++)
5691 smb_io_job_info_2("", buffer, &info[i], 0);
5696 free_a_printer(&ntprinter, 2);
5697 free_devmode(devmode);
5705 /****************************************************************************
5707 ****************************************************************************/
5709 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5711 POLICY_HND *handle = &q_u->handle;
5712 uint32 level = q_u->level;
5713 NEW_BUFFER *buffer = NULL;
5714 uint32 offered = q_u->offered;
5715 uint32 *needed = &r_u->needed;
5716 uint32 *returned = &r_u->returned;
5719 print_status_struct prt_status;
5720 print_queue_struct *queue=NULL;
5722 /* that's an [in out] buffer */
5723 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5724 buffer = r_u->buffer;
5726 DEBUG(4,("_spoolss_enumjobs\n"));
5731 if (!get_printer_snum(p, handle, &snum))
5734 *returned = print_queue_status(snum, &queue, &prt_status);
5735 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5737 if (*returned == 0) {
5744 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5746 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5750 return WERR_UNKNOWN_LEVEL;
5754 /****************************************************************************
5755 ****************************************************************************/
5757 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5762 /****************************************************************************
5763 ****************************************************************************/
5765 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5767 POLICY_HND *handle = &q_u->handle;
5768 uint32 jobid = q_u->jobid;
5769 uint32 command = q_u->command;
5771 struct current_user user;
5773 WERROR errcode = WERR_BADFUNC;
5775 if (!get_printer_snum(p, handle, &snum)) {
5779 if (!print_job_exists(snum, jobid)) {
5780 return WERR_INVALID_PRINTER_NAME;
5783 get_current_user(&user, p);
5786 case JOB_CONTROL_CANCEL:
5787 case JOB_CONTROL_DELETE:
5788 if (print_job_delete(&user, snum, jobid, &errcode)) {
5792 case JOB_CONTROL_PAUSE:
5793 if (print_job_pause(&user, snum, jobid, &errcode)) {
5797 case JOB_CONTROL_RESTART:
5798 case JOB_CONTROL_RESUME:
5799 if (print_job_resume(&user, snum, jobid, &errcode)) {
5804 return WERR_UNKNOWN_LEVEL;
5810 /****************************************************************************
5811 Enumerates all printer drivers at level 1.
5812 ****************************************************************************/
5814 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5819 fstring *list = NULL;
5821 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5822 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5826 for (version=0; version<DRIVER_MAX_VERSION; version++) {
5828 ndrivers=get_ntdrivers(&list, architecture, version);
5829 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5835 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5836 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5837 SAFE_FREE(driver_info_1);
5841 else driver_info_1 = tdi1;
5844 for (i=0; i<ndrivers; i++) {
5846 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5847 ZERO_STRUCT(driver);
5848 status = get_a_printer_driver(&driver, 3, list[i],
5849 architecture, version);
5850 if (!W_ERROR_IS_OK(status)) {
5854 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5855 free_a_printer_driver(driver, 3);
5858 *returned+=ndrivers;
5862 /* check the required size. */
5863 for (i=0; i<*returned; i++) {
5864 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5865 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5868 if (!alloc_buffer_size(buffer, *needed)) {
5869 SAFE_FREE(driver_info_1);
5870 return WERR_INSUFFICIENT_BUFFER;
5873 /* fill the buffer with the driver structures */
5874 for (i=0; i<*returned; i++) {
5875 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5876 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5879 SAFE_FREE(driver_info_1);
5881 if (*needed > offered) {
5883 return WERR_INSUFFICIENT_BUFFER;
5889 /****************************************************************************
5890 Enumerates all printer drivers at level 2.
5891 ****************************************************************************/
5893 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5898 fstring *list = NULL;
5900 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5901 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5905 for (version=0; version<DRIVER_MAX_VERSION; version++) {
5907 ndrivers=get_ntdrivers(&list, architecture, version);
5908 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5914 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5915 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5916 SAFE_FREE(driver_info_2);
5920 else driver_info_2 = tdi2;
5923 for (i=0; i<ndrivers; i++) {
5926 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5927 ZERO_STRUCT(driver);
5928 status = get_a_printer_driver(&driver, 3, list[i],
5929 architecture, version);
5930 if (!W_ERROR_IS_OK(status)) {
5934 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5935 free_a_printer_driver(driver, 3);
5938 *returned+=ndrivers;
5942 /* check the required size. */
5943 for (i=0; i<*returned; i++) {
5944 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5945 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5948 if (!alloc_buffer_size(buffer, *needed)) {
5949 SAFE_FREE(driver_info_2);
5950 return WERR_INSUFFICIENT_BUFFER;
5953 /* fill the buffer with the form structures */
5954 for (i=0; i<*returned; i++) {
5955 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5956 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5959 SAFE_FREE(driver_info_2);
5961 if (*needed > offered) {
5963 return WERR_INSUFFICIENT_BUFFER;
5969 /****************************************************************************
5970 Enumerates all printer drivers at level 3.
5971 ****************************************************************************/
5973 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5978 fstring *list = NULL;
5980 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5981 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5985 for (version=0; version<DRIVER_MAX_VERSION; version++) {
5987 ndrivers=get_ntdrivers(&list, architecture, version);
5988 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5994 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5995 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5996 SAFE_FREE(driver_info_3);
6000 else driver_info_3 = tdi3;
6003 for (i=0; i<ndrivers; i++) {
6006 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6007 ZERO_STRUCT(driver);
6008 status = get_a_printer_driver(&driver, 3, list[i],
6009 architecture, version);
6010 if (!W_ERROR_IS_OK(status)) {
6014 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6015 free_a_printer_driver(driver, 3);
6018 *returned+=ndrivers;
6022 /* check the required size. */
6023 for (i=0; i<*returned; i++) {
6024 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6025 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6028 if (!alloc_buffer_size(buffer, *needed)) {
6029 SAFE_FREE(driver_info_3);
6030 return WERR_INSUFFICIENT_BUFFER;
6033 /* fill the buffer with the driver structures */
6034 for (i=0; i<*returned; i++) {
6035 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6036 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6039 for (i=0; i<*returned; i++)
6040 SAFE_FREE(driver_info_3[i].dependentfiles);
6042 SAFE_FREE(driver_info_3);
6044 if (*needed > offered) {
6046 return WERR_INSUFFICIENT_BUFFER;
6052 /****************************************************************************
6053 Enumerates all printer drivers.
6054 ****************************************************************************/
6056 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6058 UNISTR2 *environment = &q_u->environment;
6059 uint32 level = q_u->level;
6060 NEW_BUFFER *buffer = NULL;
6061 uint32 offered = q_u->offered;
6062 uint32 *needed = &r_u->needed;
6063 uint32 *returned = &r_u->returned;
6065 fstring *list = NULL;
6067 fstring architecture;
6069 /* that's an [in out] buffer */
6070 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6071 buffer = r_u->buffer;
6073 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6074 fstrcpy(servername, get_called_name());
6078 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6082 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6084 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6086 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6090 return WERR_UNKNOWN_LEVEL;
6094 /****************************************************************************
6095 ****************************************************************************/
6097 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6099 form->flag=list->flag;
6100 init_unistr(&form->name, list->name);
6101 form->width=list->width;
6102 form->length=list->length;
6103 form->left=list->left;
6104 form->top=list->top;
6105 form->right=list->right;
6106 form->bottom=list->bottom;
6109 /****************************************************************************
6110 ****************************************************************************/
6112 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6114 uint32 level = q_u->level;
6115 NEW_BUFFER *buffer = NULL;
6116 uint32 offered = q_u->offered;
6117 uint32 *needed = &r_u->needed;
6118 uint32 *numofforms = &r_u->numofforms;
6119 uint32 numbuiltinforms;
6121 nt_forms_struct *list=NULL;
6122 nt_forms_struct *builtinlist=NULL;
6127 /* that's an [in out] buffer */
6128 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6129 buffer = r_u->buffer;
6131 DEBUG(4,("_spoolss_enumforms\n"));
6132 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6133 DEBUGADD(5,("Info level [%d]\n", level));
6135 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6136 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6137 *numofforms = get_ntforms(&list);
6138 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6139 *numofforms += numbuiltinforms;
6141 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6145 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6150 /* construct the list of form structures */
6151 for (i=0; i<numbuiltinforms; i++) {
6152 DEBUGADD(6,("Filling form number [%d]\n",i));
6153 fill_form_1(&forms_1[i], &builtinlist[i]);
6156 SAFE_FREE(builtinlist);
6158 for (; i<*numofforms; i++) {
6159 DEBUGADD(6,("Filling form number [%d]\n",i));
6160 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6165 /* check the required size. */
6166 for (i=0; i<numbuiltinforms; i++) {
6167 DEBUGADD(6,("adding form [%d]'s size\n",i));
6168 buffer_size += spoolss_size_form_1(&forms_1[i]);
6170 for (; i<*numofforms; i++) {
6171 DEBUGADD(6,("adding form [%d]'s size\n",i));
6172 buffer_size += spoolss_size_form_1(&forms_1[i]);
6175 *needed=buffer_size;
6177 if (!alloc_buffer_size(buffer, buffer_size)){
6179 return WERR_INSUFFICIENT_BUFFER;
6182 /* fill the buffer with the form structures */
6183 for (i=0; i<numbuiltinforms; i++) {
6184 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6185 smb_io_form_1("", buffer, &forms_1[i], 0);
6187 for (; i<*numofforms; i++) {
6188 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6189 smb_io_form_1("", buffer, &forms_1[i], 0);
6194 if (*needed > offered) {
6196 return WERR_INSUFFICIENT_BUFFER;
6203 SAFE_FREE(builtinlist);
6204 return WERR_UNKNOWN_LEVEL;
6209 /****************************************************************************
6210 ****************************************************************************/
6212 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6214 uint32 level = q_u->level;
6215 UNISTR2 *uni_formname = &q_u->formname;
6216 NEW_BUFFER *buffer = NULL;
6217 uint32 offered = q_u->offered;
6218 uint32 *needed = &r_u->needed;
6220 nt_forms_struct *list=NULL;
6221 nt_forms_struct builtin_form;
6226 int numofforms=0, i=0;
6228 /* that's an [in out] buffer */
6229 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6230 buffer = r_u->buffer;
6232 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6234 DEBUG(4,("_spoolss_getform\n"));
6235 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6236 DEBUGADD(5,("Info level [%d]\n", level));
6238 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6239 if (!foundBuiltin) {
6240 numofforms = get_ntforms(&list);
6241 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6243 if (numofforms == 0)
6250 fill_form_1(&form_1, &builtin_form);
6253 /* Check if the requested name is in the list of form structures */
6254 for (i=0; i<numofforms; i++) {
6256 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6258 if (strequal(form_name, list[i].name)) {
6259 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6260 fill_form_1(&form_1, &list[i]);
6266 if (i == numofforms) {
6270 /* check the required size. */
6272 *needed=spoolss_size_form_1(&form_1);
6274 if (!alloc_buffer_size(buffer, buffer_size)){
6275 return WERR_INSUFFICIENT_BUFFER;
6278 if (*needed > offered) {
6279 return WERR_INSUFFICIENT_BUFFER;
6282 /* fill the buffer with the form structures */
6283 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6284 smb_io_form_1("", buffer, &form_1, 0);
6290 return WERR_UNKNOWN_LEVEL;
6294 /****************************************************************************
6295 ****************************************************************************/
6297 static void fill_port_1(PORT_INFO_1 *port, char *name)
6299 init_unistr(&port->port_name, name);
6302 /****************************************************************************
6303 ****************************************************************************/
6305 static void fill_port_2(PORT_INFO_2 *port, char *name)
6307 init_unistr(&port->port_name, name);
6308 init_unistr(&port->monitor_name, "Local Monitor");
6309 init_unistr(&port->description, "Local Port");
6310 #define PORT_TYPE_WRITE 1
6311 port->port_type=PORT_TYPE_WRITE;
6315 /****************************************************************************
6317 ****************************************************************************/
6319 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6321 PORT_INFO_1 *ports=NULL;
6324 if (*lp_enumports_cmd()) {
6325 char *cmd = lp_enumports_cmd();
6332 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6334 DEBUG(10,("Running [%s]\n", command));
6335 ret = smbrun(command, &fd);
6336 DEBUG(10,("Returned [%d]\n", ret));
6340 /* Is this the best error to return here? */
6341 return WERR_ACCESS_DENIED;
6345 qlines = fd_lines_load(fd, &numlines);
6346 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6350 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6351 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6352 dos_errstr(WERR_NOMEM)));
6353 file_lines_free(qlines);
6357 for (i=0; i<numlines; i++) {
6358 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6359 fill_port_1(&ports[i], qlines[i]);
6362 file_lines_free(qlines);
6365 *returned = numlines;
6368 *returned = 1; /* Sole Samba port returned. */
6370 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6373 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6375 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6378 /* check the required size. */
6379 for (i=0; i<*returned; i++) {
6380 DEBUGADD(6,("adding port [%d]'s size\n", i));
6381 *needed += spoolss_size_port_info_1(&ports[i]);
6384 if (!alloc_buffer_size(buffer, *needed)) {
6386 return WERR_INSUFFICIENT_BUFFER;
6389 /* fill the buffer with the ports structures */
6390 for (i=0; i<*returned; i++) {
6391 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6392 smb_io_port_1("", buffer, &ports[i], 0);
6397 if (*needed > offered) {
6399 return WERR_INSUFFICIENT_BUFFER;
6405 /****************************************************************************
6407 ****************************************************************************/
6409 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6411 PORT_INFO_2 *ports=NULL;
6414 if (*lp_enumports_cmd()) {
6415 char *cmd = lp_enumports_cmd();
6424 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6425 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6427 path = lp_lockdir();
6429 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6430 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6433 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6434 ret = smbrun(command, &fd);
6435 DEBUGADD(10,("returned [%d]\n", ret));
6439 /* Is this the best error to return here? */
6440 return WERR_ACCESS_DENIED;
6444 qlines = fd_lines_load(fd, &numlines);
6445 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6449 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6450 file_lines_free(qlines);
6454 for (i=0; i<numlines; i++) {
6455 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6456 fill_port_2(&(ports[i]), qlines[i]);
6459 file_lines_free(qlines);
6462 *returned = numlines;
6468 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6471 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6473 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6476 /* check the required size. */
6477 for (i=0; i<*returned; i++) {
6478 DEBUGADD(6,("adding port [%d]'s size\n", i));
6479 *needed += spoolss_size_port_info_2(&ports[i]);
6482 if (!alloc_buffer_size(buffer, *needed)) {
6484 return WERR_INSUFFICIENT_BUFFER;
6487 /* fill the buffer with the ports structures */
6488 for (i=0; i<*returned; i++) {
6489 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6490 smb_io_port_2("", buffer, &ports[i], 0);
6495 if (*needed > offered) {
6497 return WERR_INSUFFICIENT_BUFFER;
6503 /****************************************************************************
6505 ****************************************************************************/
6507 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6509 uint32 level = q_u->level;
6510 NEW_BUFFER *buffer = NULL;
6511 uint32 offered = q_u->offered;
6512 uint32 *needed = &r_u->needed;
6513 uint32 *returned = &r_u->returned;
6515 /* that's an [in out] buffer */
6516 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6517 buffer = r_u->buffer;
6519 DEBUG(4,("_spoolss_enumports\n"));
6526 return enumports_level_1(buffer, offered, needed, returned);
6528 return enumports_level_2(buffer, offered, needed, returned);
6530 return WERR_UNKNOWN_LEVEL;
6534 /****************************************************************************
6535 ****************************************************************************/
6537 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6538 const SPOOL_PRINTER_INFO_LEVEL *info,
6539 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6540 uint32 user_switch, const SPOOL_USER_CTR *user,
6543 NT_PRINTER_INFO_LEVEL *printer = NULL;
6546 WERROR err = WERR_OK;
6548 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6549 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6553 ZERO_STRUCTP(printer);
6555 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6556 if (!convert_printer_info(info, printer, 2)) {
6557 free_a_printer(&printer, 2);
6561 /* check to see if the printer already exists */
6563 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6564 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6565 printer->info_2->sharename));
6566 free_a_printer(&printer, 2);
6567 return WERR_PRINTER_ALREADY_EXISTS;
6570 if (*lp_addprinter_cmd() )
6571 if ( !add_printer_hook(printer) ) {
6572 free_a_printer(&printer,2);
6573 return WERR_ACCESS_DENIED;
6576 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6577 printer->info_2->sharename);
6579 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6580 free_a_printer(&printer,2);
6581 return WERR_ACCESS_DENIED;
6584 /* you must be a printer admin to add a new printer */
6585 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6586 free_a_printer(&printer,2);
6587 return WERR_ACCESS_DENIED;
6591 * Do sanity check on the requested changes for Samba.
6594 if (!check_printer_ok(printer->info_2, snum)) {
6595 free_a_printer(&printer,2);
6596 return WERR_INVALID_PARAM;
6600 * When a printer is created, the drivername bound to the printer is used
6601 * to lookup previously saved driver initialization info, which is then
6602 * bound to the new printer, simulating what happens in the Windows arch.
6606 set_driver_init(printer, 2);
6608 /* A valid devmode was included, convert and link it
6610 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6612 if (!convert_devicemode(printer->info_2->printername, devmode,
6613 &printer->info_2->devmode))
6617 set_driver_init(printer, 2);
6619 /* write the ASCII on disk */
6620 err = mod_a_printer(*printer, 2);
6621 if (!W_ERROR_IS_OK(err)) {
6622 free_a_printer(&printer,2);
6626 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6627 /* Handle open failed - remove addition. */
6628 del_a_printer(printer->info_2->sharename);
6629 free_a_printer(&printer,2);
6630 return WERR_ACCESS_DENIED;
6633 update_c_setprinter(False);
6634 free_a_printer(&printer,2);
6639 /****************************************************************************
6640 ****************************************************************************/
6642 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6644 UNISTR2 *uni_srv_name = &q_u->server_name;
6645 uint32 level = q_u->level;
6646 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6647 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6648 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6649 uint32 user_switch = q_u->user_switch;
6650 SPOOL_USER_CTR *user = &q_u->user_ctr;
6651 POLICY_HND *handle = &r_u->handle;
6655 /* we don't handle yet */
6656 /* but I know what to do ... */
6657 return WERR_UNKNOWN_LEVEL;
6659 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6661 user_switch, user, handle);
6663 return WERR_UNKNOWN_LEVEL;
6667 /****************************************************************************
6668 ****************************************************************************/
6670 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6672 uint32 level = q_u->level;
6673 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6674 WERROR err = WERR_OK;
6675 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6676 struct current_user user;
6677 fstring driver_name;
6680 ZERO_STRUCT(driver);
6682 get_current_user(&user, p);
6684 if (!convert_printer_driver_info(info, &driver, level)) {
6689 DEBUG(5,("Cleaning driver's information\n"));
6690 err = clean_up_driver_struct(driver, level, &user);
6691 if (!W_ERROR_IS_OK(err))
6694 DEBUG(5,("Moving driver to final destination\n"));
6695 if(!move_driver_to_download_area(driver, level, &user, &err)) {
6696 if (W_ERROR_IS_OK(err))
6697 err = WERR_ACCESS_DENIED;
6701 if (add_a_printer_driver(driver, level)!=0) {
6702 err = WERR_ACCESS_DENIED;
6706 /* BEGIN_ADMIN_LOG */
6709 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6710 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
6711 fstrcpy(driver_name, driver.info_3->name);
6714 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6715 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
6716 fstrcpy(driver_name, driver.info_6->name);
6722 * I think this is where he DrvUpgradePrinter() hook would be
6723 * be called in a driver's interface DLL on a Windows NT 4.0/2k
6724 * server. Right now, we just need to send ourselves a message
6725 * to update each printer bound to this driver. --jerry
6728 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
6729 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
6734 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
6735 * decide if the driver init data should be deleted. The rules are:
6736 * 1) never delete init data if it is a 9x driver, they don't use it anyway
6737 * 2) delete init data only if there is no 2k/Xp driver
6738 * 3) always delete init data
6739 * The generalized rule is always use init data from the highest order driver.
6740 * It is necessary to follow the driver install by an initialization step to
6741 * finish off this process.
6744 version = driver.info_3->cversion;
6745 else if (level == 6)
6746 version = driver.info_6->version;
6751 * 9x printer driver - never delete init data
6754 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
6759 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
6760 * there is no 2k/Xp driver init data for this driver name.
6764 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
6766 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
6768 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
6770 if (!del_driver_init(driver_name))
6771 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
6774 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
6776 free_a_printer_driver(driver1,3);
6777 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
6784 * 2k or Xp printer driver - always delete init data
6787 if (!del_driver_init(driver_name))
6788 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
6792 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
6798 free_a_printer_driver(driver, level);
6802 /********************************************************************
6803 * spoolss_addprinterdriverex
6804 ********************************************************************/
6806 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
6808 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
6809 SPOOL_R_ADDPRINTERDRIVER r_u_local;
6812 * we only support the semantics of AddPrinterDriver()
6813 * i.e. only copy files that are newer than existing ones
6816 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
6817 return WERR_ACCESS_DENIED;
6819 ZERO_STRUCT(q_u_local);
6820 ZERO_STRUCT(r_u_local);
6822 /* just pass the information off to _spoolss_addprinterdriver() */
6823 q_u_local.server_name_ptr = q_u->server_name_ptr;
6824 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
6825 q_u_local.level = q_u->level;
6826 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
6828 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
6831 /****************************************************************************
6832 ****************************************************************************/
6834 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6836 init_unistr(&info->name, name);
6839 /****************************************************************************
6840 ****************************************************************************/
6842 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6846 pstring short_archi;
6847 DRIVER_DIRECTORY_1 *info=NULL;
6849 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6851 if (get_short_archi(short_archi, long_archi)==False)
6852 return WERR_INVALID_ENVIRONMENT;
6854 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6857 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6859 DEBUG(4,("printer driver directory: [%s]\n", path));
6861 fill_driverdir_1(info, path);
6863 *needed += spoolss_size_driverdir_info_1(info);
6865 if (!alloc_buffer_size(buffer, *needed)) {
6867 return WERR_INSUFFICIENT_BUFFER;
6870 smb_io_driverdir_1("", buffer, info, 0);
6874 if (*needed > offered)
6875 return WERR_INSUFFICIENT_BUFFER;
6880 /****************************************************************************
6881 ****************************************************************************/
6883 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6885 UNISTR2 *name = &q_u->name;
6886 UNISTR2 *uni_environment = &q_u->environment;
6887 uint32 level = q_u->level;
6888 NEW_BUFFER *buffer = NULL;
6889 uint32 offered = q_u->offered;
6890 uint32 *needed = &r_u->needed;
6892 /* that's an [in out] buffer */
6893 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6894 buffer = r_u->buffer;
6896 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6902 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6904 return WERR_UNKNOWN_LEVEL;
6908 /****************************************************************************
6909 ****************************************************************************/
6911 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6913 POLICY_HND *handle = &q_u->handle;
6914 uint32 idx = q_u->index;
6915 uint32 in_value_len = q_u->valuesize;
6916 uint32 in_data_len = q_u->datasize;
6917 uint32 *out_max_value_len= &r_u->valuesize;
6918 uint16 **out_value = &r_u->value;
6919 uint32 *out_value_len = &r_u->realvaluesize;
6920 uint32 *out_type = &r_u->type;
6921 uint32 *out_max_data_len = &r_u->datasize;
6922 uint8 **data_out = &r_u->data;
6923 uint32 *out_data_len = &r_u->realdatasize;
6925 NT_PRINTER_INFO_LEVEL *printer = NULL;
6928 uint32 biggest_valuesize;
6929 uint32 biggest_datasize;
6931 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6934 REGISTRY_VALUE *val;
6935 NT_PRINTER_DATA *p_data;
6936 int i, key_index, num_values;
6939 ZERO_STRUCT( printer );
6943 *out_max_data_len = 0;
6947 DEBUG(5,("spoolss_enumprinterdata\n"));
6950 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6954 if (!get_printer_snum(p,handle, &snum))
6957 result = get_a_printer(&printer, 2, lp_servicename(snum));
6958 if (!W_ERROR_IS_OK(result))
6961 p_data = &printer->info_2->data;
6962 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
6967 * The NT machine wants to know the biggest size of value and data
6969 * cf: MSDN EnumPrinterData remark section
6972 if ( !in_value_len && !in_data_len )
6974 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6977 biggest_valuesize = 0;
6978 biggest_datasize = 0;
6980 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
6982 for ( i=0; i<num_values; i++ )
6984 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
6986 name_length = strlen(val->valuename);
6987 if ( strlen(val->valuename) > biggest_valuesize )
6988 biggest_valuesize = name_length;
6990 if ( val->size > biggest_datasize )
6991 biggest_datasize = val->size;
6993 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
6997 /* the value is an UNICODE string but real_value_size is the length
6998 in bytes including the trailing 0 */
7000 *out_value_len = 2 * (1+biggest_valuesize);
7001 *out_data_len = biggest_datasize;
7003 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7009 * the value len is wrong in NT sp3
7010 * that's the number of bytes not the number of unicode chars
7013 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7018 /* out_value should default to "" or else NT4 has
7019 problems unmarshalling the response */
7021 *out_max_value_len = (in_value_len/sizeof(uint16));
7023 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7025 result = WERR_NOMEM;
7029 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7031 /* the data is counted in bytes */
7033 *out_max_data_len = in_data_len;
7034 *out_data_len = in_data_len;
7036 /* only allocate when given a non-zero data_len */
7038 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7040 result = WERR_NOMEM;
7044 result = WERR_NO_MORE_ITEMS;
7050 * - counted in bytes in the request
7051 * - counted in UNICODE chars in the max reply
7052 * - counted in bytes in the real size
7054 * take a pause *before* coding not *during* coding
7058 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7059 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7061 result = WERR_NOMEM;
7065 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7069 *out_type = regval_type( val );
7071 /* data - counted in bytes */
7073 *out_max_data_len = in_data_len;
7074 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7076 result = WERR_NOMEM;
7079 data_len = (size_t)regval_size(val);
7080 memcpy( *data_out, regval_data_p(val), data_len );
7081 *out_data_len = data_len;
7085 free_a_printer(&printer, 2);
7089 /****************************************************************************
7090 ****************************************************************************/
7092 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7094 POLICY_HND *handle = &q_u->handle;
7095 UNISTR2 *value = &q_u->value;
7096 uint32 type = q_u->type;
7097 uint8 *data = q_u->data;
7098 uint32 real_len = q_u->real_len;
7100 NT_PRINTER_INFO_LEVEL *printer = NULL;
7102 WERROR status = WERR_OK;
7103 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7106 DEBUG(5,("spoolss_setprinterdata\n"));
7109 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7113 if (!get_printer_snum(p,handle, &snum))
7117 * Access check : NT returns "access denied" if you make a
7118 * SetPrinterData call without the necessary privildge.
7119 * we were originally returning OK if nothing changed
7120 * which made Win2k issue **a lot** of SetPrinterData
7121 * when connecting to a printer --jerry
7124 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7126 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7127 status = WERR_ACCESS_DENIED;
7131 status = get_a_printer(&printer, 2, lp_servicename(snum));
7132 if (!W_ERROR_IS_OK(status))
7135 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7137 /* save the registry data */
7139 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7140 type, data, real_len );
7143 free_a_printer(&printer, 2);
7148 /****************************************************************************
7149 ****************************************************************************/
7151 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7153 POLICY_HND *handle = &q_u->handle;
7154 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7157 DEBUG(5,("_spoolss_resetprinter\n"));
7160 * All we do is to check to see if the handle and queue is valid.
7161 * This call really doesn't mean anything to us because we only
7162 * support RAW printing. --jerry
7166 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7170 if (!get_printer_snum(p,handle, &snum))
7174 /* blindly return success */
7179 /****************************************************************************
7180 ****************************************************************************/
7182 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7184 POLICY_HND *handle = &q_u->handle;
7185 UNISTR2 *value = &q_u->valuename;
7187 NT_PRINTER_INFO_LEVEL *printer = NULL;
7189 WERROR status = WERR_OK;
7190 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7193 DEBUG(5,("spoolss_deleteprinterdata\n"));
7196 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7200 if (!get_printer_snum(p, handle, &snum))
7203 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7204 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7205 return WERR_ACCESS_DENIED;
7208 status = get_a_printer(&printer, 2, lp_servicename(snum));
7209 if (!W_ERROR_IS_OK(status))
7212 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7214 status = delete_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename );
7215 if ( W_ERROR_IS_OK(status) )
7216 status = mod_a_printer(*printer, 2);
7218 free_a_printer(&printer, 2);
7223 /****************************************************************************
7224 ****************************************************************************/
7226 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7228 POLICY_HND *handle = &q_u->handle;
7229 FORM *form = &q_u->form;
7230 nt_forms_struct tmpForm;
7232 WERROR status = WERR_OK;
7233 NT_PRINTER_INFO_LEVEL *printer = NULL;
7236 nt_forms_struct *list=NULL;
7237 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7239 DEBUG(5,("spoolss_addform\n"));
7242 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7246 if (!get_printer_snum(p,handle, &snum))
7249 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7250 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7251 status = WERR_ACCESS_DENIED;
7255 /* can't add if builtin */
7256 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7257 return WERR_ALREADY_EXISTS;
7260 count=get_ntforms(&list);
7261 if(!add_a_form(&list, form, &count))
7263 write_ntforms(&list, count);
7266 * ChangeID must always be set
7269 status = get_a_printer(&printer, 2, lp_servicename(snum));
7270 if (!W_ERROR_IS_OK(status))
7273 status = mod_a_printer(*printer, 2);
7274 if (!W_ERROR_IS_OK(status))
7278 free_a_printer(&printer, 2);
7284 /****************************************************************************
7285 ****************************************************************************/
7287 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7289 POLICY_HND *handle = &q_u->handle;
7290 UNISTR2 *form_name = &q_u->name;
7291 nt_forms_struct tmpForm;
7293 WERROR ret = WERR_OK;
7294 nt_forms_struct *list=NULL;
7295 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7297 WERROR status = WERR_OK;
7298 NT_PRINTER_INFO_LEVEL *printer = NULL;
7300 DEBUG(5,("spoolss_deleteform\n"));
7303 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7307 if (!get_printer_snum(p, handle, &snum))
7310 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7311 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
7312 return WERR_ACCESS_DENIED;
7315 /* can't delete if builtin */
7316 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7317 return WERR_INVALID_PARAM;
7320 count = get_ntforms(&list);
7321 if(!delete_a_form(&list, form_name, &count, &ret))
7322 return WERR_INVALID_PARAM;
7325 * ChangeID must always be set
7328 status = get_a_printer(&printer, 2, lp_servicename(snum));
7329 if (!W_ERROR_IS_OK(status))
7332 status = mod_a_printer(*printer, 2);
7333 if (!W_ERROR_IS_OK(status))
7337 free_a_printer(&printer, 2);
7343 /****************************************************************************
7344 ****************************************************************************/
7346 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7348 POLICY_HND *handle = &q_u->handle;
7349 FORM *form = &q_u->form;
7350 nt_forms_struct tmpForm;
7352 WERROR status = WERR_OK;
7353 NT_PRINTER_INFO_LEVEL *printer = NULL;
7356 nt_forms_struct *list=NULL;
7357 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7359 DEBUG(5,("spoolss_setform\n"));
7362 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7366 if (!get_printer_snum(p, handle, &snum))
7369 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7370 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7371 return WERR_ACCESS_DENIED;
7374 /* can't set if builtin */
7375 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7376 return WERR_INVALID_PARAM;
7379 count=get_ntforms(&list);
7380 update_a_form(&list, form, count);
7381 write_ntforms(&list, count);
7384 * ChangeID must always be set
7387 status = get_a_printer(&printer, 2, lp_servicename(snum));
7388 if (!W_ERROR_IS_OK(status))
7391 status = mod_a_printer(*printer, 2);
7392 if (!W_ERROR_IS_OK(status))
7396 free_a_printer(&printer, 2);
7402 /****************************************************************************
7403 enumprintprocessors level 1.
7404 ****************************************************************************/
7406 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7408 PRINTPROCESSOR_1 *info_1=NULL;
7410 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7415 init_unistr(&info_1->name, "winprint");
7417 *needed += spoolss_size_printprocessor_info_1(info_1);
7419 if (!alloc_buffer_size(buffer, *needed))
7420 return WERR_INSUFFICIENT_BUFFER;
7422 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7426 if (*needed > offered) {
7428 return WERR_INSUFFICIENT_BUFFER;
7434 /****************************************************************************
7435 ****************************************************************************/
7437 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7439 uint32 level = q_u->level;
7440 NEW_BUFFER *buffer = NULL;
7441 uint32 offered = q_u->offered;
7442 uint32 *needed = &r_u->needed;
7443 uint32 *returned = &r_u->returned;
7445 /* that's an [in out] buffer */
7446 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7447 buffer = r_u->buffer;
7449 DEBUG(5,("spoolss_enumprintprocessors\n"));
7452 * Enumerate the print processors ...
7454 * Just reply with "winprint", to keep NT happy
7455 * and I can use my nice printer checker.
7463 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7465 return WERR_UNKNOWN_LEVEL;
7469 /****************************************************************************
7470 enumprintprocdatatypes level 1.
7471 ****************************************************************************/
7473 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7475 PRINTPROCDATATYPE_1 *info_1=NULL;
7477 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7482 init_unistr(&info_1->name, "RAW");
7484 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7486 if (!alloc_buffer_size(buffer, *needed))
7487 return WERR_INSUFFICIENT_BUFFER;
7489 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7493 if (*needed > offered) {
7495 return WERR_INSUFFICIENT_BUFFER;
7501 /****************************************************************************
7502 ****************************************************************************/
7504 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7506 uint32 level = q_u->level;
7507 NEW_BUFFER *buffer = NULL;
7508 uint32 offered = q_u->offered;
7509 uint32 *needed = &r_u->needed;
7510 uint32 *returned = &r_u->returned;
7512 /* that's an [in out] buffer */
7513 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7514 buffer = r_u->buffer;
7516 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7523 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7525 return WERR_UNKNOWN_LEVEL;
7529 /****************************************************************************
7530 enumprintmonitors level 1.
7531 ****************************************************************************/
7533 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7535 PRINTMONITOR_1 *info_1=NULL;
7537 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7542 init_unistr(&info_1->name, "Local Port");
7544 *needed += spoolss_size_printmonitor_info_1(info_1);
7546 if (!alloc_buffer_size(buffer, *needed))
7547 return WERR_INSUFFICIENT_BUFFER;
7549 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7553 if (*needed > offered) {
7555 return WERR_INSUFFICIENT_BUFFER;
7561 /****************************************************************************
7562 enumprintmonitors level 2.
7563 ****************************************************************************/
7565 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7567 PRINTMONITOR_2 *info_2=NULL;
7569 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7574 init_unistr(&info_2->name, "Local Port");
7575 init_unistr(&info_2->environment, "Windows NT X86");
7576 init_unistr(&info_2->dll_name, "localmon.dll");
7578 *needed += spoolss_size_printmonitor_info_2(info_2);
7580 if (!alloc_buffer_size(buffer, *needed))
7581 return WERR_INSUFFICIENT_BUFFER;
7583 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7587 if (*needed > offered) {
7589 return WERR_INSUFFICIENT_BUFFER;
7595 /****************************************************************************
7596 ****************************************************************************/
7598 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7600 uint32 level = q_u->level;
7601 NEW_BUFFER *buffer = NULL;
7602 uint32 offered = q_u->offered;
7603 uint32 *needed = &r_u->needed;
7604 uint32 *returned = &r_u->returned;
7606 /* that's an [in out] buffer */
7607 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7608 buffer = r_u->buffer;
7610 DEBUG(5,("spoolss_enumprintmonitors\n"));
7613 * Enumerate the print monitors ...
7615 * Just reply with "Local Port", to keep NT happy
7616 * and I can use my nice printer checker.
7624 return enumprintmonitors_level_1(buffer, offered, needed, returned);
7626 return enumprintmonitors_level_2(buffer, offered, needed, returned);
7628 return WERR_UNKNOWN_LEVEL;
7632 /****************************************************************************
7633 ****************************************************************************/
7635 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7639 JOB_INFO_1 *info_1=NULL;
7641 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
7643 if (info_1 == NULL) {
7648 for (i=0; i<count && found==False; i++) {
7649 if (queue[i].job==(int)jobid)
7656 /* NT treats not found as bad param... yet another bad choice */
7657 return WERR_INVALID_PARAM;
7660 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
7664 *needed += spoolss_size_job_info_1(info_1);
7666 if (!alloc_buffer_size(buffer, *needed)) {
7668 return WERR_INSUFFICIENT_BUFFER;
7671 smb_io_job_info_1("", buffer, info_1, 0);
7675 if (*needed > offered)
7676 return WERR_INSUFFICIENT_BUFFER;
7681 /****************************************************************************
7682 ****************************************************************************/
7684 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7689 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
7691 DEVICEMODE *devmode = NULL;
7693 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
7695 ZERO_STRUCTP(info_2);
7697 if (info_2 == NULL) {
7702 for (i=0; i<count && found==False; i++) {
7703 if (queue[i].job==(int)jobid)
7708 /* NT treats not found as bad param... yet another bad
7710 ret = WERR_INVALID_PARAM;
7714 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
7715 if (!W_ERROR_IS_OK(ret))
7717 if (construct_dev_mode(snum) == NULL) {
7722 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
7724 *needed += spoolss_size_job_info_2(info_2);
7726 if (!alloc_buffer_size(buffer, *needed)) {
7727 ret = WERR_INSUFFICIENT_BUFFER;
7731 smb_io_job_info_2("", buffer, info_2, 0);
7733 if (*needed > offered) {
7734 ret = WERR_INSUFFICIENT_BUFFER;
7741 /* Cleanup allocated memory */
7744 free_job_info_2(info_2); /* Also frees devmode */
7746 free_a_printer(&ntprinter, 2);
7751 /****************************************************************************
7752 ****************************************************************************/
7754 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
7756 POLICY_HND *handle = &q_u->handle;
7757 uint32 jobid = q_u->jobid;
7758 uint32 level = q_u->level;
7759 NEW_BUFFER *buffer = NULL;
7760 uint32 offered = q_u->offered;
7761 uint32 *needed = &r_u->needed;
7765 print_queue_struct *queue=NULL;
7766 print_status_struct prt_status;
7768 /* that's an [in out] buffer */
7769 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7770 buffer = r_u->buffer;
7772 DEBUG(5,("spoolss_getjob\n"));
7776 if (!get_printer_snum(p, handle, &snum))
7779 count = print_queue_status(snum, &queue, &prt_status);
7781 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7782 count, prt_status.status, prt_status.message));
7786 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
7788 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
7791 return WERR_UNKNOWN_LEVEL;
7795 /********************************************************************
7796 spoolss_getprinterdataex
7798 From MSDN documentation of GetPrinterDataEx: pass request
7799 to GetPrinterData if key is "PrinterDriverData".
7800 ********************************************************************/
7802 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
7804 POLICY_HND *handle = &q_u->handle;
7805 uint32 in_size = q_u->size;
7806 uint32 *type = &r_u->type;
7807 uint32 *out_size = &r_u->size;
7808 uint8 **data = &r_u->data;
7809 uint32 *needed = &r_u->needed;
7810 fstring keyname, valuename;
7812 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7814 NT_PRINTER_INFO_LEVEL *printer = NULL;
7816 WERROR status = WERR_OK;
7818 DEBUG(4,("_spoolss_getprinterdataex\n"));
7820 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
7821 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
7823 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
7824 keyname, valuename));
7826 /* in case of problem, return some default values */
7830 *out_size = in_size;
7833 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
7835 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7839 /* Is the handle to a printer or to the server? */
7841 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
7843 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7844 return WERR_INVALID_PARAM;
7847 if ( !get_printer_snum(p,handle, &snum) )
7850 status = get_a_printer(&printer, 2, lp_servicename(snum));
7851 if ( !W_ERROR_IS_OK(status) )
7854 /* check to see if the keyname is valid */
7855 if ( !strlen(keyname) ) {
7856 status = WERR_INVALID_PARAM;
7860 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
7861 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
7862 status = WERR_BADFILE;
7866 /* When given a new keyname, we should just create it */
7868 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
7870 if ( !W_ERROR_IS_OK(status) )
7872 DEBUG(5, ("value not found, allocating %d\n", *out_size));
7874 /* reply this param doesn't exist */
7878 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
7879 status = WERR_NOMEM;
7887 if (*needed > *out_size)
7888 status = WERR_MORE_DATA;
7891 free_a_printer( &printer, 2 );
7896 /********************************************************************
7897 * spoolss_setprinterdata
7898 ********************************************************************/
7900 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
7902 POLICY_HND *handle = &q_u->handle;
7903 uint32 type = q_u->type;
7904 uint8 *data = q_u->data;
7905 uint32 real_len = q_u->real_len;
7907 NT_PRINTER_INFO_LEVEL *printer = NULL;
7909 WERROR status = WERR_OK;
7910 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7914 DEBUG(4,("_spoolss_setprinterdataex\n"));
7916 /* From MSDN documentation of SetPrinterDataEx: pass request to
7917 SetPrinterData if key is "PrinterDriverData" */
7920 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7924 if ( !get_printer_snum(p,handle, &snum) )
7928 * Access check : NT returns "access denied" if you make a
7929 * SetPrinterData call without the necessary privildge.
7930 * we were originally returning OK if nothing changed
7931 * which made Win2k issue **a lot** of SetPrinterData
7932 * when connecting to a printer --jerry
7935 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7937 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
7938 return WERR_ACCESS_DENIED;
7941 status = get_a_printer(&printer, 2, lp_servicename(snum));
7942 if (!W_ERROR_IS_OK(status))
7945 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
7946 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
7948 /* save the registry data */
7950 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
7952 free_a_printer(&printer, 2);
7958 /********************************************************************
7959 * spoolss_deleteprinterdataex
7960 ********************************************************************/
7962 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
7964 POLICY_HND *handle = &q_u->handle;
7965 UNISTR2 *value = &q_u->valuename;
7966 UNISTR2 *key = &q_u->keyname;
7968 NT_PRINTER_INFO_LEVEL *printer = NULL;
7970 WERROR status = WERR_OK;
7971 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7972 pstring valuename, keyname;
7974 DEBUG(5,("spoolss_deleteprinterdataex\n"));
7977 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7981 if (!get_printer_snum(p, handle, &snum))
7984 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7985 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
7986 return WERR_ACCESS_DENIED;
7989 status = get_a_printer(&printer, 2, lp_servicename(snum));
7990 if (!W_ERROR_IS_OK(status))
7993 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7994 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
7996 status = delete_printer_data( printer->info_2, keyname, valuename );
7997 if ( W_ERROR_IS_OK(status) )
7998 status = mod_a_printer(*printer, 2);
8000 free_a_printer(&printer, 2);
8005 /********************************************************************
8006 * spoolss_enumprinterkey
8007 ********************************************************************/
8010 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8013 fstring *keynames = NULL;
8014 uint16 *enumkeys = NULL;
8017 POLICY_HND *handle = &q_u->handle;
8018 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8019 NT_PRINTER_DATA *data;
8020 NT_PRINTER_INFO_LEVEL *printer = NULL;
8022 WERROR status = WERR_BADFILE;
8025 DEBUG(4,("_spoolss_enumprinterkey\n"));
8028 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8032 if ( !get_printer_snum(p,handle, &snum) )
8035 status = get_a_printer(&printer, 2, lp_servicename(snum));
8036 if (!W_ERROR_IS_OK(status))
8039 /* get the list of subkey names */
8041 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8042 data = &printer->info_2->data;
8044 num_keys = get_printer_subkeys( data, key, &keynames );
8046 if ( num_keys == -1 ) {
8047 status = WERR_BADFILE;
8051 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8053 r_u->needed = printerkey_len*2;
8055 if ( q_u->size < r_u->needed ) {
8056 status = WERR_MORE_DATA;
8060 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8061 status = WERR_NOMEM;
8067 if ( q_u->size < r_u->needed )
8068 status = WERR_MORE_DATA;
8071 free_a_printer( &printer, 2 );
8072 SAFE_FREE( keynames );
8077 /********************************************************************
8078 * spoolss_deleteprinterkey
8079 ********************************************************************/
8081 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8083 POLICY_HND *handle = &q_u->handle;
8084 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8086 NT_PRINTER_INFO_LEVEL *printer = NULL;
8090 DEBUG(5,("spoolss_deleteprinterkey\n"));
8093 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8097 /* if keyname == NULL, return error */
8099 if ( !q_u->keyname.buffer )
8100 return WERR_INVALID_PARAM;
8102 if (!get_printer_snum(p, handle, &snum))
8105 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8106 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8107 return WERR_ACCESS_DENIED;
8110 status = get_a_printer(&printer, 2, lp_servicename(snum));
8111 if (!W_ERROR_IS_OK(status))
8114 /* delete the key and all subneys */
8116 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8118 status = delete_all_printer_data( printer->info_2, key );
8119 if ( W_ERROR_IS_OK(status) )
8120 status = mod_a_printer(*printer, 2);
8122 free_a_printer( &printer, 2 );
8128 /********************************************************************
8129 * spoolss_enumprinterdataex
8130 ********************************************************************/
8132 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8134 POLICY_HND *handle = &q_u->handle;
8135 uint32 in_size = q_u->size;
8138 NT_PRINTER_INFO_LEVEL *printer = NULL;
8139 PRINTER_ENUM_VALUES *enum_values = NULL;
8140 NT_PRINTER_DATA *p_data;
8142 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8147 REGISTRY_VALUE *val;
8152 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8155 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8159 /* first get the printer off of disk */
8161 if (!get_printer_snum(p,handle, &snum))
8164 ZERO_STRUCT(printer);
8165 result = get_a_printer(&printer, 2, lp_servicename(snum));
8166 if (!W_ERROR_IS_OK(result))
8169 /* now look for a match on the key name */
8171 p_data = &printer->info_2->data;
8173 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8174 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8176 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8177 result = WERR_INVALID_PARAM;
8184 /* allocate the memory for the array of pointers -- if necessary */
8186 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8189 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8191 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8192 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8193 result = WERR_NOMEM;
8197 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8201 * loop through all params and build the array to pass
8202 * back to the client
8205 for ( i=0; i<num_entries; i++ )
8207 /* lookup the registry value */
8209 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8210 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8214 value_name = regval_name( val );
8215 init_unistr( &enum_values[i].valuename, value_name );
8216 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8217 enum_values[i].type = regval_type( val );
8219 data_len = regval_size( val );
8221 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8223 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8225 result = WERR_NOMEM;
8229 enum_values[i].data_len = data_len;
8231 /* keep track of the size of the array in bytes */
8233 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8236 /* housekeeping information in the reply */
8238 r_u->needed = needed;
8239 r_u->returned = num_entries;
8241 if (needed > in_size) {
8242 result = WERR_MORE_DATA;
8246 /* copy data into the reply */
8248 r_u->ctr.size = r_u->needed;
8249 r_u->ctr.size_of_array = r_u->returned;
8250 r_u->ctr.values = enum_values;
8255 free_a_printer(&printer, 2);
8260 /****************************************************************************
8261 ****************************************************************************/
8263 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8265 init_unistr(&info->name, name);
8268 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8269 UNISTR2 *environment,
8276 pstring short_archi;
8277 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8279 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8281 if (get_short_archi(short_archi, long_archi)==False)
8282 return WERR_INVALID_ENVIRONMENT;
8284 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8287 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8289 fill_printprocessordirectory_1(info, path);
8291 *needed += spoolss_size_printprocessordirectory_info_1(info);
8293 if (!alloc_buffer_size(buffer, *needed)) {
8295 return WERR_INSUFFICIENT_BUFFER;
8298 smb_io_printprocessordirectory_1("", buffer, info, 0);
8302 if (*needed > offered)
8303 return WERR_INSUFFICIENT_BUFFER;
8308 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8310 uint32 level = q_u->level;
8311 NEW_BUFFER *buffer = NULL;
8312 uint32 offered = q_u->offered;
8313 uint32 *needed = &r_u->needed;
8316 /* that's an [in out] buffer */
8317 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8318 buffer = r_u->buffer;
8320 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8326 result = getprintprocessordirectory_level_1
8327 (&q_u->name, &q_u->environment, buffer, offered, needed);
8329 result = WERR_UNKNOWN_LEVEL;
8337 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
8338 SPOOL_R_REPLYOPENPRINTER *r_u)
8340 DEBUG(5,("_spoolss_replyopenprinter\n"));
8342 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
8347 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
8348 SPOOL_R_REPLYCLOSEPRINTER *r_u)
8350 DEBUG(5,("_spoolss_replycloseprinter\n"));