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-2001,
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 int 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 cli;
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(&cli, 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(&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", NULL },
672 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", NULL },
673 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", NULL },
674 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", NULL },
675 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", NULL },
676 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", NULL },
677 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", NULL },
678 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
679 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", NULL },
680 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", NULL },
681 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
682 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", NULL },
683 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
684 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", NULL },
685 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", NULL },
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 for (p = printers_list; p; p = p->next) {
730 SPOOL_NOTIFY_INFO_DATA *data;
734 /* Is there notification on this handle? */
736 if (!p->notify.client_connected)
739 /* For this printer? Print servers always receive
742 if (p->printer_type == PRINTER_HANDLE_IS_PRINTER &&
743 !strequal(msg->printer, p->dev.handlename))
746 /* Are we monitoring this event? */
748 if (!is_monitoring_event(p, msg->type, msg->field))
751 /* OK - send the event to the client */
753 data = talloc(mem_ctx, sizeof(SPOOL_NOTIFY_INFO_DATA));
757 /* Convert unix jobid to smb jobid */
761 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
763 id = sysjob_to_jobid(msg->id);
766 DEBUG(3, ("no such unix jobid %d\n", msg->id));
771 construct_info_data(data, msg->type, msg->field, id);
774 case PRINTER_NOTIFY_TYPE:
775 if (printer_notify_table[msg->field].fn)
776 printer_notify_table[msg->field].fn(
781 case JOB_NOTIFY_TYPE:
782 if (job_notify_table[msg->field].fn)
783 job_notify_table[msg->field].fn(
789 DEBUG(5, ("Unknown notification type %d\n",
794 if (!p->notify.flags)
796 &cli, mem_ctx, &p->notify.client_hnd,
797 data_len, data, p->notify.change, 0);
799 NT_PRINTER_INFO_LEVEL *printer = NULL;
801 get_a_printer(&printer, 2, msg->printer);
804 DEBUG(5, ("unable to load info2 for %s\n",
809 /* XXX: This needs to be updated for
810 PRINTER_CHANGE_SET_PRINTER_DRIVER. */
812 cli_spoolss_routerreplyprinter(
813 &cli, mem_ctx, &p->notify.client_hnd,
814 0, printer->info_2->changeid);
816 free_a_printer(&printer, 2);
823 /* Receive a notify2 message */
825 static void receive_notify2_message(int msg_type, pid_t src, void *buf,
828 struct spoolss_notify_msg msg;
830 TALLOC_CTX *mem_ctx = talloc_init();
836 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
839 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
840 &msg.type, &msg.field, &msg.id, &msg.len, &msg.flags);
843 tdb_unpack((char *)buf + offset, len - offset, "dd",
844 &msg.notify.value[0], &msg.notify.value[1]);
846 tdb_unpack((char *)buf + offset, len - offset, "B",
847 &msg.len, &msg.notify.data);
849 DEBUG(3, ("got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
850 msg.type, msg.field, msg.flags));
853 DEBUG(3, ("value1 = %d, value2 = %d\n", msg.notify.value[0],
854 msg.notify.value[1]));
856 dump_data(3, msg.notify.data, msg.len);
858 /* Process message */
860 process_notify2_message(&msg, mem_ctx);
865 free(msg.notify.data);
867 talloc_destroy(mem_ctx);
870 /***************************************************************************
871 Server wrapper for cli_spoolss_routerreplyprinter() since the client
872 function can only send a single change notification at a time.
874 FIXME!!! only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
876 **************************************************************************/
878 static WERROR srv_spoolss_routerreplyprinter (struct cli_state *reply_cli, TALLOC_CTX *mem_ctx,
879 POLICY_HND *pol, PRINTER_MESSAGE_INFO *info,
880 NT_PRINTER_INFO_LEVEL *printer)
883 uint32 condition = 0x0;
885 if (info->flags & PRINTER_MESSAGE_DRIVER)
886 condition = PRINTER_CHANGE_SET_PRINTER_DRIVER;
888 result = cli_spoolss_routerreplyprinter(reply_cli, mem_ctx, pol, condition,
889 printer->info_2->changeid);
894 /********************************************************************
895 Send a message to ourself about new driver being installed
896 so we can upgrade the information for each printer bound to this
898 ********************************************************************/
900 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
902 int len = strlen(drivername);
907 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
910 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
915 /**********************************************************************
916 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
917 over all printers, upgrading ones as neessary
918 **********************************************************************/
920 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
924 int n_services = lp_numservices();
926 len = MIN(len,sizeof(drivername)-1);
927 strncpy(drivername, buf, len);
929 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
931 /* Iterate the printer list */
933 for (snum=0; snum<n_services; snum++)
935 if (lp_snum_ok(snum) && lp_print_ok(snum) )
938 NT_PRINTER_INFO_LEVEL *printer = NULL;
940 result = get_a_printer(&printer, 2, lp_servicename(snum));
941 if (!W_ERROR_IS_OK(result))
944 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
946 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
948 /* all we care about currently is the change_id */
950 result = mod_a_printer(*printer, 2);
951 if (!W_ERROR_IS_OK(result)) {
952 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
953 dos_errstr(result)));
957 free_a_printer(&printer, 2);
964 /********************************************************************
965 Copy routines used by convert_to_openprinterex()
966 *******************************************************************/
968 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
976 DEBUG (8,("dup_devmode\n"));
978 /* bulk copy first */
980 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
984 /* dup the pointer members separately */
986 len = unistrlen(devmode->devicename.buffer);
988 d->devicename.buffer = talloc(ctx, len*2);
989 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
994 len = unistrlen(devmode->formname.buffer);
996 d->devicename.buffer = talloc(ctx, len*2);
997 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1001 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1006 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1008 if (!new_ctr || !ctr)
1011 DEBUG(8,("copy_devmode_ctr\n"));
1013 new_ctr->size = ctr->size;
1014 new_ctr->devmode_ptr = ctr->devmode_ptr;
1016 if(ctr->devmode_ptr)
1017 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1020 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1022 if (!new_def || !def)
1025 DEBUG(8,("copy_printer_defaults\n"));
1027 new_def->datatype_ptr = def->datatype_ptr;
1029 if (def->datatype_ptr)
1030 copy_unistr2(&new_def->datatype, &def->datatype);
1032 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1034 new_def->access_required = def->access_required;
1037 /********************************************************************
1038 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1039 * SPOOL_Q_OPEN_PRINTER_EX structure
1040 ********************************************************************/
1042 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1044 if (!q_u_ex || !q_u)
1047 DEBUG(8,("convert_to_openprinterex\n"));
1049 q_u_ex->printername_ptr = q_u->printername_ptr;
1051 if (q_u->printername_ptr)
1052 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1054 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1057 /********************************************************************
1058 * spoolss_open_printer
1060 * called from the spoolss dispatcher
1061 ********************************************************************/
1063 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1065 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1066 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1071 ZERO_STRUCT(q_u_ex);
1072 ZERO_STRUCT(r_u_ex);
1074 /* convert the OpenPrinter() call to OpenPrinterEx() */
1076 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1078 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1080 /* convert back to OpenPrinter() */
1082 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1087 /********************************************************************
1088 * spoolss_open_printer
1090 * called from the spoolss dispatcher
1091 ********************************************************************/
1093 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1095 UNISTR2 *printername = NULL;
1096 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1097 /* uint32 user_switch = q_u->user_switch; - notused */
1098 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
1099 POLICY_HND *handle = &r_u->handle;
1103 struct current_user user;
1104 Printer_entry *Printer=NULL;
1106 if (q_u->printername_ptr != 0)
1107 printername = &q_u->printername;
1109 if (printername == NULL)
1110 return WERR_INVALID_PRINTER_NAME;
1112 /* some sanity check because you can open a printer or a print server */
1113 /* aka: \\server\printer or \\server */
1114 unistr2_to_ascii(name, printername, sizeof(name)-1);
1116 DEBUGADD(3,("checking name: %s\n",name));
1118 if (!open_printer_hnd(p, handle, name, 0))
1119 return WERR_INVALID_PRINTER_NAME;
1121 Printer=find_printer_index_by_hnd(p, handle);
1123 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1124 Can't find printer handle we created for printer %s\n", name ));
1125 close_printer_handle(p,handle);
1126 return WERR_INVALID_PRINTER_NAME;
1130 First case: the user is opening the print server:
1132 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1133 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1135 Then both Win2k and WinNT clients try an OpenPrinterEx with
1136 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1137 or if the user is listed in the smb.conf printer admin parameter.
1139 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1140 client view printer folder, but does not show the MSAPW.
1142 Note: this test needs code to check access rights here too. Jeremy
1143 could you look at this?
1146 Second case: the user is opening a printer:
1147 NT doesn't let us connect to a printer if the connecting user
1148 doesn't have print permission.
1152 get_current_user(&user, p);
1154 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
1156 /* Printserver handles use global struct... */
1160 /* Map standard access rights to object specific access
1163 se_map_standard(&printer_default->access_required,
1164 &printserver_std_mapping);
1166 /* Deny any object specific bits that don't apply to print
1167 servers (i.e printer and job specific bits) */
1169 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1171 if (printer_default->access_required &
1172 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1173 DEBUG(3, ("access DENIED for non-printserver bits"));
1174 close_printer_handle(p, handle);
1175 return WERR_ACCESS_DENIED;
1178 /* Allow admin access */
1180 if (printer_default->access_required &
1181 SERVER_ACCESS_ADMINISTER) {
1183 if (!lp_ms_add_printer_wizard()) {
1184 close_printer_handle(p, handle);
1185 return WERR_ACCESS_DENIED;
1188 if (user.uid == 0 ||
1189 user_in_list(uidtoname(user.uid),
1190 lp_printer_admin(snum)))
1193 close_printer_handle(p, handle);
1194 return WERR_ACCESS_DENIED;
1197 /* We fall through to return WERR_OK */
1202 /* NT doesn't let us connect to a printer if the connecting user
1203 doesn't have print permission. */
1205 if (!get_printer_snum(p, handle, &snum))
1208 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1210 /* map an empty access mask to the minimum access mask */
1211 if (printer_default->access_required == 0x0)
1212 printer_default->access_required = PRINTER_ACCESS_USE;
1215 * If we are not serving the printer driver for this printer,
1216 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1217 * will keep NT clients happy --jerry
1220 if (lp_use_client_driver(snum)
1221 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1223 printer_default->access_required = PRINTER_ACCESS_USE;
1226 /* check smb.conf parameters and the the sec_desc */
1228 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1229 DEBUG(3, ("access DENIED for printer open\n"));
1230 close_printer_handle(p, handle);
1231 return WERR_ACCESS_DENIED;
1234 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1235 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1236 close_printer_handle(p, handle);
1237 return WERR_ACCESS_DENIED;
1240 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1241 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1243 printer_default->access_required = PRINTER_ACCESS_USE;
1245 DEBUG(4,("Setting printer access=%x\n", printer_default->access_required));
1246 Printer->access_granted = printer_default->access_required;
1249 * If we have a default device pointer in the
1250 * printer_default struct, then we need to get
1251 * the printer info from the tdb and if there is
1252 * no default devicemode there then we do a *SET*
1253 * here ! This is insanity.... JRA.
1257 * If the openprinterex rpc call contains a devmode,
1258 * it's a per-user one. This per-user devmode is derivated
1259 * from the global devmode. Openprinterex() contains a per-user
1260 * devmode for when you do EMF printing and spooling.
1261 * In the EMF case, the NT workstation is only doing half the job
1262 * of rendering the page. The other half is done by running the printer
1263 * driver on the server.
1264 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1265 * The EMF file only contains what is to be printed on the page.
1266 * So in order for the server to know how to print, the NT client sends
1267 * a devicemode attached to the openprinterex call.
1268 * But this devicemode is short lived, it's only valid for the current print job.
1270 * If Samba would have supported EMF spooling, this devicemode would
1271 * have been attached to the handle, to sent it to the driver to correctly
1272 * rasterize the EMF file.
1274 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1275 * we just act as a pass-thru between windows and the printer.
1277 * In order to know that Samba supports only RAW spooling, NT has to call
1278 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1279 * and until NT sends a RAW job, we refuse it.
1281 * But to call getprinter() or startdoc(), you first need a valid handle,
1282 * and to get an handle you have to call openprintex(). Hence why you have
1283 * a devicemode in the openprinterex() call.
1286 * Differences between NT4 and NT 2000.
1289 * On NT4, you only have a global devicemode. This global devicemode can be changed
1290 * by the administrator (or by a user with enough privs). Everytime a user
1291 * wants to print, the devicemode is resetted to the default. In Word, everytime
1292 * you print, the printer's characteristics are always reset to the global devicemode.
1296 * In W2K, there is the notion of per-user devicemode. The first time you use
1297 * a printer, a per-user devicemode is build from the global devicemode.
1298 * If you change your per-user devicemode, it is saved in the registry, under the
1299 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1300 * printer preferences available.
1302 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1303 * on the General Tab of the printer properties windows.
1305 * To change the global devicemode: it's the "Printing Defaults..." button
1306 * on the Advanced Tab of the printer properties window.
1314 if (printer_default->devmode_cont.devmode != NULL) {
1315 result = printer_write_default_dev( snum, printer_default);
1317 close_printer_handle(p, handle);
1327 /****************************************************************************
1328 ****************************************************************************/
1330 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1331 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1337 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1346 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1347 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1353 printer->info_3=NULL;
1354 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1358 printer->info_6=NULL;
1359 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1369 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1370 NT_DEVICEMODE **pp_nt_devmode)
1372 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1375 * Ensure nt_devmode is a valid pointer
1376 * as we will be overwriting it.
1379 if (nt_devmode == NULL) {
1380 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1381 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1385 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1386 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1388 nt_devmode->specversion=devmode->specversion;
1389 nt_devmode->driverversion=devmode->driverversion;
1390 nt_devmode->size=devmode->size;
1391 nt_devmode->fields=devmode->fields;
1392 nt_devmode->orientation=devmode->orientation;
1393 nt_devmode->papersize=devmode->papersize;
1394 nt_devmode->paperlength=devmode->paperlength;
1395 nt_devmode->paperwidth=devmode->paperwidth;
1396 nt_devmode->scale=devmode->scale;
1397 nt_devmode->copies=devmode->copies;
1398 nt_devmode->defaultsource=devmode->defaultsource;
1399 nt_devmode->printquality=devmode->printquality;
1400 nt_devmode->color=devmode->color;
1401 nt_devmode->duplex=devmode->duplex;
1402 nt_devmode->yresolution=devmode->yresolution;
1403 nt_devmode->ttoption=devmode->ttoption;
1404 nt_devmode->collate=devmode->collate;
1406 nt_devmode->logpixels=devmode->logpixels;
1407 nt_devmode->bitsperpel=devmode->bitsperpel;
1408 nt_devmode->pelswidth=devmode->pelswidth;
1409 nt_devmode->pelsheight=devmode->pelsheight;
1410 nt_devmode->displayflags=devmode->displayflags;
1411 nt_devmode->displayfrequency=devmode->displayfrequency;
1412 nt_devmode->icmmethod=devmode->icmmethod;
1413 nt_devmode->icmintent=devmode->icmintent;
1414 nt_devmode->mediatype=devmode->mediatype;
1415 nt_devmode->dithertype=devmode->dithertype;
1416 nt_devmode->reserved1=devmode->reserved1;
1417 nt_devmode->reserved2=devmode->reserved2;
1418 nt_devmode->panningwidth=devmode->panningwidth;
1419 nt_devmode->panningheight=devmode->panningheight;
1422 * Only change private and driverextra if the incoming devmode
1423 * has a new one. JRA.
1426 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1427 SAFE_FREE(nt_devmode->private);
1428 nt_devmode->driverextra=devmode->driverextra;
1429 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1431 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1434 *pp_nt_devmode = nt_devmode;
1439 /********************************************************************
1440 * _spoolss_enddocprinter_internal.
1441 ********************************************************************/
1443 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1445 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1448 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1452 Printer->document_started=False;
1453 print_job_end(Printer->jobid,True);
1454 /* error codes unhandled so far ... */
1459 /********************************************************************
1460 * api_spoolss_closeprinter
1461 ********************************************************************/
1463 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1465 POLICY_HND *handle = &q_u->handle;
1467 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1469 if (Printer && Printer->document_started)
1470 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1472 if (!close_printer_handle(p, handle))
1475 /* clear the returned printer handle. Observed behavior
1476 from Win2k server. Don't think this really matters.
1477 Previous code just copied the value of the closed
1480 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1485 /********************************************************************
1486 * api_spoolss_deleteprinter
1488 ********************************************************************/
1490 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1492 POLICY_HND *handle = &q_u->handle;
1493 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1496 if (Printer && Printer->document_started)
1497 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1499 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1501 result = delete_printer_handle(p, handle);
1503 update_c_setprinter(False);
1508 /*******************************************************************
1509 * static function to lookup the version id corresponding to an
1510 * long architecture string
1511 ******************************************************************/
1513 static int get_version_id (char * arch)
1516 struct table_node archi_table[]= {
1518 {"Windows 4.0", "WIN40", 0 },
1519 {"Windows NT x86", "W32X86", 2 },
1520 {"Windows NT R4000", "W32MIPS", 2 },
1521 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1522 {"Windows NT PowerPC", "W32PPC", 2 },
1526 for (i=0; archi_table[i].long_archi != NULL; i++)
1528 if (strcmp(arch, archi_table[i].long_archi) == 0)
1529 return (archi_table[i].version);
1535 /********************************************************************
1536 * _spoolss_deleteprinterdriver
1537 ********************************************************************/
1539 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1543 NT_PRINTER_DRIVER_INFO_LEVEL info;
1545 struct current_user user;
1547 get_current_user(&user, p);
1549 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1550 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1552 /* check that we have a valid driver name first */
1553 if ((version=get_version_id(arch)) == -1) {
1554 /* this is what NT returns */
1555 return WERR_INVALID_ENVIRONMENT;
1558 /* if they said "Windows NT x86", then try for version 2 & 3 */
1561 version = DRIVER_ANY_VERSION;
1565 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1566 return WERR_UNKNOWN_PRINTER_DRIVER;
1568 if (printer_driver_in_use(info.info_3))
1569 return WERR_PRINTER_DRIVER_IN_USE;
1571 return delete_printer_driver(info.info_3, &user, DRIVER_ANY_VERSION, False);
1574 /********************************************************************
1575 * spoolss_deleteprinterdriverex
1576 ********************************************************************/
1578 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1582 NT_PRINTER_DRIVER_INFO_LEVEL info;
1584 uint32 flags = q_u->delete_flags;
1586 struct current_user user;
1588 get_current_user(&user, p);
1590 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1591 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1593 /* check that we have a valid driver name first */
1594 if ((version=get_version_id(arch)) == -1) {
1595 /* this is what NT returns */
1596 return WERR_INVALID_ENVIRONMENT;
1599 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
1600 version = q_u->version;
1601 else if ( version == 2 )
1602 /* if they said "Windows NT x86", then try for version 2 & 3 */
1603 version = DRIVER_ANY_VERSION;
1607 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1608 return WERR_UNKNOWN_PRINTER_DRIVER;
1610 if ( printer_driver_in_use(info.info_3) )
1611 return WERR_PRINTER_DRIVER_IN_USE;
1614 * we have a couple of cases to consider.
1615 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1616 * then the delete should fail if **any** files overlap with
1618 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1619 * non-overlapping files
1620 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1621 * is set, the do not delete any files
1622 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1625 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1629 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1631 if ( printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) )
1632 /* no idea of the correct error here */
1633 return WERR_ACCESS_DENIED;
1636 return delete_printer_driver(info.info_3, &user, version, delete_files);
1640 /********************************************************************
1641 GetPrinterData on a printer server Handle.
1642 ********************************************************************/
1644 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1648 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1650 if (!strcmp(value, "W3SvcInstalled")) {
1652 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
1658 if (!strcmp(value, "BeepEnabled")) {
1660 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1662 SIVAL(*data, 0, 0x00);
1667 if (!strcmp(value, "EventLog")) {
1669 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1671 /* formally was 0x1b */
1672 SIVAL(*data, 0, 0x0);
1677 if (!strcmp(value, "NetPopup")) {
1679 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1681 SIVAL(*data, 0, 0x00);
1686 if (!strcmp(value, "MajorVersion")) {
1688 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1690 #ifndef EMULATE_WIN2K_HACK /* JERRY */
1699 if (!strcmp(value, "DefaultSpoolDirectory")) {
1702 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1704 *needed = 2*(strlen(string)+1);
1705 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1707 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1709 /* it's done by hand ready to go on the wire */
1710 for (i=0; i<strlen(string); i++) {
1711 (*data)[2*i]=string[i];
1712 (*data)[2*i+1]='\0';
1717 if (!strcmp(value, "Architecture")) {
1718 pstring string="Windows NT x86";
1720 *needed = 2*(strlen(string)+1);
1721 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1723 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1724 for (i=0; i<strlen(string); i++) {
1725 (*data)[2*i]=string[i];
1726 (*data)[2*i+1]='\0';
1734 /********************************************************************
1735 GetPrinterData on a printer Handle.
1736 ********************************************************************/
1738 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1739 fstring value, uint32 *type,
1740 uint8 **data, uint32 *needed, uint32 in_size )
1742 NT_PRINTER_INFO_LEVEL *printer = NULL;
1746 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1748 DEBUG(5,("getprinterdata_printer\n"));
1751 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1755 if(!get_printer_snum(p, handle, &snum))
1758 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1761 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1762 free_a_printer(&printer, 2);
1766 free_a_printer(&printer, 2);
1768 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1771 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1775 memset(*data, 0, in_size *sizeof(uint8));
1776 /* copy the min(in_size, len) */
1777 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1784 DEBUG(5,("getprinterdata_printer:copy done\n"));
1791 /********************************************************************
1792 * spoolss_getprinterdata
1793 ********************************************************************/
1795 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1797 POLICY_HND *handle = &q_u->handle;
1798 UNISTR2 *valuename = &q_u->valuename;
1799 uint32 in_size = q_u->size;
1800 uint32 *type = &r_u->type;
1801 uint32 *out_size = &r_u->size;
1802 uint8 **data = &r_u->data;
1803 uint32 *needed = &r_u->needed;
1807 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1810 * Reminder: when it's a string, the length is in BYTES
1811 * even if UNICODE is negociated.
1818 /* in case of problem, return some default values */
1822 DEBUG(4,("_spoolss_getprinterdata\n"));
1825 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1827 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1831 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1833 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1834 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1836 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1839 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1840 /* reply this param doesn't exist */
1842 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1848 /* error depends on handle type */
1850 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1851 return WERR_INVALID_PARAM;
1853 return WERR_BADFILE;
1856 if (*needed > *out_size)
1857 return WERR_MORE_DATA;
1862 /*********************************************************
1863 Connect to the client machine.
1864 **********************************************************/
1866 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, char *remote_machine)
1868 extern pstring global_myname;
1870 ZERO_STRUCTP(the_cli);
1871 if(cli_initialise(the_cli) == NULL) {
1872 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
1876 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
1877 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
1878 cli_shutdown(the_cli);
1882 if (ismyip(the_cli->dest_ip)) {
1883 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
1884 cli_shutdown(the_cli);
1888 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
1889 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1890 cli_shutdown(the_cli);
1894 if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
1895 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
1900 the_cli->protocol = PROTOCOL_NT1;
1902 if (!cli_negprot(the_cli)) {
1903 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1904 cli_shutdown(the_cli);
1908 if (the_cli->protocol != PROTOCOL_NT1) {
1909 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
1910 cli_shutdown(the_cli);
1915 * Do an anonymous session setup.
1918 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
1919 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1920 cli_shutdown(the_cli);
1924 if (!(the_cli->sec_mode & 1)) {
1925 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
1926 cli_shutdown(the_cli);
1930 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
1931 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1932 cli_shutdown(the_cli);
1937 * Ok - we have an anonymous connection to the IPC$ share.
1938 * Now start the NT Domain stuff :-).
1941 if(cli_nt_session_open(the_cli, PIPE_SPOOLSS) == False) {
1942 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)));
1943 cli_nt_session_close(the_cli);
1944 cli_ulogoff(the_cli);
1945 cli_shutdown(the_cli);
1952 /***************************************************************************
1953 Connect to the client.
1954 ****************************************************************************/
1956 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1961 * If it's the first connection, contact the client
1962 * and connect to the IPC$ share anonumously
1964 if (smb_connections==0) {
1965 fstring unix_printer;
1967 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1969 if(!spoolss_connect_to_client(&cli, unix_printer))
1972 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message);
1977 result = cli_spoolss_reply_open_printer(&cli, cli.mem_ctx, printer, localprinter,
1980 if (!W_ERROR_IS_OK(result))
1981 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
1982 dos_errstr(result)));
1984 return (W_ERROR_IS_OK(result));
1987 /********************************************************************
1989 * ReplyFindFirstPrinterChangeNotifyEx
1991 * before replying OK: status=0 a rpc call is made to the workstation
1992 * asking ReplyOpenPrinter
1994 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1995 * called from api_spoolss_rffpcnex
1996 ********************************************************************/
1998 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2000 POLICY_HND *handle = &q_u->handle;
2001 uint32 flags = q_u->flags;
2002 uint32 options = q_u->options;
2003 UNISTR2 *localmachine = &q_u->localmachine;
2004 uint32 printerlocal = q_u->printerlocal;
2005 SPOOL_NOTIFY_OPTION *option = q_u->option;
2007 /* store the notify value in the printer struct */
2009 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2012 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2016 Printer->notify.flags=flags;
2017 Printer->notify.options=options;
2018 Printer->notify.printerlocal=printerlocal;
2020 if (Printer->notify.option)
2021 free_spool_notify_option(&Printer->notify.option);
2023 Printer->notify.option=dup_spool_notify_option(option);
2025 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2026 sizeof(Printer->notify.localmachine)-1);
2028 /* Connect to the client machine and send a ReplyOpenPrinter */
2030 if(!srv_spoolss_replyopenprinter(Printer->notify.localmachine,
2031 Printer->notify.printerlocal, 1,
2032 &Printer->notify.client_hnd))
2033 return WERR_SERVER_UNAVAILABLE;
2035 Printer->notify.client_connected=True;
2040 /*******************************************************************
2041 * fill a notify_info_data with the servername
2042 ********************************************************************/
2044 void spoolss_notify_server_name(int snum,
2045 SPOOL_NOTIFY_INFO_DATA *data,
2046 print_queue_struct *queue,
2047 NT_PRINTER_INFO_LEVEL *printer,
2048 TALLOC_CTX *mem_ctx)
2050 pstring temp_name, temp;
2053 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2055 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2057 data->notify_data.data.length = len;
2058 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2060 if (!data->notify_data.data.string) {
2061 data->notify_data.data.length = 0;
2065 memcpy(data->notify_data.data.string, temp, len);
2068 /*******************************************************************
2069 * fill a notify_info_data with the printername (not including the servername).
2070 ********************************************************************/
2072 void spoolss_notify_printer_name(int snum,
2073 SPOOL_NOTIFY_INFO_DATA *data,
2074 print_queue_struct *queue,
2075 NT_PRINTER_INFO_LEVEL *printer,
2076 TALLOC_CTX *mem_ctx)
2081 /* the notify name should not contain the \\server\ part */
2082 char *p = strrchr(printer->info_2->printername, '\\');
2085 p = printer->info_2->printername;
2090 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2092 data->notify_data.data.length = len;
2093 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2095 if (!data->notify_data.data.string) {
2096 data->notify_data.data.length = 0;
2100 memcpy(data->notify_data.data.string, temp, len);
2103 /*******************************************************************
2104 * fill a notify_info_data with the servicename
2105 ********************************************************************/
2107 void spoolss_notify_share_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)
2116 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2118 data->notify_data.data.length = len;
2119 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2121 if (!data->notify_data.data.string) {
2122 data->notify_data.data.length = 0;
2126 memcpy(data->notify_data.data.string, temp, len);
2129 /*******************************************************************
2130 * fill a notify_info_data with the port name
2131 ********************************************************************/
2133 void spoolss_notify_port_name(int snum,
2134 SPOOL_NOTIFY_INFO_DATA *data,
2135 print_queue_struct *queue,
2136 NT_PRINTER_INFO_LEVEL *printer,
2137 TALLOC_CTX *mem_ctx)
2142 /* even if it's strange, that's consistant in all the code */
2144 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2146 data->notify_data.data.length = len;
2147 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2149 if (!data->notify_data.data.string) {
2150 data->notify_data.data.length = 0;
2154 memcpy(data->notify_data.data.string, temp, len);
2157 /*******************************************************************
2158 * fill a notify_info_data with the printername
2159 * but it doesn't exist, have to see what to do
2160 ********************************************************************/
2162 void spoolss_notify_driver_name(int snum,
2163 SPOOL_NOTIFY_INFO_DATA *data,
2164 print_queue_struct *queue,
2165 NT_PRINTER_INFO_LEVEL *printer,
2166 TALLOC_CTX *mem_ctx)
2171 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2173 data->notify_data.data.length = len;
2174 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2176 if (!data->notify_data.data.string) {
2177 data->notify_data.data.length = 0;
2181 memcpy(data->notify_data.data.string, temp, len);
2184 /*******************************************************************
2185 * fill a notify_info_data with the comment
2186 ********************************************************************/
2188 void spoolss_notify_comment(int snum,
2189 SPOOL_NOTIFY_INFO_DATA *data,
2190 print_queue_struct *queue,
2191 NT_PRINTER_INFO_LEVEL *printer,
2192 TALLOC_CTX *mem_ctx)
2197 if (*printer->info_2->comment == '\0')
2198 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2200 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2202 data->notify_data.data.length = len;
2203 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2205 if (!data->notify_data.data.string) {
2206 data->notify_data.data.length = 0;
2210 memcpy(data->notify_data.data.string, temp, len);
2213 /*******************************************************************
2214 * fill a notify_info_data with the comment
2215 * location = "Room 1, floor 2, building 3"
2216 ********************************************************************/
2218 void spoolss_notify_location(int snum,
2219 SPOOL_NOTIFY_INFO_DATA *data,
2220 print_queue_struct *queue,
2221 NT_PRINTER_INFO_LEVEL *printer,
2222 TALLOC_CTX *mem_ctx)
2227 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2229 data->notify_data.data.length = len;
2230 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2232 if (!data->notify_data.data.string) {
2233 data->notify_data.data.length = 0;
2237 memcpy(data->notify_data.data.string, temp, len);
2240 /*******************************************************************
2241 * fill a notify_info_data with the device mode
2242 * jfm:xxxx don't to it for know but that's a real problem !!!
2243 ********************************************************************/
2245 static void spoolss_notify_devmode(int snum,
2246 SPOOL_NOTIFY_INFO_DATA *data,
2247 print_queue_struct *queue,
2248 NT_PRINTER_INFO_LEVEL *printer,
2249 TALLOC_CTX *mem_ctx)
2253 /*******************************************************************
2254 * fill a notify_info_data with the separator file name
2255 ********************************************************************/
2257 void spoolss_notify_sepfile(int snum,
2258 SPOOL_NOTIFY_INFO_DATA *data,
2259 print_queue_struct *queue,
2260 NT_PRINTER_INFO_LEVEL *printer,
2261 TALLOC_CTX *mem_ctx)
2266 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2268 data->notify_data.data.length = len;
2269 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2271 if (!data->notify_data.data.string) {
2272 data->notify_data.data.length = 0;
2276 memcpy(data->notify_data.data.string, temp, len);
2279 /*******************************************************************
2280 * fill a notify_info_data with the print processor
2281 * jfm:xxxx return always winprint to indicate we don't do anything to it
2282 ********************************************************************/
2284 void spoolss_notify_print_processor(int snum,
2285 SPOOL_NOTIFY_INFO_DATA *data,
2286 print_queue_struct *queue,
2287 NT_PRINTER_INFO_LEVEL *printer,
2288 TALLOC_CTX *mem_ctx)
2293 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2295 data->notify_data.data.length = len;
2296 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2298 if (!data->notify_data.data.string) {
2299 data->notify_data.data.length = 0;
2303 memcpy(data->notify_data.data.string, temp, len);
2306 /*******************************************************************
2307 * fill a notify_info_data with the print processor options
2308 * jfm:xxxx send an empty string
2309 ********************************************************************/
2311 void spoolss_notify_parameters(int snum,
2312 SPOOL_NOTIFY_INFO_DATA *data,
2313 print_queue_struct *queue,
2314 NT_PRINTER_INFO_LEVEL *printer,
2315 TALLOC_CTX *mem_ctx)
2320 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2322 data->notify_data.data.length = len;
2323 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2325 if (!data->notify_data.data.string) {
2326 data->notify_data.data.length = 0;
2330 memcpy(data->notify_data.data.string, temp, len);
2333 /*******************************************************************
2334 * fill a notify_info_data with the data type
2335 * jfm:xxxx always send RAW as data type
2336 ********************************************************************/
2338 void spoolss_notify_datatype(int snum,
2339 SPOOL_NOTIFY_INFO_DATA *data,
2340 print_queue_struct *queue,
2341 NT_PRINTER_INFO_LEVEL *printer,
2342 TALLOC_CTX *mem_ctx)
2347 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2349 data->notify_data.data.length = len;
2350 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2352 if (!data->notify_data.data.string) {
2353 data->notify_data.data.length = 0;
2357 memcpy(data->notify_data.data.string, temp, len);
2360 /*******************************************************************
2361 * fill a notify_info_data with the security descriptor
2362 * jfm:xxxx send an null pointer to say no security desc
2363 * have to implement security before !
2364 ********************************************************************/
2366 static void spoolss_notify_security_desc(int snum,
2367 SPOOL_NOTIFY_INFO_DATA *data,
2368 print_queue_struct *queue,
2369 NT_PRINTER_INFO_LEVEL *printer,
2370 TALLOC_CTX *mem_ctx)
2372 data->notify_data.data.length=0;
2373 data->notify_data.data.string = NULL;
2376 /*******************************************************************
2377 * fill a notify_info_data with the attributes
2378 * jfm:xxxx a samba printer is always shared
2379 ********************************************************************/
2381 void spoolss_notify_attributes(int snum,
2382 SPOOL_NOTIFY_INFO_DATA *data,
2383 print_queue_struct *queue,
2384 NT_PRINTER_INFO_LEVEL *printer,
2385 TALLOC_CTX *mem_ctx)
2387 data->notify_data.value[0] = printer->info_2->attributes;
2388 data->notify_data.value[1] = 0;
2391 /*******************************************************************
2392 * fill a notify_info_data with the priority
2393 ********************************************************************/
2395 static void spoolss_notify_priority(int snum,
2396 SPOOL_NOTIFY_INFO_DATA *data,
2397 print_queue_struct *queue,
2398 NT_PRINTER_INFO_LEVEL *printer,
2399 TALLOC_CTX *mem_ctx)
2401 data->notify_data.value[0] = printer->info_2->priority;
2402 data->notify_data.value[1] = 0;
2405 /*******************************************************************
2406 * fill a notify_info_data with the default priority
2407 ********************************************************************/
2409 static void spoolss_notify_default_priority(int snum,
2410 SPOOL_NOTIFY_INFO_DATA *data,
2411 print_queue_struct *queue,
2412 NT_PRINTER_INFO_LEVEL *printer,
2413 TALLOC_CTX *mem_ctx)
2415 data->notify_data.value[0] = printer->info_2->default_priority;
2416 data->notify_data.value[1] = 0;
2419 /*******************************************************************
2420 * fill a notify_info_data with the start time
2421 ********************************************************************/
2423 static void spoolss_notify_start_time(int snum,
2424 SPOOL_NOTIFY_INFO_DATA *data,
2425 print_queue_struct *queue,
2426 NT_PRINTER_INFO_LEVEL *printer,
2427 TALLOC_CTX *mem_ctx)
2429 data->notify_data.value[0] = printer->info_2->starttime;
2430 data->notify_data.value[1] = 0;
2433 /*******************************************************************
2434 * fill a notify_info_data with the until time
2435 ********************************************************************/
2437 static void spoolss_notify_until_time(int snum,
2438 SPOOL_NOTIFY_INFO_DATA *data,
2439 print_queue_struct *queue,
2440 NT_PRINTER_INFO_LEVEL *printer,
2441 TALLOC_CTX *mem_ctx)
2443 data->notify_data.value[0] = printer->info_2->untiltime;
2444 data->notify_data.value[1] = 0;
2447 /*******************************************************************
2448 * fill a notify_info_data with the status
2449 ********************************************************************/
2451 static void spoolss_notify_status(int snum,
2452 SPOOL_NOTIFY_INFO_DATA *data,
2453 print_queue_struct *queue,
2454 NT_PRINTER_INFO_LEVEL *printer,
2455 TALLOC_CTX *mem_ctx)
2457 print_status_struct status;
2459 print_queue_length(snum, &status);
2460 data->notify_data.value[0]=(uint32) status.status;
2461 data->notify_data.value[1] = 0;
2464 /*******************************************************************
2465 * fill a notify_info_data with the number of jobs queued
2466 ********************************************************************/
2468 void spoolss_notify_cjobs(int snum,
2469 SPOOL_NOTIFY_INFO_DATA *data,
2470 print_queue_struct *queue,
2471 NT_PRINTER_INFO_LEVEL *printer,
2472 TALLOC_CTX *mem_ctx)
2474 data->notify_data.value[0] = print_queue_length(snum, NULL);
2475 data->notify_data.value[1] = 0;
2478 /*******************************************************************
2479 * fill a notify_info_data with the average ppm
2480 ********************************************************************/
2482 static void spoolss_notify_average_ppm(int snum,
2483 SPOOL_NOTIFY_INFO_DATA *data,
2484 print_queue_struct *queue,
2485 NT_PRINTER_INFO_LEVEL *printer,
2486 TALLOC_CTX *mem_ctx)
2488 /* always respond 8 pages per minutes */
2489 /* a little hard ! */
2490 data->notify_data.value[0] = printer->info_2->averageppm;
2491 data->notify_data.value[1] = 0;
2494 /*******************************************************************
2495 * fill a notify_info_data with username
2496 ********************************************************************/
2498 static void spoolss_notify_username(int snum,
2499 SPOOL_NOTIFY_INFO_DATA *data,
2500 print_queue_struct *queue,
2501 NT_PRINTER_INFO_LEVEL *printer,
2502 TALLOC_CTX *mem_ctx)
2507 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2509 data->notify_data.data.length = len;
2510 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2512 if (!data->notify_data.data.string) {
2513 data->notify_data.data.length = 0;
2517 memcpy(data->notify_data.data.string, temp, len);
2520 /*******************************************************************
2521 * fill a notify_info_data with job status
2522 ********************************************************************/
2524 static void spoolss_notify_job_status(int snum,
2525 SPOOL_NOTIFY_INFO_DATA *data,
2526 print_queue_struct *queue,
2527 NT_PRINTER_INFO_LEVEL *printer,
2528 TALLOC_CTX *mem_ctx)
2530 data->notify_data.value[0]=nt_printj_status(queue->status);
2531 data->notify_data.value[1] = 0;
2534 /*******************************************************************
2535 * fill a notify_info_data with job name
2536 ********************************************************************/
2538 static void spoolss_notify_job_name(int snum,
2539 SPOOL_NOTIFY_INFO_DATA *data,
2540 print_queue_struct *queue,
2541 NT_PRINTER_INFO_LEVEL *printer,
2542 TALLOC_CTX *mem_ctx)
2547 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
2549 data->notify_data.data.length = len;
2550 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2552 if (!data->notify_data.data.string) {
2553 data->notify_data.data.length = 0;
2557 memcpy(data->notify_data.data.string, temp, len);
2560 /*******************************************************************
2561 * fill a notify_info_data with job status
2562 ********************************************************************/
2564 static void spoolss_notify_job_status_string(int snum,
2565 SPOOL_NOTIFY_INFO_DATA *data,
2566 print_queue_struct *queue,
2567 NT_PRINTER_INFO_LEVEL *printer,
2568 TALLOC_CTX *mem_ctx)
2571 * Now we're returning job status codes we just return a "" here. JRA.
2578 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2581 switch (queue->status) {
2586 p = ""; /* NT provides the paused string */
2595 #endif /* NO LONGER NEEDED. */
2597 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
2599 data->notify_data.data.length = len;
2600 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2602 if (!data->notify_data.data.string) {
2603 data->notify_data.data.length = 0;
2607 memcpy(data->notify_data.data.string, temp, len);
2610 /*******************************************************************
2611 * fill a notify_info_data with job time
2612 ********************************************************************/
2614 static void spoolss_notify_job_time(int snum,
2615 SPOOL_NOTIFY_INFO_DATA *data,
2616 print_queue_struct *queue,
2617 NT_PRINTER_INFO_LEVEL *printer,
2618 TALLOC_CTX *mem_ctx)
2620 data->notify_data.value[0]=0x0;
2621 data->notify_data.value[1]=0;
2624 /*******************************************************************
2625 * fill a notify_info_data with job size
2626 ********************************************************************/
2628 static void spoolss_notify_job_size(int snum,
2629 SPOOL_NOTIFY_INFO_DATA *data,
2630 print_queue_struct *queue,
2631 NT_PRINTER_INFO_LEVEL *printer,
2632 TALLOC_CTX *mem_ctx)
2634 data->notify_data.value[0]=queue->size;
2635 data->notify_data.value[1]=0;
2638 /*******************************************************************
2639 * fill a notify_info_data with page info
2640 ********************************************************************/
2641 static void spoolss_notify_total_pages(int snum,
2642 SPOOL_NOTIFY_INFO_DATA *data,
2643 print_queue_struct *queue,
2644 NT_PRINTER_INFO_LEVEL *printer,
2645 TALLOC_CTX *mem_ctx)
2647 data->notify_data.value[0]=queue->page_count;
2648 data->notify_data.value[1]=0;
2651 /*******************************************************************
2652 * fill a notify_info_data with pages printed info.
2653 ********************************************************************/
2654 static void spoolss_notify_pages_printed(int snum,
2655 SPOOL_NOTIFY_INFO_DATA *data,
2656 print_queue_struct *queue,
2657 NT_PRINTER_INFO_LEVEL *printer,
2658 TALLOC_CTX *mem_ctx)
2660 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
2661 data->notify_data.value[1]=0;
2664 /*******************************************************************
2665 Fill a notify_info_data with job position.
2666 ********************************************************************/
2668 static void spoolss_notify_job_position(int snum,
2669 SPOOL_NOTIFY_INFO_DATA *data,
2670 print_queue_struct *queue,
2671 NT_PRINTER_INFO_LEVEL *printer,
2672 TALLOC_CTX *mem_ctx)
2674 data->notify_data.value[0]=queue->job;
2675 data->notify_data.value[1]=0;
2678 /*******************************************************************
2679 Fill a notify_info_data with submitted time.
2680 ********************************************************************/
2682 static void spoolss_notify_submitted_time(int snum,
2683 SPOOL_NOTIFY_INFO_DATA *data,
2684 print_queue_struct *queue,
2685 NT_PRINTER_INFO_LEVEL *printer,
2686 TALLOC_CTX *mem_ctx)
2693 t=gmtime(&queue->time);
2695 len = sizeof(SYSTEMTIME);
2697 data->notify_data.data.length = len;
2698 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2700 if (!data->notify_data.data.string) {
2701 data->notify_data.data.length = 0;
2705 make_systemtime(&st, t);
2708 * Systemtime must be linearized as a set of UINT16's.
2709 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2712 p = (char *)data->notify_data.data.string;
2713 SSVAL(p, 0, st.year);
2714 SSVAL(p, 2, st.month);
2715 SSVAL(p, 4, st.dayofweek);
2716 SSVAL(p, 6, st.day);
2717 SSVAL(p, 8, st.hour);
2718 SSVAL(p, 10, st.minute);
2719 SSVAL(p, 12, st.second);
2720 SSVAL(p, 14, st.milliseconds);
2723 struct s_notify_info_data_table
2729 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2730 print_queue_struct *queue,
2731 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2734 /* A table describing the various print notification constants and
2735 whether the notification data is a pointer to a variable sized
2736 buffer, a one value uint32 or a two value uint32. */
2738 struct s_notify_info_data_table notify_info_data_table[] =
2740 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
2741 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
2742 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
2743 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
2744 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
2745 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
2746 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
2747 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
2748 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
2749 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
2750 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
2751 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
2752 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, spoolss_notify_security_desc },
2753 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
2754 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
2755 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
2756 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
2757 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
2758 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
2759 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
2760 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
2761 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
2762 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
2763 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
2764 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
2765 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
2766 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
2767 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
2768 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
2769 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
2770 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
2771 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
2772 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
2773 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
2774 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
2775 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
2776 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
2777 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
2778 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
2779 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
2780 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
2781 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
2782 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
2783 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
2784 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
2785 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
2786 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
2787 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
2788 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
2791 /*******************************************************************
2792 Return the size of info_data structure.
2793 ********************************************************************/
2795 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2799 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2800 if (notify_info_data_table[i].type == type &&
2801 notify_info_data_table[i].field == field) {
2802 switch(notify_info_data_table[i].size) {
2803 case NOTIFY_ONE_VALUE:
2804 case NOTIFY_TWO_VALUE:
2809 /* The only pointer notify data I have seen on
2810 the wire is the submitted time and this has
2811 the notify size set to 4. -tpot */
2813 case NOTIFY_POINTER:
2819 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
2824 /*******************************************************************
2825 Return the type of notify_info_data.
2826 ********************************************************************/
2828 static int type_of_notify_info_data(uint16 type, uint16 field)
2832 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2833 if (notify_info_data_table[i].type == type &&
2834 notify_info_data_table[i].field == field)
2835 return notify_info_data_table[i].size;
2841 /****************************************************************************
2842 ****************************************************************************/
2844 static int search_notify(uint16 type, uint16 field, int *value)
2848 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2849 if (notify_info_data_table[i].type == type &&
2850 notify_info_data_table[i].field == field &&
2851 notify_info_data_table[i].fn != NULL) {
2860 /****************************************************************************
2861 ****************************************************************************/
2863 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2865 info_data->type = type;
2866 info_data->field = field;
2867 info_data->reserved = 0;
2869 if (type == JOB_NOTIFY_TYPE)
2874 info_data->size = size_of_notify_info_data(type, field);
2875 info_data->enc_type = type_of_notify_info_data(type, field);
2879 /*******************************************************************
2881 * fill a notify_info struct with info asked
2883 ********************************************************************/
2885 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2886 snum, SPOOL_NOTIFY_OPTION_TYPE
2887 *option_type, uint32 id,
2888 TALLOC_CTX *mem_ctx)
2894 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2895 NT_PRINTER_INFO_LEVEL *printer = NULL;
2896 print_queue_struct *queue=NULL;
2898 type=option_type->type;
2900 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2901 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2902 option_type->count, lp_servicename(snum)));
2904 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2907 for(field_num=0; field_num<option_type->count; field_num++) {
2908 field = option_type->fields[field_num];
2909 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2911 if (!search_notify(type, field, &j) )
2914 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2915 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2918 else info->data = tid;
2920 current_data=&info->data[info->count];
2922 construct_info_data(current_data, type, field, id);
2924 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2925 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2927 notify_info_data_table[j].fn(snum, current_data, queue,
2933 free_a_printer(&printer, 2);
2937 /*******************************************************************
2939 * fill a notify_info struct with info asked
2941 ********************************************************************/
2943 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2944 SPOOL_NOTIFY_INFO *info,
2945 NT_PRINTER_INFO_LEVEL *printer,
2946 int snum, SPOOL_NOTIFY_OPTION_TYPE
2947 *option_type, uint32 id,
2948 TALLOC_CTX *mem_ctx)
2954 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2956 DEBUG(4,("construct_notify_jobs_info\n"));
2958 type = option_type->type;
2960 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2961 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2962 option_type->count));
2964 for(field_num=0; field_num<option_type->count; field_num++) {
2965 field = option_type->fields[field_num];
2967 if (!search_notify(type, field, &j) )
2970 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2971 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2974 else info->data = tid;
2976 current_data=&(info->data[info->count]);
2978 construct_info_data(current_data, type, field, id);
2979 notify_info_data_table[j].fn(snum, current_data, queue,
2988 * JFM: The enumeration is not that simple, it's even non obvious.
2990 * let's take an example: I want to monitor the PRINTER SERVER for
2991 * the printer's name and the number of jobs currently queued.
2992 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2993 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2995 * I have 3 printers on the back of my server.
2997 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3000 * 1 printer 1 name 1
3001 * 2 printer 1 cjob 1
3002 * 3 printer 2 name 2
3003 * 4 printer 2 cjob 2
3004 * 5 printer 3 name 3
3005 * 6 printer 3 name 3
3007 * that's the print server case, the printer case is even worse.
3010 /*******************************************************************
3012 * enumerate all printers on the printserver
3013 * fill a notify_info struct with info asked
3015 ********************************************************************/
3017 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3018 SPOOL_NOTIFY_INFO *info,
3019 TALLOC_CTX *mem_ctx)
3022 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3023 int n_services=lp_numservices();
3026 SPOOL_NOTIFY_OPTION *option;
3027 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3029 DEBUG(4,("printserver_notify_info\n"));
3034 option=Printer->notify.option;
3040 for (i=0; i<option->count; i++) {
3041 option_type=&(option->ctr.type[i]);
3043 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3046 for (snum=0; snum<n_services; snum++)
3047 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3048 if (construct_notify_printer_info
3049 (info, snum, option_type, id, mem_ctx))
3054 * Debugging information, don't delete.
3057 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3058 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3059 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3061 for (i=0; i<info->count; i++) {
3062 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3063 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3064 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3071 /*******************************************************************
3073 * fill a notify_info struct with info asked
3075 ********************************************************************/
3077 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3078 TALLOC_CTX *mem_ctx)
3081 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3084 SPOOL_NOTIFY_OPTION *option;
3085 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3087 print_queue_struct *queue=NULL;
3088 print_status_struct status;
3090 DEBUG(4,("printer_notify_info\n"));
3095 option=Printer->notify.option;
3101 get_printer_snum(p, hnd, &snum);
3103 for (i=0; i<option->count; i++) {
3104 option_type=&option->ctr.type[i];
3106 switch ( option_type->type ) {
3107 case PRINTER_NOTIFY_TYPE:
3108 if(construct_notify_printer_info(info, snum,
3114 case JOB_NOTIFY_TYPE: {
3115 NT_PRINTER_INFO_LEVEL *printer = NULL;
3117 count = print_queue_status(snum, &queue, &status);
3119 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3120 lp_servicename(snum))))
3123 for (j=0; j<count; j++) {
3124 construct_notify_jobs_info(&queue[j], info,
3131 free_a_printer(&printer, 2);
3141 * Debugging information, don't delete.
3144 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3145 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3146 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3148 for (i=0; i<info->count; i++) {
3149 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3150 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3151 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3157 /********************************************************************
3159 ********************************************************************/
3161 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3163 POLICY_HND *handle = &q_u->handle;
3164 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
3165 SPOOL_NOTIFY_INFO *info = &r_u->info;
3167 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3168 WERROR result = WERR_BADFID;
3170 /* we always have a NOTIFY_INFO struct */
3174 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3175 OUR_HANDLE(handle)));
3179 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3182 * We are now using the change value, and
3183 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3184 * I don't have a global notification system, I'm sending back all the
3185 * informations even when _NOTHING_ has changed.
3188 /* We need to keep track of the change value to send back in
3189 RRPCN replies otherwise our updates are ignored. */
3191 if (Printer->notify.client_connected)
3192 Printer->notify.change = q_u->change;
3194 /* just ignore the SPOOL_NOTIFY_OPTION */
3196 switch (Printer->printer_type) {
3197 case PRINTER_HANDLE_IS_PRINTSERVER:
3198 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3201 case PRINTER_HANDLE_IS_PRINTER:
3202 result = printer_notify_info(p, handle, info, p->mem_ctx);
3210 /********************************************************************
3211 * construct_printer_info_0
3212 * fill a printer_info_0 struct
3213 ********************************************************************/
3215 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3219 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3220 counter_printer_0 *session_counter;
3221 uint32 global_counter;
3224 print_status_struct status;
3226 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3229 count = print_queue_length(snum, &status);
3231 /* check if we already have a counter for this printer */
3232 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3234 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3235 if (session_counter->snum == snum)
3239 /* it's the first time, add it to the list */
3240 if (session_counter==NULL) {
3241 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3242 free_a_printer(&ntprinter, 2);
3245 ZERO_STRUCTP(session_counter);
3246 session_counter->snum=snum;
3247 session_counter->counter=0;
3248 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3252 session_counter->counter++;
3255 * the global_counter should be stored in a TDB as it's common to all the clients
3256 * and should be zeroed on samba startup
3258 global_counter=session_counter->counter;
3260 pstrcpy(chaine,ntprinter->info_2->printername);
3262 init_unistr(&printer->printername, chaine);
3264 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3265 init_unistr(&printer->servername, chaine);
3267 printer->cjobs = count;
3268 printer->total_jobs = 0;
3269 printer->total_bytes = 0;
3271 setuptime = (time_t)ntprinter->info_2->setuptime;
3272 t=gmtime(&setuptime);
3274 printer->year = t->tm_year+1900;
3275 printer->month = t->tm_mon+1;
3276 printer->dayofweek = t->tm_wday;
3277 printer->day = t->tm_mday;
3278 printer->hour = t->tm_hour;
3279 printer->minute = t->tm_min;
3280 printer->second = t->tm_sec;
3281 printer->milliseconds = 0;
3283 printer->global_counter = global_counter;
3284 printer->total_pages = 0;
3285 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3286 printer->major_version = 0x0004; /* NT 4 */
3287 printer->build_version = 0x0565; /* build 1381 */
3289 printer->major_version = 0x0005; /* NT 5 */
3290 printer->build_version = 0x0893; /* build 2195 */
3292 printer->unknown7 = 0x1;
3293 printer->unknown8 = 0x0;
3294 printer->unknown9 = 0x0;
3295 printer->session_counter = session_counter->counter;
3296 printer->unknown11 = 0x0;
3297 printer->printer_errors = 0x0; /* number of print failure */
3298 printer->unknown13 = 0x0;
3299 printer->unknown14 = 0x1;
3300 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3301 printer->unknown16 = 0x0;
3302 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3303 printer->unknown18 = 0x0;
3304 printer->status = nt_printq_status(status.status);
3305 printer->unknown20 = 0x0;
3306 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3307 printer->unknown22 = 0x0;
3308 printer->unknown23 = 0x6; /* 6 ???*/
3309 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3310 printer->unknown25 = 0;
3311 printer->unknown26 = 0;
3312 printer->unknown27 = 0;
3313 printer->unknown28 = 0;
3314 printer->unknown29 = 0;
3316 free_a_printer(&ntprinter,2);
3320 /********************************************************************
3321 * construct_printer_info_1
3322 * fill a printer_info_1 struct
3323 ********************************************************************/
3324 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3328 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3330 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3333 printer->flags=flags;
3335 if (*ntprinter->info_2->comment == '\0') {
3336 init_unistr(&printer->comment, lp_comment(snum));
3337 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3338 ntprinter->info_2->drivername, lp_comment(snum));
3341 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3342 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3343 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3346 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3348 init_unistr(&printer->description, chaine);
3349 init_unistr(&printer->name, chaine2);
3351 free_a_printer(&ntprinter,2);
3356 /****************************************************************************
3357 Free a DEVMODE struct.
3358 ****************************************************************************/
3360 static void free_dev_mode(DEVICEMODE *dev)
3365 SAFE_FREE(dev->private);
3369 /****************************************************************************
3370 Create a DEVMODE struct. Returns malloced memory.
3371 ****************************************************************************/
3373 static DEVICEMODE *construct_dev_mode(int snum)
3377 NT_PRINTER_INFO_LEVEL *printer = NULL;
3378 NT_DEVICEMODE *ntdevmode = NULL;
3379 DEVICEMODE *devmode = NULL;
3381 DEBUG(7,("construct_dev_mode\n"));
3383 DEBUGADD(8,("getting printer characteristics\n"));
3385 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3386 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3390 ZERO_STRUCTP(devmode);
3392 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3395 if (printer->info_2->devmode)
3396 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
3398 if (ntdevmode == NULL) {
3399 DEBUG(5, ("BONG! There was no device mode!\n"));
3403 DEBUGADD(8,("loading DEVICEMODE\n"));
3405 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
3406 init_unistr(&devmode->devicename, adevice);
3408 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
3409 init_unistr(&devmode->formname, aform);
3411 devmode->specversion = ntdevmode->specversion;
3412 devmode->driverversion = ntdevmode->driverversion;
3413 devmode->size = ntdevmode->size;
3414 devmode->driverextra = ntdevmode->driverextra;
3415 devmode->fields = ntdevmode->fields;
3417 devmode->orientation = ntdevmode->orientation;
3418 devmode->papersize = ntdevmode->papersize;
3419 devmode->paperlength = ntdevmode->paperlength;
3420 devmode->paperwidth = ntdevmode->paperwidth;
3421 devmode->scale = ntdevmode->scale;
3422 devmode->copies = ntdevmode->copies;
3423 devmode->defaultsource = ntdevmode->defaultsource;
3424 devmode->printquality = ntdevmode->printquality;
3425 devmode->color = ntdevmode->color;
3426 devmode->duplex = ntdevmode->duplex;
3427 devmode->yresolution = ntdevmode->yresolution;
3428 devmode->ttoption = ntdevmode->ttoption;
3429 devmode->collate = ntdevmode->collate;
3430 devmode->icmmethod = ntdevmode->icmmethod;
3431 devmode->icmintent = ntdevmode->icmintent;
3432 devmode->mediatype = ntdevmode->mediatype;
3433 devmode->dithertype = ntdevmode->dithertype;
3435 if (ntdevmode->private != NULL) {
3436 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3440 free_nt_devicemode(&ntdevmode);
3441 free_a_printer(&printer,2);
3448 free_nt_devicemode(&ntdevmode);
3450 free_a_printer(&printer,2);
3451 free_dev_mode(devmode);
3456 /********************************************************************
3457 * construct_printer_info_2
3458 * fill a printer_info_2 struct
3459 ********************************************************************/
3461 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3464 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3466 print_status_struct status;
3468 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3471 count = print_queue_length(snum, &status);
3473 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3474 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3475 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3476 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3477 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3479 if (*ntprinter->info_2->comment == '\0')
3480 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3482 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3484 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3485 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3486 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3487 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3488 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3490 printer->attributes = ntprinter->info_2->attributes;
3492 printer->priority = ntprinter->info_2->priority; /* priority */
3493 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3494 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3495 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3496 printer->status = nt_printq_status(status.status); /* status */
3497 printer->cjobs = count; /* jobs */
3498 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3500 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3501 DEBUG(8, ("Returning NULL Devicemode!\n"));
3504 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3505 /* steal the printer info sec_desc structure. [badly done]. */
3506 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3507 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3508 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3509 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3512 printer->secdesc = NULL;
3515 free_a_printer(&ntprinter, 2);
3519 /********************************************************************
3520 * construct_printer_info_3
3521 * fill a printer_info_3 struct
3522 ********************************************************************/
3524 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3526 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3527 PRINTER_INFO_3 *printer = NULL;
3529 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3533 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3534 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3538 ZERO_STRUCTP(printer);
3540 printer->flags = 4; /* These are the components of the SD we are returning. */
3541 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3542 /* steal the printer info sec_desc structure. [badly done]. */
3543 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3547 * Set the flags for the components we are returning.
3550 if (printer->secdesc->owner_sid)
3551 printer->flags |= OWNER_SECURITY_INFORMATION;
3553 if (printer->secdesc->grp_sid)
3554 printer->flags |= GROUP_SECURITY_INFORMATION;
3556 if (printer->secdesc->dacl)
3557 printer->flags |= DACL_SECURITY_INFORMATION;
3559 if (printer->secdesc->sacl)
3560 printer->flags |= SACL_SECURITY_INFORMATION;
3563 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
3564 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
3565 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
3568 free_a_printer(&ntprinter, 2);
3570 *pp_printer = printer;
3574 /********************************************************************
3575 * construct_printer_info_4
3576 * fill a printer_info_4 struct
3577 ********************************************************************/
3579 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
3581 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3583 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3586 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3587 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3588 printer->attributes = ntprinter->info_2->attributes;
3590 free_a_printer(&ntprinter, 2);
3594 /********************************************************************
3595 * construct_printer_info_5
3596 * fill a printer_info_5 struct
3597 ********************************************************************/
3599 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
3601 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3603 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3606 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3607 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
3608 printer->attributes = ntprinter->info_2->attributes;
3609 printer->device_not_selected_timeout = 0x3a98;
3610 printer->transmission_retry_timeout = 0xafc8;
3612 free_a_printer(&ntprinter, 2);
3616 /********************************************************************
3617 Spoolss_enumprinters.
3618 ********************************************************************/
3620 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3624 int n_services=lp_numservices();
3625 PRINTER_INFO_1 *tp, *printers=NULL;
3626 PRINTER_INFO_1 current_prt;
3628 DEBUG(4,("enum_all_printers_info_1\n"));
3630 for (snum=0; snum<n_services; snum++) {
3631 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3632 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3634 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
3635 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
3636 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3637 SAFE_FREE(printers);
3642 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
3644 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
3650 /* check the required size. */
3651 for (i=0; i<*returned; i++)
3652 (*needed) += spoolss_size_printer_info_1(&printers[i]);
3654 if (!alloc_buffer_size(buffer, *needed))
3655 return WERR_INSUFFICIENT_BUFFER;
3657 /* fill the buffer with the structures */
3658 for (i=0; i<*returned; i++)
3659 smb_io_printer_info_1("", buffer, &printers[i], 0);
3662 SAFE_FREE(printers);
3664 if (*needed > offered) {
3666 return WERR_INSUFFICIENT_BUFFER;
3672 /********************************************************************
3673 enum_all_printers_info_1_local.
3674 *********************************************************************/
3676 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3678 DEBUG(4,("enum_all_printers_info_1_local\n"));
3680 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3683 /********************************************************************
3684 enum_all_printers_info_1_name.
3685 *********************************************************************/
3687 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3691 DEBUG(4,("enum_all_printers_info_1_name\n"));
3693 if ((name[0] == '\\') && (name[1] == '\\'))
3696 if (is_myname_or_ipaddr(s)) {
3697 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3700 return WERR_INVALID_NAME;
3703 /********************************************************************
3704 enum_all_printers_info_1_remote.
3705 *********************************************************************/
3707 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3709 PRINTER_INFO_1 *printer;
3710 fstring printername;
3713 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3715 /* JFM: currently it's more a place holder than anything else.
3716 * In the spooler world there is a notion of server registration.
3717 * the print servers are registring (sp ?) on the PDC (in the same domain)
3719 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3722 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3727 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3728 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3729 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3731 init_unistr(&printer->description, desc);
3732 init_unistr(&printer->name, printername);
3733 init_unistr(&printer->comment, comment);
3734 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3736 /* check the required size. */
3737 *needed += spoolss_size_printer_info_1(printer);
3739 if (!alloc_buffer_size(buffer, *needed)) {
3741 return WERR_INSUFFICIENT_BUFFER;
3744 /* fill the buffer with the structures */
3745 smb_io_printer_info_1("", buffer, printer, 0);
3750 if (*needed > offered) {
3752 return WERR_INSUFFICIENT_BUFFER;
3758 /********************************************************************
3759 enum_all_printers_info_1_network.
3760 *********************************************************************/
3762 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3766 DEBUG(4,("enum_all_printers_info_1_network\n"));
3768 /* If we respond to a enum_printers level 1 on our name with flags
3769 set to PRINTER_ENUM_REMOTE with a list of printers then these
3770 printers incorrectly appear in the APW browse list.
3771 Specifically the printers for the server appear at the workgroup
3772 level where all the other servers in the domain are
3773 listed. Windows responds to this call with a
3774 WERR_CAN_NOT_COMPLETE so we should do the same. */
3776 if (name[0] == '\\' && name[1] == '\\')
3779 if (is_myname_or_ipaddr(s))
3780 return WERR_CAN_NOT_COMPLETE;
3782 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3785 /********************************************************************
3786 * api_spoolss_enumprinters
3788 * called from api_spoolss_enumprinters (see this to understand)
3789 ********************************************************************/
3791 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3795 int n_services=lp_numservices();
3796 PRINTER_INFO_2 *tp, *printers=NULL;
3797 PRINTER_INFO_2 current_prt;
3799 for (snum=0; snum<n_services; snum++) {
3800 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3801 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3803 if (construct_printer_info_2(¤t_prt, snum)) {
3804 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3805 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3806 SAFE_FREE(printers);
3811 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3812 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
3818 /* check the required size. */
3819 for (i=0; i<*returned; i++)
3820 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3822 if (!alloc_buffer_size(buffer, *needed)) {
3823 for (i=0; i<*returned; i++) {
3824 free_devmode(printers[i].devmode);
3826 SAFE_FREE(printers);
3827 return WERR_INSUFFICIENT_BUFFER;
3830 /* fill the buffer with the structures */
3831 for (i=0; i<*returned; i++)
3832 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3835 for (i=0; i<*returned; i++) {
3836 free_devmode(printers[i].devmode);
3838 SAFE_FREE(printers);
3840 if (*needed > offered) {
3842 return WERR_INSUFFICIENT_BUFFER;
3848 /********************************************************************
3849 * handle enumeration of printers at level 1
3850 ********************************************************************/
3852 static WERROR enumprinters_level1( uint32 flags, fstring name,
3853 NEW_BUFFER *buffer, uint32 offered,
3854 uint32 *needed, uint32 *returned)
3856 /* Not all the flags are equals */
3858 if (flags & PRINTER_ENUM_LOCAL)
3859 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3861 if (flags & PRINTER_ENUM_NAME)
3862 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3864 if (flags & PRINTER_ENUM_REMOTE)
3865 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3867 if (flags & PRINTER_ENUM_NETWORK)
3868 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
3870 return WERR_OK; /* NT4sp5 does that */
3873 /********************************************************************
3874 * handle enumeration of printers at level 2
3875 ********************************************************************/
3877 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3878 NEW_BUFFER *buffer, uint32 offered,
3879 uint32 *needed, uint32 *returned)
3881 char *s = servername;
3883 if (flags & PRINTER_ENUM_LOCAL) {
3884 return enum_all_printers_info_2(buffer, offered, needed, returned);
3887 if (flags & PRINTER_ENUM_NAME) {
3888 if ((servername[0] == '\\') && (servername[1] == '\\'))
3890 if (is_myname_or_ipaddr(s))
3891 return enum_all_printers_info_2(buffer, offered, needed, returned);
3893 return WERR_INVALID_NAME;
3896 if (flags & PRINTER_ENUM_REMOTE)
3897 return WERR_UNKNOWN_LEVEL;
3902 /********************************************************************
3903 * handle enumeration of printers at level 5
3904 ********************************************************************/
3906 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3907 NEW_BUFFER *buffer, uint32 offered,
3908 uint32 *needed, uint32 *returned)
3910 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3914 /********************************************************************
3915 * api_spoolss_enumprinters
3917 * called from api_spoolss_enumprinters (see this to understand)
3918 ********************************************************************/
3920 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3922 uint32 flags = q_u->flags;
3923 UNISTR2 *servername = &q_u->servername;
3924 uint32 level = q_u->level;
3925 NEW_BUFFER *buffer = NULL;
3926 uint32 offered = q_u->offered;
3927 uint32 *needed = &r_u->needed;
3928 uint32 *returned = &r_u->returned;
3932 /* that's an [in out] buffer */
3933 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3934 buffer = r_u->buffer;
3936 DEBUG(4,("_spoolss_enumprinters\n"));
3943 * flags==PRINTER_ENUM_NAME
3944 * if name=="" then enumerates all printers
3945 * if name!="" then enumerate the printer
3946 * flags==PRINTER_ENUM_REMOTE
3947 * name is NULL, enumerate printers
3948 * Level 2: name!="" enumerates printers, name can't be NULL
3949 * Level 3: doesn't exist
3950 * Level 4: does a local registry lookup
3951 * Level 5: same as Level 2
3954 unistr2_to_ascii(name, servername, sizeof(name)-1);
3959 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3961 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3963 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3968 return WERR_UNKNOWN_LEVEL;
3971 /****************************************************************************
3972 ****************************************************************************/
3974 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3976 PRINTER_INFO_0 *printer=NULL;
3978 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3981 construct_printer_info_0(printer, snum);
3983 /* check the required size. */
3984 *needed += spoolss_size_printer_info_0(printer);
3986 if (!alloc_buffer_size(buffer, *needed)) {
3988 return WERR_INSUFFICIENT_BUFFER;
3991 /* fill the buffer with the structures */
3992 smb_io_printer_info_0("", buffer, printer, 0);
3997 if (*needed > offered) {
3998 return WERR_INSUFFICIENT_BUFFER;
4004 /****************************************************************************
4005 ****************************************************************************/
4007 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4009 PRINTER_INFO_1 *printer=NULL;
4011 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4014 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4016 /* check the required size. */
4017 *needed += spoolss_size_printer_info_1(printer);
4019 if (!alloc_buffer_size(buffer, *needed)) {
4021 return WERR_INSUFFICIENT_BUFFER;
4024 /* fill the buffer with the structures */
4025 smb_io_printer_info_1("", buffer, printer, 0);
4030 if (*needed > offered) {
4031 return WERR_INSUFFICIENT_BUFFER;
4037 /****************************************************************************
4038 ****************************************************************************/
4040 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4042 PRINTER_INFO_2 *printer=NULL;
4044 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4047 construct_printer_info_2(printer, snum);
4049 /* check the required size. */
4050 *needed += spoolss_size_printer_info_2(printer);
4052 if (!alloc_buffer_size(buffer, *needed)) {
4053 free_printer_info_2(printer);
4054 return WERR_INSUFFICIENT_BUFFER;
4057 /* fill the buffer with the structures */
4058 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4059 free_printer_info_2(printer);
4064 free_printer_info_2(printer);
4066 if (*needed > offered) {
4067 return WERR_INSUFFICIENT_BUFFER;
4073 /****************************************************************************
4074 ****************************************************************************/
4076 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4078 PRINTER_INFO_3 *printer=NULL;
4080 if (!construct_printer_info_3(&printer, snum))
4083 /* check the required size. */
4084 *needed += spoolss_size_printer_info_3(printer);
4086 if (!alloc_buffer_size(buffer, *needed)) {
4087 free_printer_info_3(printer);
4088 return WERR_INSUFFICIENT_BUFFER;
4091 /* fill the buffer with the structures */
4092 smb_io_printer_info_3("", buffer, printer, 0);
4095 free_printer_info_3(printer);
4097 if (*needed > offered) {
4098 return WERR_INSUFFICIENT_BUFFER;
4104 /****************************************************************************
4105 ****************************************************************************/
4107 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4109 PRINTER_INFO_4 *printer=NULL;
4111 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4114 if (!construct_printer_info_4(printer, snum))
4117 /* check the required size. */
4118 *needed += spoolss_size_printer_info_4(printer);
4120 if (!alloc_buffer_size(buffer, *needed)) {
4121 free_printer_info_4(printer);
4122 return WERR_INSUFFICIENT_BUFFER;
4125 /* fill the buffer with the structures */
4126 smb_io_printer_info_4("", buffer, printer, 0);
4129 free_printer_info_4(printer);
4131 if (*needed > offered) {
4132 return WERR_INSUFFICIENT_BUFFER;
4138 /****************************************************************************
4139 ****************************************************************************/
4141 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4143 PRINTER_INFO_5 *printer=NULL;
4145 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4148 if (!construct_printer_info_5(printer, snum))
4151 /* check the required size. */
4152 *needed += spoolss_size_printer_info_5(printer);
4154 if (!alloc_buffer_size(buffer, *needed)) {
4155 free_printer_info_5(printer);
4156 return WERR_INSUFFICIENT_BUFFER;
4159 /* fill the buffer with the structures */
4160 smb_io_printer_info_5("", buffer, printer, 0);
4163 free_printer_info_5(printer);
4165 if (*needed > offered) {
4166 return WERR_INSUFFICIENT_BUFFER;
4172 /****************************************************************************
4173 ****************************************************************************/
4175 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4177 POLICY_HND *handle = &q_u->handle;
4178 uint32 level = q_u->level;
4179 NEW_BUFFER *buffer = NULL;
4180 uint32 offered = q_u->offered;
4181 uint32 *needed = &r_u->needed;
4185 /* that's an [in out] buffer */
4186 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4187 buffer = r_u->buffer;
4191 if (!get_printer_snum(p, handle, &snum))
4196 return getprinter_level_0(snum, buffer, offered, needed);
4198 return getprinter_level_1(snum, buffer, offered, needed);
4200 return getprinter_level_2(snum, buffer, offered, needed);
4202 return getprinter_level_3(snum, buffer, offered, needed);
4204 return getprinter_level_4(snum, buffer, offered, needed);
4206 return getprinter_level_5(snum, buffer, offered, needed);
4208 return WERR_UNKNOWN_LEVEL;
4211 /********************************************************************
4212 * fill a DRIVER_INFO_1 struct
4213 ********************************************************************/
4215 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4217 init_unistr( &info->name, driver.info_3->name);
4220 /********************************************************************
4221 * construct_printer_driver_info_1
4222 ********************************************************************/
4224 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4226 NT_PRINTER_INFO_LEVEL *printer = NULL;
4227 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4229 ZERO_STRUCT(driver);
4231 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4232 return WERR_INVALID_PRINTER_NAME;
4234 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4235 return WERR_UNKNOWN_PRINTER_DRIVER;
4237 fill_printer_driver_info_1(info, driver, servername, architecture);
4239 free_a_printer(&printer,2);
4244 /********************************************************************
4245 * construct_printer_driver_info_2
4246 * fill a printer_info_2 struct
4247 ********************************************************************/
4249 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4253 info->version=driver.info_3->cversion;
4255 init_unistr( &info->name, driver.info_3->name );
4256 init_unistr( &info->architecture, driver.info_3->environment );
4259 if (strlen(driver.info_3->driverpath)) {
4260 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4261 init_unistr( &info->driverpath, temp );
4263 init_unistr( &info->driverpath, "" );
4265 if (strlen(driver.info_3->datafile)) {
4266 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4267 init_unistr( &info->datafile, temp );
4269 init_unistr( &info->datafile, "" );
4271 if (strlen(driver.info_3->configfile)) {
4272 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4273 init_unistr( &info->configfile, temp );
4275 init_unistr( &info->configfile, "" );
4278 /********************************************************************
4279 * construct_printer_driver_info_2
4280 * fill a printer_info_2 struct
4281 ********************************************************************/
4283 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4285 NT_PRINTER_INFO_LEVEL *printer = NULL;
4286 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4288 ZERO_STRUCT(printer);
4289 ZERO_STRUCT(driver);
4291 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4292 return WERR_INVALID_PRINTER_NAME;
4294 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4295 return WERR_UNKNOWN_PRINTER_DRIVER;
4297 fill_printer_driver_info_2(info, driver, servername);
4299 free_a_printer(&printer,2);
4304 /********************************************************************
4305 * copy a strings array and convert to UNICODE
4307 * convert an array of ascii string to a UNICODE string
4308 ********************************************************************/
4310 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4318 DEBUG(6,("init_unistr_array\n"));
4322 if (char_array == NULL)
4326 if (!v) v = ""; /* hack to handle null lists */
4328 if (strlen(v) == 0) break;
4329 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
4330 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4331 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
4332 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4336 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
4341 (*uni_array)[j]=0x0000;
4344 DEBUGADD(6,("last one:done\n"));
4347 /********************************************************************
4348 * construct_printer_info_3
4349 * fill a printer_info_3 struct
4350 ********************************************************************/
4352 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4358 info->version=driver.info_3->cversion;
4360 init_unistr( &info->name, driver.info_3->name );
4361 init_unistr( &info->architecture, driver.info_3->environment );
4363 if (strlen(driver.info_3->driverpath)) {
4364 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4365 init_unistr( &info->driverpath, temp );
4367 init_unistr( &info->driverpath, "" );
4369 if (strlen(driver.info_3->datafile)) {
4370 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4371 init_unistr( &info->datafile, temp );
4373 init_unistr( &info->datafile, "" );
4375 if (strlen(driver.info_3->configfile)) {
4376 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4377 init_unistr( &info->configfile, temp );
4379 init_unistr( &info->configfile, "" );
4381 if (strlen(driver.info_3->helpfile)) {
4382 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4383 init_unistr( &info->helpfile, temp );
4385 init_unistr( &info->helpfile, "" );
4387 init_unistr( &info->monitorname, driver.info_3->monitorname );
4388 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4390 info->dependentfiles=NULL;
4391 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4394 /********************************************************************
4395 * construct_printer_info_3
4396 * fill a printer_info_3 struct
4397 ********************************************************************/
4399 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4401 NT_PRINTER_INFO_LEVEL *printer = NULL;
4402 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4404 ZERO_STRUCT(driver);
4406 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4407 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4408 if (!W_ERROR_IS_OK(status))
4409 return WERR_INVALID_PRINTER_NAME;
4411 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4412 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4417 * I put this code in during testing. Helpful when commenting out the
4418 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4419 * as win2k always queries the driver using an infor level of 6.
4420 * I've left it in (but ifdef'd out) because I'll probably
4421 * use it in experimentation again in the future. --jerry 22/01/2002
4424 if (!W_ERROR_IS_OK(status)) {
4426 * Is this a W2k client ?
4429 /* Yes - try again with a WinNT driver. */
4431 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4432 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4436 if (!W_ERROR_IS_OK(status)) {
4437 free_a_printer(&printer,2);
4438 return WERR_UNKNOWN_PRINTER_DRIVER;
4446 fill_printer_driver_info_3(info, driver, servername);
4448 free_a_printer(&printer,2);
4453 /********************************************************************
4454 * construct_printer_info_6
4455 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4456 ********************************************************************/
4458 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4464 memset(&nullstr, '\0', sizeof(fstring));
4466 info->version=driver.info_3->cversion;
4468 init_unistr( &info->name, driver.info_3->name );
4469 init_unistr( &info->architecture, driver.info_3->environment );
4471 if (strlen(driver.info_3->driverpath)) {
4472 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4473 init_unistr( &info->driverpath, temp );
4475 init_unistr( &info->driverpath, "" );
4477 if (strlen(driver.info_3->datafile)) {
4478 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4479 init_unistr( &info->datafile, temp );
4481 init_unistr( &info->datafile, "" );
4483 if (strlen(driver.info_3->configfile)) {
4484 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4485 init_unistr( &info->configfile, temp );
4487 init_unistr( &info->configfile, "" );
4489 if (strlen(driver.info_3->helpfile)) {
4490 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4491 init_unistr( &info->helpfile, temp );
4493 init_unistr( &info->helpfile, "" );
4495 init_unistr( &info->monitorname, driver.info_3->monitorname );
4496 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4498 info->dependentfiles=NULL;
4499 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4501 info->previousdrivernames=NULL;
4502 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4504 info->driver_date.low=0;
4505 info->driver_date.high=0;
4508 info->driver_version_low=0;
4509 info->driver_version_high=0;
4511 init_unistr( &info->mfgname, "");
4512 init_unistr( &info->oem_url, "");
4513 init_unistr( &info->hardware_id, "");
4514 init_unistr( &info->provider, "");
4517 /********************************************************************
4518 * construct_printer_info_6
4519 * fill a printer_info_6 struct
4520 ********************************************************************/
4522 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
4524 NT_PRINTER_INFO_LEVEL *printer = NULL;
4525 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4527 ZERO_STRUCT(driver);
4529 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4530 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4531 if (!W_ERROR_IS_OK(status))
4532 return WERR_INVALID_PRINTER_NAME;
4534 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4535 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4536 if (!W_ERROR_IS_OK(status)) {
4538 * Is this a W2k client ?
4542 free_a_printer(&printer,2);
4543 return WERR_UNKNOWN_PRINTER_DRIVER;
4546 /* Yes - try again with a WinNT driver. */
4548 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4549 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4550 if (!W_ERROR_IS_OK(status)) {
4551 free_a_printer(&printer,2);
4552 return WERR_UNKNOWN_PRINTER_DRIVER;
4556 fill_printer_driver_info_6(info, driver, servername);
4558 free_a_printer(&printer,2);
4563 /****************************************************************************
4564 ****************************************************************************/
4566 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
4568 SAFE_FREE(info->dependentfiles);
4571 /****************************************************************************
4572 ****************************************************************************/
4574 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
4576 SAFE_FREE(info->dependentfiles);
4580 /****************************************************************************
4581 ****************************************************************************/
4583 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4585 DRIVER_INFO_1 *info=NULL;
4588 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
4591 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
4592 if (!W_ERROR_IS_OK(status)) {
4597 /* check the required size. */
4598 *needed += spoolss_size_printer_driver_info_1(info);
4600 if (!alloc_buffer_size(buffer, *needed)) {
4602 return WERR_INSUFFICIENT_BUFFER;
4605 /* fill the buffer with the structures */
4606 smb_io_printer_driver_info_1("", buffer, info, 0);
4611 if (*needed > offered)
4612 return WERR_INSUFFICIENT_BUFFER;
4617 /****************************************************************************
4618 ****************************************************************************/
4620 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4622 DRIVER_INFO_2 *info=NULL;
4625 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
4628 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
4629 if (!W_ERROR_IS_OK(status)) {
4634 /* check the required size. */
4635 *needed += spoolss_size_printer_driver_info_2(info);
4637 if (!alloc_buffer_size(buffer, *needed)) {
4639 return WERR_INSUFFICIENT_BUFFER;
4642 /* fill the buffer with the structures */
4643 smb_io_printer_driver_info_2("", buffer, info, 0);
4648 if (*needed > offered)
4649 return WERR_INSUFFICIENT_BUFFER;
4654 /****************************************************************************
4655 ****************************************************************************/
4657 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4664 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
4665 if (!W_ERROR_IS_OK(status)) {
4669 /* check the required size. */
4670 *needed += spoolss_size_printer_driver_info_3(&info);
4672 if (!alloc_buffer_size(buffer, *needed)) {
4673 free_printer_driver_info_3(&info);
4674 return WERR_INSUFFICIENT_BUFFER;
4677 /* fill the buffer with the structures */
4678 smb_io_printer_driver_info_3("", buffer, &info, 0);
4680 free_printer_driver_info_3(&info);
4682 if (*needed > offered)
4683 return WERR_INSUFFICIENT_BUFFER;
4688 /****************************************************************************
4689 ****************************************************************************/
4691 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4698 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
4699 if (!W_ERROR_IS_OK(status)) {
4703 /* check the required size. */
4704 *needed += spoolss_size_printer_driver_info_6(&info);
4706 if (!alloc_buffer_size(buffer, *needed)) {
4707 free_printer_driver_info_6(&info);
4708 return WERR_INSUFFICIENT_BUFFER;
4711 /* fill the buffer with the structures */
4712 smb_io_printer_driver_info_6("", buffer, &info, 0);
4714 free_printer_driver_info_6(&info);
4716 if (*needed > offered)
4717 return WERR_INSUFFICIENT_BUFFER;
4722 /****************************************************************************
4723 ****************************************************************************/
4725 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
4727 POLICY_HND *handle = &q_u->handle;
4728 UNISTR2 *uni_arch = &q_u->architecture;
4729 uint32 level = q_u->level;
4730 uint32 clientmajorversion = q_u->clientmajorversion;
4731 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
4732 NEW_BUFFER *buffer = NULL;
4733 uint32 offered = q_u->offered;
4734 uint32 *needed = &r_u->needed;
4735 uint32 *servermajorversion = &r_u->servermajorversion;
4736 uint32 *serverminorversion = &r_u->serverminorversion;
4739 fstring architecture;
4742 /* that's an [in out] buffer */
4743 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4744 buffer = r_u->buffer;
4746 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4749 *servermajorversion=0;
4750 *serverminorversion=0;
4752 pstrcpy(servername, get_called_name());
4753 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4755 if (!get_printer_snum(p, handle, &snum))
4760 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4762 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4764 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4766 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4769 return WERR_UNKNOWN_LEVEL;
4772 /****************************************************************************
4773 ****************************************************************************/
4775 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4777 POLICY_HND *handle = &q_u->handle;
4779 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4782 DEBUG(3,("Error in startpageprinter printer handle\n"));
4786 Printer->page_started=True;
4790 /****************************************************************************
4791 ****************************************************************************/
4793 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4795 POLICY_HND *handle = &q_u->handle;
4797 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4800 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
4804 Printer->page_started=False;
4805 print_job_endpage(Printer->jobid);
4810 /********************************************************************
4811 * api_spoolss_getprinter
4812 * called from the spoolss dispatcher
4814 ********************************************************************/
4816 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4818 POLICY_HND *handle = &q_u->handle;
4819 /* uint32 level = q_u->doc_info_container.level; - notused. */
4820 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4821 uint32 *jobid = &r_u->jobid;
4823 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4827 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4828 struct current_user user;
4831 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4835 get_current_user(&user, p);
4838 * a nice thing with NT is it doesn't listen to what you tell it.
4839 * when asked to send _only_ RAW datas, it tries to send datas
4842 * So I add checks like in NT Server ...
4844 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4845 * there's a bug in NT client-side code, so we'll fix it in the
4846 * server-side code. *nnnnnggggh!*
4849 if (info_1->p_datatype != 0) {
4850 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4851 if (strcmp(datatype, "RAW") != 0) {
4853 return WERR_INVALID_DATATYPE;
4857 /* get the share number of the printer */
4858 if (!get_printer_snum(p, handle, &snum)) {
4862 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4864 Printer->jobid = print_job_start(&user, snum, jobname);
4866 /* An error occured in print_job_start() so return an appropriate
4869 if (Printer->jobid == -1) {
4870 return map_werror_from_unix(errno);
4873 Printer->document_started=True;
4874 (*jobid) = Printer->jobid;
4879 /********************************************************************
4880 * api_spoolss_getprinter
4881 * called from the spoolss dispatcher
4883 ********************************************************************/
4885 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4887 POLICY_HND *handle = &q_u->handle;
4889 return _spoolss_enddocprinter_internal(p, handle);
4892 /****************************************************************************
4893 ****************************************************************************/
4895 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4897 POLICY_HND *handle = &q_u->handle;
4898 uint32 buffer_size = q_u->buffer_size;
4899 uint8 *buffer = q_u->buffer;
4900 uint32 *buffer_written = &q_u->buffer_size2;
4902 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4905 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
4906 r_u->buffer_written = q_u->buffer_size2;
4910 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4913 r_u->buffer_written = q_u->buffer_size2;
4918 /********************************************************************
4919 * api_spoolss_getprinter
4920 * called from the spoolss dispatcher
4922 ********************************************************************/
4924 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4927 struct current_user user;
4929 WERROR errcode = WERR_BADFUNC;
4930 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4932 get_current_user(&user, p);
4935 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4939 if (!get_printer_snum(p, handle, &snum))
4943 case PRINTER_CONTROL_PAUSE:
4944 if (print_queue_pause(&user, snum, &errcode)) {
4948 case PRINTER_CONTROL_RESUME:
4949 case PRINTER_CONTROL_UNPAUSE:
4950 if (print_queue_resume(&user, snum, &errcode)) {
4954 case PRINTER_CONTROL_PURGE:
4955 if (print_queue_purge(&user, snum, &errcode)) {
4960 return WERR_UNKNOWN_LEVEL;
4966 /********************************************************************
4967 * api_spoolss_abortprinter
4968 ********************************************************************/
4970 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4972 POLICY_HND *handle = &q_u->handle;
4974 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4977 /********************************************************************
4978 * called by spoolss_api_setprinter
4979 * when updating a printer description
4980 ********************************************************************/
4982 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4983 const SPOOL_PRINTER_INFO_LEVEL *info,
4984 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4986 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4987 struct current_user user;
4991 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4993 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4994 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
4995 OUR_HANDLE(handle)));
4997 result = WERR_BADFID;
5001 /* NT seems to like setting the security descriptor even though
5002 nothing may have actually changed. This causes annoying
5003 dialog boxes when the user doesn't have permission to change
5004 the security descriptor. */
5006 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5008 if (DEBUGLEVEL >= 10) {
5012 the_acl = old_secdesc_ctr->sec->dacl;
5013 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5014 PRINTERNAME(snum), the_acl->num_aces));
5016 for (i = 0; i < the_acl->num_aces; i++) {
5019 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5021 DEBUG(10, ("%s 0x%08x\n", sid_str,
5022 the_acl->ace[i].info.mask));
5025 the_acl = secdesc_ctr->sec->dacl;
5028 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5029 PRINTERNAME(snum), the_acl->num_aces));
5031 for (i = 0; i < the_acl->num_aces; i++) {
5034 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5036 DEBUG(10, ("%s 0x%08x\n", sid_str,
5037 the_acl->ace[i].info.mask));
5040 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5044 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5046 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5051 /* Work out which user is performing the operation */
5053 get_current_user(&user, p);
5055 /* Check the user has permissions to change the security
5056 descriptor. By experimentation with two NT machines, the user
5057 requires Full Access to the printer to change security
5060 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5061 result = WERR_ACCESS_DENIED;
5065 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5072 /********************************************************************
5073 Do Samba sanity checks on a printer info struct.
5074 this has changed purpose: it now "canonicalises" printer
5075 info from a client rather than just checking it is correct
5076 ********************************************************************/
5078 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5080 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5081 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5083 /* we force some elements to "correct" values */
5084 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5085 fstrcpy(info->sharename, lp_servicename(snum));
5086 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5087 get_called_name(), info->sharename);
5088 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5093 /****************************************************************************
5094 ****************************************************************************/
5096 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5098 extern userdom_struct current_user_info;
5099 char *cmd = lp_addprinter_cmd();
5102 pstring driverlocation;
5106 fstring remote_machine = "%m";
5108 /* build driver path... only 9X architecture is needed for legacy reasons */
5109 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
5111 /* change \ to \\ for the shell */
5112 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
5113 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5115 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5116 cmd, printer->info_2->printername, printer->info_2->sharename,
5117 printer->info_2->portname, printer->info_2->drivername,
5118 printer->info_2->location, driverlocation, remote_machine);
5120 DEBUG(10,("Running [%s]\n", command));
5121 ret = smbrun(command, &fd);
5122 DEBUGADD(10,("returned [%d]\n", ret));
5131 /* Get lines and convert them back to dos-codepage */
5132 qlines = fd_lines_load(fd, &numlines);
5133 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5137 /* Set the portname to what the script says the portname should be. */
5138 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5139 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5141 /* Send SIGHUP to process group... is there a better way? */
5146 file_lines_free(qlines);
5152 /* Return true if two devicemodes are equal */
5154 #define DEVMODE_CHECK_INT(field) \
5155 if (d1->field != d2->field) { \
5156 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
5157 d1->field, d2->field)); \
5161 /************************************************************************
5162 Handy, but currently unused functions
5163 ***********************************************************************/
5165 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
5167 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
5170 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
5171 return False; /* if either is exclusively NULL are not equal */
5174 if (!strequal(d1->devicename, d2->devicename)) {
5175 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
5179 if (!strequal(d1->formname, d2->formname)) {
5180 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
5184 DEVMODE_CHECK_INT(specversion);
5185 DEVMODE_CHECK_INT(driverversion);
5186 DEVMODE_CHECK_INT(driverextra);
5187 DEVMODE_CHECK_INT(orientation);
5188 DEVMODE_CHECK_INT(papersize);
5189 DEVMODE_CHECK_INT(paperlength);
5190 DEVMODE_CHECK_INT(paperwidth);
5191 DEVMODE_CHECK_INT(scale);
5192 DEVMODE_CHECK_INT(copies);
5193 DEVMODE_CHECK_INT(defaultsource);
5194 DEVMODE_CHECK_INT(printquality);
5195 DEVMODE_CHECK_INT(color);
5196 DEVMODE_CHECK_INT(duplex);
5197 DEVMODE_CHECK_INT(yresolution);
5198 DEVMODE_CHECK_INT(ttoption);
5199 DEVMODE_CHECK_INT(collate);
5200 DEVMODE_CHECK_INT(logpixels);
5202 DEVMODE_CHECK_INT(fields);
5203 DEVMODE_CHECK_INT(bitsperpel);
5204 DEVMODE_CHECK_INT(pelswidth);
5205 DEVMODE_CHECK_INT(pelsheight);
5206 DEVMODE_CHECK_INT(displayflags);
5207 DEVMODE_CHECK_INT(displayfrequency);
5208 DEVMODE_CHECK_INT(icmmethod);
5209 DEVMODE_CHECK_INT(icmintent);
5210 DEVMODE_CHECK_INT(mediatype);
5211 DEVMODE_CHECK_INT(dithertype);
5212 DEVMODE_CHECK_INT(reserved1);
5213 DEVMODE_CHECK_INT(reserved2);
5214 DEVMODE_CHECK_INT(panningwidth);
5215 DEVMODE_CHECK_INT(panningheight);
5217 /* compare the private data if it exists */
5218 if (!d1->driverextra && !d2->driverextra) goto equal;
5221 DEVMODE_CHECK_INT(driverextra);
5223 if (memcmp(d1->private, d2->private, d1->driverextra)) {
5224 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
5229 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
5233 /* Return true if two NT_PRINTER_PARAM structures are equal */
5235 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
5236 NT_PRINTER_PARAM *p2)
5238 if (!p1 && !p2) goto equal;
5240 if ((!p1 && p2) || (p1 && !p2)) {
5241 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
5245 /* Compare lists of printer parameters */
5249 NT_PRINTER_PARAM *q = p1;
5251 /* Find the parameter in the second structure */
5255 if (strequal(p1->value, q->value)) {
5257 if (p1->type != q->type) {
5258 DEBUG(10, ("nt_printer_param_equal():"
5259 "types for %s differ (%d != %d)\n",
5260 p1->value, p1->type,
5265 if (p1->data_len != q->data_len) {
5266 DEBUG(10, ("nt_printer_param_equal():"
5267 "len for %s differs (%d != %d)\n",
5268 p1->value, p1->data_len,
5273 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
5276 DEBUG(10, ("nt_printer_param_equal():"
5277 "data for %s differs\n", p1->value));
5287 DEBUG(10, ("nt_printer_param_equal(): param %s "
5288 "does not exist\n", p1->value));
5297 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
5301 /********************************************************************
5302 * Called by update_printer when trying to work out whether to
5303 * actually update printer info.
5304 ********************************************************************/
5306 #define PI_CHECK_INT(field) \
5307 if (pi1->field != pi2->field) { \
5308 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
5309 pi1->field, pi2->field)); \
5313 #define PI_CHECK_STR(field) \
5314 if (!strequal(pi1->field, pi2->field)) { \
5315 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
5316 pi1->field, pi2->field)); \
5320 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
5321 NT_PRINTER_INFO_LEVEL *p2)
5323 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
5325 /* Trivial conditions */
5327 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
5331 if ((!p1 && p2) || (p1 && !p2) ||
5332 (!p1->info_2 && p2->info_2) ||
5333 (p1->info_2 && !p2->info_2)) {
5334 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
5339 /* Compare two nt_printer_info_level structures. Don't compare
5340 status or cjobs as they seem to have something to do with the
5346 /* Don't check the attributes as we stomp on the value in
5347 check_printer_ok() anyway. */
5350 PI_CHECK_INT(attributes);
5353 PI_CHECK_INT(priority);
5354 PI_CHECK_INT(default_priority);
5355 PI_CHECK_INT(starttime);
5356 PI_CHECK_INT(untiltime);
5357 PI_CHECK_INT(averageppm);
5359 /* Yuck - don't check the printername or servername as the
5360 mod_a_printer() code plays games with them. You can't
5361 change the printername or the sharename through this interface
5364 PI_CHECK_STR(sharename);
5365 PI_CHECK_STR(portname);
5366 PI_CHECK_STR(drivername);
5367 PI_CHECK_STR(comment);
5368 PI_CHECK_STR(location);
5370 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
5374 PI_CHECK_STR(sepfile);
5375 PI_CHECK_STR(printprocessor);
5376 PI_CHECK_STR(datatype);
5377 PI_CHECK_STR(parameters);
5379 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
5383 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
5387 PI_CHECK_INT(changeid);
5388 PI_CHECK_INT(c_setprinter);
5389 PI_CHECK_INT(setuptime);
5392 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
5398 /********************************************************************
5399 * Called by spoolss_api_setprinter
5400 * when updating a printer description.
5401 ********************************************************************/
5403 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5404 const SPOOL_PRINTER_INFO_LEVEL *info,
5405 DEVICEMODE *devmode)
5408 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5409 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5412 DEBUG(8,("update_printer\n"));
5417 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5418 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5419 result = WERR_UNKNOWN_LEVEL;
5424 result = WERR_BADFID;
5428 if (!get_printer_snum(p, handle, &snum)) {
5429 result = WERR_BADFID;
5433 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5434 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5435 result = WERR_BADFID;
5439 DEBUGADD(8,("Converting info_2 struct\n"));
5442 * convert_printer_info converts the incoming
5443 * info from the client and overwrites the info
5444 * just read from the tdb in the pointer 'printer'.
5447 if (!convert_printer_info(info, printer, level)) {
5448 result = WERR_NOMEM;
5453 /* we have a valid devmode
5454 convert it and link it*/
5456 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5457 if (!convert_devicemode(printer->info_2->printername, devmode,
5458 &printer->info_2->devmode)) {
5459 result = WERR_NOMEM;
5464 /* Do sanity check on the requested changes for Samba */
5466 if (!check_printer_ok(printer->info_2, snum)) {
5467 result = WERR_INVALID_PARAM;
5474 * Another one of those historical misunderstandings...
5475 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5476 * I'm leaving it here as a reminder. --jerry
5479 if (nt_printer_info_level_equal(printer, old_printer)) {
5480 DEBUG(3, ("update_printer: printer info has not changed\n"));
5487 /* Check calling user has permission to update printer description */
5489 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5490 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5491 result = WERR_ACCESS_DENIED;
5495 /* Call addprinter hook */
5497 if (*lp_addprinter_cmd()) {
5498 if ( !add_printer_hook(printer) ) {
5499 result = WERR_ACCESS_DENIED;
5505 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5506 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5507 * requires Win32 client code (see other notes elsewhere in the code).
5509 if (printer->info_2->devmode &&
5510 printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) {
5512 DEBUG(10,("update_printer: Save printer driver init data\n"));
5513 printer->info_2->devmode->displayfrequency = 0;
5515 if (update_driver_init(*printer, 2)!=0) {
5516 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5517 result = WERR_ACCESS_DENIED;
5522 * When a *new* driver is bound to a printer, the drivername is used to
5523 * lookup previously saved driver initialization info, which is then
5524 * bound to the printer, simulating what happens in the Windows arch.
5526 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){
5527 if (!set_driver_init(printer, 2)) {
5528 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5529 printer->info_2->drivername));
5531 notify_printer_driver(snum, printer->info_2->drivername);
5535 /* Update printer info */
5536 result = mod_a_printer(*printer, 2);
5538 /* flag which changes actually occured. This is a small subset of
5539 all the possible changes */
5541 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5542 notify_printer_comment(snum, printer->info_2->comment);
5544 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5545 notify_printer_sharename(snum, printer->info_2->sharename);
5547 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5548 notify_printer_port(snum, printer->info_2->portname);
5550 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5551 notify_printer_location(snum, printer->info_2->location);
5554 free_a_printer(&printer, 2);
5555 free_a_printer(&old_printer, 2);
5561 /****************************************************************************
5562 ****************************************************************************/
5564 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5566 POLICY_HND *handle = &q_u->handle;
5567 uint32 level = q_u->level;
5568 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5569 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5570 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5571 uint32 command = q_u->command;
5573 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5576 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5580 /* check the level */
5583 return control_printer(handle, command, p);
5585 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5587 return update_printer_sec(handle, level, info, p,
5590 return WERR_UNKNOWN_LEVEL;
5594 /****************************************************************************
5595 ****************************************************************************/
5597 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5599 POLICY_HND *handle = &q_u->handle;
5601 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5604 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5608 if (Printer->notify.client_connected==True)
5609 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5611 Printer->notify.flags=0;
5612 Printer->notify.options=0;
5613 Printer->notify.localmachine[0]='\0';
5614 Printer->notify.printerlocal=0;
5615 if (Printer->notify.option)
5616 free_spool_notify_option(&Printer->notify.option);
5617 Printer->notify.client_connected=False;
5622 /****************************************************************************
5623 ****************************************************************************/
5625 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5627 /* that's an [in out] buffer (despite appearences to the contrary) */
5628 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5631 return WERR_INVALID_PARAM; /* this is what a NT server
5632 returns for AddJob. AddJob
5633 must fail on non-local
5637 /****************************************************************************
5638 ****************************************************************************/
5640 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5641 int position, int snum)
5647 t=gmtime(&queue->time);
5648 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5650 job_info->jobid=queue->job;
5651 init_unistr(&job_info->printername, lp_servicename(snum));
5652 init_unistr(&job_info->machinename, temp_name);
5653 init_unistr(&job_info->username, queue->fs_user);
5654 init_unistr(&job_info->document, queue->fs_file);
5655 init_unistr(&job_info->datatype, "RAW");
5656 init_unistr(&job_info->text_status, "");
5657 job_info->status=nt_printj_status(queue->status);
5658 job_info->priority=queue->priority;
5659 job_info->position=position;
5660 job_info->totalpages=queue->page_count;
5661 job_info->pagesprinted=0;
5663 make_systemtime(&job_info->submitted, t);
5666 /****************************************************************************
5667 ****************************************************************************/
5669 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5670 int position, int snum,
5671 NT_PRINTER_INFO_LEVEL *ntprinter,
5672 DEVICEMODE *devmode)
5678 t=gmtime(&queue->time);
5679 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5681 job_info->jobid=queue->job;
5683 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5685 init_unistr(&job_info->printername, chaine);
5687 init_unistr(&job_info->machinename, temp_name);
5688 init_unistr(&job_info->username, queue->fs_user);
5689 init_unistr(&job_info->document, queue->fs_file);
5690 init_unistr(&job_info->notifyname, queue->fs_user);
5691 init_unistr(&job_info->datatype, "RAW");
5692 init_unistr(&job_info->printprocessor, "winprint");
5693 init_unistr(&job_info->parameters, "");
5694 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5695 init_unistr(&job_info->text_status, "");
5697 /* and here the security descriptor */
5699 job_info->status=nt_printj_status(queue->status);
5700 job_info->priority=queue->priority;
5701 job_info->position=position;
5702 job_info->starttime=0;
5703 job_info->untiltime=0;
5704 job_info->totalpages=queue->page_count;
5705 job_info->size=queue->size;
5706 make_systemtime(&(job_info->submitted), t);
5707 job_info->timeelapsed=0;
5708 job_info->pagesprinted=0;
5710 job_info->devmode = devmode;
5715 /****************************************************************************
5716 Enumjobs at level 1.
5717 ****************************************************************************/
5719 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5720 NEW_BUFFER *buffer, uint32 offered,
5721 uint32 *needed, uint32 *returned)
5726 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5733 for (i=0; i<*returned; i++)
5734 fill_job_info_1(&info[i], &queue[i], i, snum);
5738 /* check the required size. */
5739 for (i=0; i<*returned; i++)
5740 (*needed) += spoolss_size_job_info_1(&info[i]);
5742 if (!alloc_buffer_size(buffer, *needed)) {
5744 return WERR_INSUFFICIENT_BUFFER;
5747 /* fill the buffer with the structures */
5748 for (i=0; i<*returned; i++)
5749 smb_io_job_info_1("", buffer, &info[i], 0);
5754 if (*needed > offered) {
5756 return WERR_INSUFFICIENT_BUFFER;
5762 /****************************************************************************
5763 Enumjobs at level 2.
5764 ****************************************************************************/
5766 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5767 NEW_BUFFER *buffer, uint32 offered,
5768 uint32 *needed, uint32 *returned)
5770 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5771 JOB_INFO_2 *info = NULL;
5774 DEVICEMODE *devmode = NULL;
5776 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5779 result = WERR_NOMEM;
5783 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5784 if (!W_ERROR_IS_OK(result)) {
5789 if (!(devmode = construct_dev_mode(snum))) {
5791 result = WERR_NOMEM;
5795 for (i=0; i<*returned; i++)
5796 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
5799 free_a_printer(&ntprinter, 2);
5802 /* check the required size. */
5803 for (i=0; i<*returned; i++)
5804 (*needed) += spoolss_size_job_info_2(&info[i]);
5806 if (*needed > offered) {
5808 result = WERR_INSUFFICIENT_BUFFER;
5812 if (!alloc_buffer_size(buffer, *needed)) {
5814 result = WERR_INSUFFICIENT_BUFFER;
5818 /* fill the buffer with the structures */
5819 for (i=0; i<*returned; i++)
5820 smb_io_job_info_2("", buffer, &info[i], 0);
5825 free_a_printer(&ntprinter, 2);
5826 free_devmode(devmode);
5834 /****************************************************************************
5836 ****************************************************************************/
5838 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5840 POLICY_HND *handle = &q_u->handle;
5841 /* uint32 firstjob = q_u->firstjob; - notused. */
5842 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5843 uint32 level = q_u->level;
5844 NEW_BUFFER *buffer = NULL;
5845 uint32 offered = q_u->offered;
5846 uint32 *needed = &r_u->needed;
5847 uint32 *returned = &r_u->returned;
5850 print_status_struct prt_status;
5851 print_queue_struct *queue=NULL;
5853 /* that's an [in out] buffer */
5854 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5855 buffer = r_u->buffer;
5857 DEBUG(4,("_spoolss_enumjobs\n"));
5862 if (!get_printer_snum(p, handle, &snum))
5865 *returned = print_queue_status(snum, &queue, &prt_status);
5866 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5868 if (*returned == 0) {
5875 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5877 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5881 return WERR_UNKNOWN_LEVEL;
5885 /****************************************************************************
5886 ****************************************************************************/
5888 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5893 /****************************************************************************
5894 ****************************************************************************/
5896 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5898 POLICY_HND *handle = &q_u->handle;
5899 uint32 jobid = q_u->jobid;
5900 uint32 command = q_u->command;
5902 struct current_user user;
5904 WERROR errcode = WERR_BADFUNC;
5906 if (!get_printer_snum(p, handle, &snum)) {
5910 if (!print_job_exists(jobid)) {
5911 return WERR_INVALID_PRINTER_NAME;
5914 get_current_user(&user, p);
5917 case JOB_CONTROL_CANCEL:
5918 case JOB_CONTROL_DELETE:
5919 if (print_job_delete(&user, jobid, &errcode)) {
5923 case JOB_CONTROL_PAUSE:
5924 if (print_job_pause(&user, jobid, &errcode)) {
5928 case JOB_CONTROL_RESTART:
5929 case JOB_CONTROL_RESUME:
5930 if (print_job_resume(&user, jobid, &errcode)) {
5935 return WERR_UNKNOWN_LEVEL;
5941 /****************************************************************************
5942 Enumerates all printer drivers at level 1.
5943 ****************************************************************************/
5945 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5950 fstring *list = NULL;
5952 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5953 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5957 for (version=0; version<DRIVER_MAX_VERSION; version++) {
5959 ndrivers=get_ntdrivers(&list, architecture, version);
5960 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5966 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5967 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5968 SAFE_FREE(driver_info_1);
5972 else driver_info_1 = tdi1;
5975 for (i=0; i<ndrivers; i++) {
5977 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5978 ZERO_STRUCT(driver);
5979 status = get_a_printer_driver(&driver, 3, list[i],
5980 architecture, version);
5981 if (!W_ERROR_IS_OK(status)) {
5985 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5986 free_a_printer_driver(driver, 3);
5989 *returned+=ndrivers;
5993 /* check the required size. */
5994 for (i=0; i<*returned; i++) {
5995 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5996 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5999 if (!alloc_buffer_size(buffer, *needed)) {
6000 SAFE_FREE(driver_info_1);
6001 return WERR_INSUFFICIENT_BUFFER;
6004 /* fill the buffer with the driver structures */
6005 for (i=0; i<*returned; i++) {
6006 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6007 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6010 SAFE_FREE(driver_info_1);
6012 if (*needed > offered) {
6014 return WERR_INSUFFICIENT_BUFFER;
6020 /****************************************************************************
6021 Enumerates all printer drivers at level 2.
6022 ****************************************************************************/
6024 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6029 fstring *list = NULL;
6031 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6032 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6036 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6038 ndrivers=get_ntdrivers(&list, architecture, version);
6039 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6045 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6046 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6047 SAFE_FREE(driver_info_2);
6051 else driver_info_2 = tdi2;
6054 for (i=0; i<ndrivers; i++) {
6057 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6058 ZERO_STRUCT(driver);
6059 status = get_a_printer_driver(&driver, 3, list[i],
6060 architecture, version);
6061 if (!W_ERROR_IS_OK(status)) {
6065 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6066 free_a_printer_driver(driver, 3);
6069 *returned+=ndrivers;
6073 /* check the required size. */
6074 for (i=0; i<*returned; i++) {
6075 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6076 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6079 if (!alloc_buffer_size(buffer, *needed)) {
6080 SAFE_FREE(driver_info_2);
6081 return WERR_INSUFFICIENT_BUFFER;
6084 /* fill the buffer with the form structures */
6085 for (i=0; i<*returned; i++) {
6086 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6087 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6090 SAFE_FREE(driver_info_2);
6092 if (*needed > offered) {
6094 return WERR_INSUFFICIENT_BUFFER;
6100 /****************************************************************************
6101 Enumerates all printer drivers at level 3.
6102 ****************************************************************************/
6104 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6109 fstring *list = NULL;
6111 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6112 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6116 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6118 ndrivers=get_ntdrivers(&list, architecture, version);
6119 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6125 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6126 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6127 SAFE_FREE(driver_info_3);
6131 else driver_info_3 = tdi3;
6134 for (i=0; i<ndrivers; i++) {
6137 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6138 ZERO_STRUCT(driver);
6139 status = get_a_printer_driver(&driver, 3, list[i],
6140 architecture, version);
6141 if (!W_ERROR_IS_OK(status)) {
6145 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6146 free_a_printer_driver(driver, 3);
6149 *returned+=ndrivers;
6153 /* check the required size. */
6154 for (i=0; i<*returned; i++) {
6155 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6156 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6159 if (!alloc_buffer_size(buffer, *needed)) {
6160 SAFE_FREE(driver_info_3);
6161 return WERR_INSUFFICIENT_BUFFER;
6164 /* fill the buffer with the driver structures */
6165 for (i=0; i<*returned; i++) {
6166 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6167 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6170 for (i=0; i<*returned; i++)
6171 SAFE_FREE(driver_info_3[i].dependentfiles);
6173 SAFE_FREE(driver_info_3);
6175 if (*needed > offered) {
6177 return WERR_INSUFFICIENT_BUFFER;
6183 /****************************************************************************
6184 Enumerates all printer drivers.
6185 ****************************************************************************/
6187 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6189 /* UNISTR2 *name = &q_u->name; - notused. */
6190 UNISTR2 *environment = &q_u->environment;
6191 uint32 level = q_u->level;
6192 NEW_BUFFER *buffer = NULL;
6193 uint32 offered = q_u->offered;
6194 uint32 *needed = &r_u->needed;
6195 uint32 *returned = &r_u->returned;
6197 fstring *list = NULL;
6199 fstring architecture;
6201 /* that's an [in out] buffer */
6202 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6203 buffer = r_u->buffer;
6205 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6206 fstrcpy(servername, get_called_name());
6210 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6214 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6216 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6218 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6222 return WERR_UNKNOWN_LEVEL;
6226 /****************************************************************************
6227 ****************************************************************************/
6229 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6231 form->flag=list->flag;
6232 init_unistr(&form->name, list->name);
6233 form->width=list->width;
6234 form->length=list->length;
6235 form->left=list->left;
6236 form->top=list->top;
6237 form->right=list->right;
6238 form->bottom=list->bottom;
6241 /****************************************************************************
6242 ****************************************************************************/
6244 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6246 /* POLICY_HND *handle = &q_u->handle; - notused. */
6247 uint32 level = q_u->level;
6248 NEW_BUFFER *buffer = NULL;
6249 uint32 offered = q_u->offered;
6250 uint32 *needed = &r_u->needed;
6251 uint32 *numofforms = &r_u->numofforms;
6252 uint32 numbuiltinforms;
6254 nt_forms_struct *list=NULL;
6255 nt_forms_struct *builtinlist=NULL;
6260 /* that's an [in out] buffer */
6261 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6262 buffer = r_u->buffer;
6264 DEBUG(4,("_spoolss_enumforms\n"));
6265 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6266 DEBUGADD(5,("Info level [%d]\n", level));
6268 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6269 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6270 *numofforms = get_ntforms(&list);
6271 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6272 *numofforms += numbuiltinforms;
6274 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6278 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6283 /* construct the list of form structures */
6284 for (i=0; i<numbuiltinforms; i++) {
6285 DEBUGADD(6,("Filling form number [%d]\n",i));
6286 fill_form_1(&forms_1[i], &builtinlist[i]);
6289 SAFE_FREE(builtinlist);
6291 for (; i<*numofforms; i++) {
6292 DEBUGADD(6,("Filling form number [%d]\n",i));
6293 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6298 /* check the required size. */
6299 for (i=0; i<numbuiltinforms; i++) {
6300 DEBUGADD(6,("adding form [%d]'s size\n",i));
6301 buffer_size += spoolss_size_form_1(&forms_1[i]);
6303 for (; i<*numofforms; i++) {
6304 DEBUGADD(6,("adding form [%d]'s size\n",i));
6305 buffer_size += spoolss_size_form_1(&forms_1[i]);
6308 *needed=buffer_size;
6310 if (!alloc_buffer_size(buffer, buffer_size)){
6312 return WERR_INSUFFICIENT_BUFFER;
6315 /* fill the buffer with the form structures */
6316 for (i=0; i<numbuiltinforms; i++) {
6317 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6318 smb_io_form_1("", buffer, &forms_1[i], 0);
6320 for (; i<*numofforms; i++) {
6321 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6322 smb_io_form_1("", buffer, &forms_1[i], 0);
6327 if (*needed > offered) {
6329 return WERR_INSUFFICIENT_BUFFER;
6336 SAFE_FREE(builtinlist);
6337 return WERR_UNKNOWN_LEVEL;
6342 /****************************************************************************
6343 ****************************************************************************/
6345 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6347 /* POLICY_HND *handle = &q_u->handle; - notused. */
6348 uint32 level = q_u->level;
6349 UNISTR2 *uni_formname = &q_u->formname;
6350 NEW_BUFFER *buffer = NULL;
6351 uint32 offered = q_u->offered;
6352 uint32 *needed = &r_u->needed;
6354 nt_forms_struct *list=NULL;
6355 nt_forms_struct builtin_form;
6360 int numofforms=0, i=0;
6362 /* that's an [in out] buffer */
6363 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6364 buffer = r_u->buffer;
6366 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6368 DEBUG(4,("_spoolss_getform\n"));
6369 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6370 DEBUGADD(5,("Info level [%d]\n", level));
6372 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6373 if (!foundBuiltin) {
6374 numofforms = get_ntforms(&list);
6375 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6377 if (numofforms == 0)
6384 fill_form_1(&form_1, &builtin_form);
6387 /* Check if the requested name is in the list of form structures */
6388 for (i=0; i<numofforms; i++) {
6390 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6392 if (strequal(form_name, list[i].name)) {
6393 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6394 fill_form_1(&form_1, &list[i]);
6400 if (i == numofforms) {
6404 /* check the required size. */
6406 *needed=spoolss_size_form_1(&form_1);
6408 if (!alloc_buffer_size(buffer, buffer_size)){
6409 return WERR_INSUFFICIENT_BUFFER;
6412 if (*needed > offered) {
6413 return WERR_INSUFFICIENT_BUFFER;
6416 /* fill the buffer with the form structures */
6417 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6418 smb_io_form_1("", buffer, &form_1, 0);
6424 return WERR_UNKNOWN_LEVEL;
6428 /****************************************************************************
6429 ****************************************************************************/
6431 static void fill_port_1(PORT_INFO_1 *port, char *name)
6433 init_unistr(&port->port_name, name);
6436 /****************************************************************************
6437 ****************************************************************************/
6439 static void fill_port_2(PORT_INFO_2 *port, char *name)
6441 init_unistr(&port->port_name, name);
6442 init_unistr(&port->monitor_name, "Local Monitor");
6443 init_unistr(&port->description, "Local Port");
6444 #define PORT_TYPE_WRITE 1
6445 port->port_type=PORT_TYPE_WRITE;
6449 /****************************************************************************
6451 ****************************************************************************/
6453 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6455 PORT_INFO_1 *ports=NULL;
6458 if (*lp_enumports_cmd()) {
6459 char *cmd = lp_enumports_cmd();
6466 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6468 DEBUG(10,("Running [%s]\n", command));
6469 ret = smbrun(command, &fd);
6470 DEBUG(10,("Returned [%d]\n", ret));
6474 /* Is this the best error to return here? */
6475 return WERR_ACCESS_DENIED;
6479 qlines = fd_lines_load(fd, &numlines);
6480 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6484 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6485 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6486 dos_errstr(WERR_NOMEM)));
6487 file_lines_free(qlines);
6491 for (i=0; i<numlines; i++) {
6492 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6493 fill_port_1(&ports[i], qlines[i]);
6496 file_lines_free(qlines);
6499 *returned = numlines;
6502 *returned = 1; /* Sole Samba port returned. */
6504 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6507 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6509 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6512 /* check the required size. */
6513 for (i=0; i<*returned; i++) {
6514 DEBUGADD(6,("adding port [%d]'s size\n", i));
6515 *needed += spoolss_size_port_info_1(&ports[i]);
6518 if (!alloc_buffer_size(buffer, *needed)) {
6520 return WERR_INSUFFICIENT_BUFFER;
6523 /* fill the buffer with the ports structures */
6524 for (i=0; i<*returned; i++) {
6525 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6526 smb_io_port_1("", buffer, &ports[i], 0);
6531 if (*needed > offered) {
6533 return WERR_INSUFFICIENT_BUFFER;
6539 /****************************************************************************
6541 ****************************************************************************/
6543 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6545 PORT_INFO_2 *ports=NULL;
6548 if (*lp_enumports_cmd()) {
6549 char *cmd = lp_enumports_cmd();
6558 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6559 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6561 path = lp_lockdir();
6563 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6564 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6567 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6568 ret = smbrun(command, &fd);
6569 DEBUGADD(10,("returned [%d]\n", ret));
6573 /* Is this the best error to return here? */
6574 return WERR_ACCESS_DENIED;
6578 qlines = fd_lines_load(fd, &numlines);
6579 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6583 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6584 file_lines_free(qlines);
6588 for (i=0; i<numlines; i++) {
6589 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6590 fill_port_2(&(ports[i]), qlines[i]);
6593 file_lines_free(qlines);
6596 *returned = numlines;
6602 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6605 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6607 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6610 /* check the required size. */
6611 for (i=0; i<*returned; i++) {
6612 DEBUGADD(6,("adding port [%d]'s size\n", i));
6613 *needed += spoolss_size_port_info_2(&ports[i]);
6616 if (!alloc_buffer_size(buffer, *needed)) {
6618 return WERR_INSUFFICIENT_BUFFER;
6621 /* fill the buffer with the ports structures */
6622 for (i=0; i<*returned; i++) {
6623 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6624 smb_io_port_2("", buffer, &ports[i], 0);
6629 if (*needed > offered) {
6631 return WERR_INSUFFICIENT_BUFFER;
6637 /****************************************************************************
6639 ****************************************************************************/
6641 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6643 /* UNISTR2 *name = &q_u->name; - notused. */
6644 uint32 level = q_u->level;
6645 NEW_BUFFER *buffer = NULL;
6646 uint32 offered = q_u->offered;
6647 uint32 *needed = &r_u->needed;
6648 uint32 *returned = &r_u->returned;
6650 /* that's an [in out] buffer */
6651 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6652 buffer = r_u->buffer;
6654 DEBUG(4,("_spoolss_enumports\n"));
6661 return enumports_level_1(buffer, offered, needed, returned);
6663 return enumports_level_2(buffer, offered, needed, returned);
6665 return WERR_UNKNOWN_LEVEL;
6669 /****************************************************************************
6670 ****************************************************************************/
6672 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6673 const SPOOL_PRINTER_INFO_LEVEL *info,
6674 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6675 uint32 user_switch, const SPOOL_USER_CTR *user,
6678 NT_PRINTER_INFO_LEVEL *printer = NULL;
6681 WERROR err = WERR_OK;
6683 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6684 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6688 ZERO_STRUCTP(printer);
6690 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6691 if (!convert_printer_info(info, printer, 2)) {
6692 free_a_printer(&printer, 2);
6696 /* check to see if the printer already exists */
6698 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6699 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6700 printer->info_2->sharename));
6701 free_a_printer(&printer, 2);
6702 return WERR_PRINTER_ALREADY_EXISTS;
6705 if (*lp_addprinter_cmd() )
6706 if ( !add_printer_hook(printer) ) {
6707 free_a_printer(&printer,2);
6708 return WERR_ACCESS_DENIED;
6711 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6712 printer->info_2->sharename);
6714 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6715 free_a_printer(&printer,2);
6716 return WERR_ACCESS_DENIED;
6719 /* you must be a printer admin to add a new printer */
6720 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6721 free_a_printer(&printer,2);
6722 return WERR_ACCESS_DENIED;
6726 * Do sanity check on the requested changes for Samba.
6729 if (!check_printer_ok(printer->info_2, snum)) {
6730 free_a_printer(&printer,2);
6731 return WERR_INVALID_PARAM;
6735 * When a printer is created, the drivername bound to the printer is used
6736 * to lookup previously saved driver initialization info, which is then
6737 * bound to the new printer, simulating what happens in the Windows arch.
6741 set_driver_init(printer, 2);
6743 /* A valid devmode was included, convert and link it
6745 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6747 if (!convert_devicemode(printer->info_2->printername, devmode,
6748 &printer->info_2->devmode))
6752 set_driver_init(printer, 2);
6754 /* write the ASCII on disk */
6755 err = mod_a_printer(*printer, 2);
6756 if (!W_ERROR_IS_OK(err)) {
6757 free_a_printer(&printer,2);
6761 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6762 /* Handle open failed - remove addition. */
6763 del_a_printer(printer->info_2->sharename);
6764 free_a_printer(&printer,2);
6765 return WERR_ACCESS_DENIED;
6768 update_c_setprinter(False);
6769 free_a_printer(&printer,2);
6774 /****************************************************************************
6775 ****************************************************************************/
6777 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6779 UNISTR2 *uni_srv_name = &q_u->server_name;
6780 uint32 level = q_u->level;
6781 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6782 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6783 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6784 uint32 user_switch = q_u->user_switch;
6785 SPOOL_USER_CTR *user = &q_u->user_ctr;
6786 POLICY_HND *handle = &r_u->handle;
6790 /* we don't handle yet */
6791 /* but I know what to do ... */
6792 return WERR_UNKNOWN_LEVEL;
6794 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6796 user_switch, user, handle);
6798 return WERR_UNKNOWN_LEVEL;
6802 /****************************************************************************
6803 ****************************************************************************/
6805 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6807 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
6808 uint32 level = q_u->level;
6809 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6810 WERROR err = WERR_OK;
6811 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6812 struct current_user user;
6813 fstring driver_name;
6816 ZERO_STRUCT(driver);
6818 get_current_user(&user, p);
6820 if (!convert_printer_driver_info(info, &driver, level)) {
6825 DEBUG(5,("Cleaning driver's information\n"));
6826 err = clean_up_driver_struct(driver, level, &user);
6827 if (!W_ERROR_IS_OK(err))
6830 DEBUG(5,("Moving driver to final destination\n"));
6831 if(!move_driver_to_download_area(driver, level, &user, &err)) {
6832 if (W_ERROR_IS_OK(err))
6833 err = WERR_ACCESS_DENIED;
6837 if (add_a_printer_driver(driver, level)!=0) {
6838 err = WERR_ACCESS_DENIED;
6842 /* BEGIN_ADMIN_LOG */
6845 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6846 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
6847 fstrcpy(driver_name, driver.info_3->name);
6850 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6851 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
6852 fstrcpy(driver_name, driver.info_6->name);
6858 * I think this is where he DrvUpgradePrinter() hook would be
6859 * be called in a driver's interface DLL on a Windows NT 4.0/2k
6860 * server. Right now, we just need to send ourselves a message
6861 * to update each printer bound to this driver. --jerry
6864 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
6865 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
6870 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
6871 * decide if the driver init data should be deleted. The rules are:
6872 * 1) never delete init data if it is a 9x driver, they don't use it anyway
6873 * 2) delete init data only if there is no 2k/Xp driver
6874 * 3) always delete init data
6875 * The generalized rule is always use init data from the highest order driver.
6876 * It is necessary to follow the driver install by an initialization step to
6877 * finish off this process.
6880 version = driver.info_3->cversion;
6881 else if (level == 6)
6882 version = driver.info_6->version;
6887 * 9x printer driver - never delete init data
6890 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
6895 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
6896 * there is no 2k/Xp driver init data for this driver name.
6900 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
6902 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
6904 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
6906 if (!del_driver_init(driver_name))
6907 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
6910 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
6912 free_a_printer_driver(driver1,3);
6913 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
6920 * 2k or Xp printer driver - always delete init data
6923 if (!del_driver_init(driver_name))
6924 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
6928 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
6934 free_a_printer_driver(driver, level);
6938 /********************************************************************
6939 * spoolss_addprinterdriverex
6940 ********************************************************************/
6942 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
6944 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
6945 SPOOL_R_ADDPRINTERDRIVER r_u_local;
6948 * we only support the semantics of AddPrinterDriver()
6949 * i.e. only copy files that are newer than existing ones
6952 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
6953 return WERR_ACCESS_DENIED;
6955 /* just pass the information off to _spoolss_addprinterdriver() */
6956 q_u_local.server_name_ptr = q_u->server_name_ptr;
6957 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
6958 q_u_local.level = q_u->level;
6959 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
6961 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
6964 /****************************************************************************
6965 ****************************************************************************/
6967 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6969 init_unistr(&info->name, name);
6972 /****************************************************************************
6973 ****************************************************************************/
6975 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6979 pstring short_archi;
6980 DRIVER_DIRECTORY_1 *info=NULL;
6982 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6984 if (get_short_archi(short_archi, long_archi)==False)
6985 return WERR_INVALID_ENVIRONMENT;
6987 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6990 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6992 DEBUG(4,("printer driver directory: [%s]\n", path));
6994 fill_driverdir_1(info, path);
6996 *needed += spoolss_size_driverdir_info_1(info);
6998 if (!alloc_buffer_size(buffer, *needed)) {
7000 return WERR_INSUFFICIENT_BUFFER;
7003 smb_io_driverdir_1("", buffer, info, 0);
7007 if (*needed > offered)
7008 return WERR_INSUFFICIENT_BUFFER;
7013 /****************************************************************************
7014 ****************************************************************************/
7016 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7018 UNISTR2 *name = &q_u->name;
7019 UNISTR2 *uni_environment = &q_u->environment;
7020 uint32 level = q_u->level;
7021 NEW_BUFFER *buffer = NULL;
7022 uint32 offered = q_u->offered;
7023 uint32 *needed = &r_u->needed;
7025 /* that's an [in out] buffer */
7026 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7027 buffer = r_u->buffer;
7029 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7035 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7037 return WERR_UNKNOWN_LEVEL;
7041 /****************************************************************************
7042 ****************************************************************************/
7044 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7046 POLICY_HND *handle = &q_u->handle;
7047 uint32 idx = q_u->index;
7048 uint32 in_value_len = q_u->valuesize;
7049 uint32 in_data_len = q_u->datasize;
7050 uint32 *out_max_value_len = &r_u->valuesize;
7051 uint16 **out_value = &r_u->value;
7052 uint32 *out_value_len = &r_u->realvaluesize;
7053 uint32 *out_type = &r_u->type;
7054 uint32 *out_max_data_len = &r_u->datasize;
7055 uint8 **data_out = &r_u->data;
7056 uint32 *out_data_len = &r_u->realdatasize;
7058 NT_PRINTER_INFO_LEVEL *printer = NULL;
7063 uint32 biggest_valuesize;
7064 uint32 biggest_datasize;
7066 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7072 ZERO_STRUCT(printer);
7076 *out_max_data_len=0;
7080 DEBUG(5,("spoolss_enumprinterdata\n"));
7083 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7087 if (!get_printer_snum(p,handle, &snum))
7090 result = get_a_printer(&printer, 2, lp_servicename(snum));
7091 if (!W_ERROR_IS_OK(result))
7095 * The NT machine wants to know the biggest size of value and data
7097 * cf: MSDN EnumPrinterData remark section
7099 if ( (in_value_len==0) && (in_data_len==0) ) {
7100 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7105 biggest_valuesize=0;
7108 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
7109 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
7110 if (data_len > biggest_datasize) biggest_datasize=data_len;
7112 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
7118 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
7119 *out_value_len=2*(1+biggest_valuesize);
7120 *out_data_len=biggest_datasize;
7122 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7124 free_a_printer(&printer, 2);
7129 * the value len is wrong in NT sp3
7130 * that's the number of bytes not the number of unicode chars
7133 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
7136 free_a_printer(&printer, 2);
7138 /* out_value should default to "" or else NT4 has
7139 problems unmarshalling the response */
7141 *out_max_value_len=(in_value_len/sizeof(uint16));
7142 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7145 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7147 /* the data is counted in bytes */
7148 *out_max_data_len = in_data_len;
7149 *out_data_len = in_data_len;
7150 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7153 return WERR_NO_MORE_ITEMS;
7156 free_a_printer(&printer, 2);
7160 * - counted in bytes in the request
7161 * - counted in UNICODE chars in the max reply
7162 * - counted in bytes in the real size
7164 * take a pause *before* coding not *during* coding
7167 *out_max_value_len=(in_value_len/sizeof(uint16));
7168 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
7173 *out_value_len = (uint32)rpcstr_push((char *)*out_value,value, in_value_len, 0);
7177 /* the data is counted in bytes */
7178 *out_max_data_len=in_data_len;
7179 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
7184 memcpy(*data_out, data, (size_t)data_len);
7185 *out_data_len=data_len;
7192 /****************************************************************************
7193 ****************************************************************************/
7195 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7197 POLICY_HND *handle = &q_u->handle;
7198 UNISTR2 *value = &q_u->value;
7199 uint32 type = q_u->type;
7200 uint8 *data = q_u->data;
7201 uint32 real_len = q_u->real_len;
7203 NT_PRINTER_INFO_LEVEL *printer = NULL;
7204 NT_PRINTER_PARAM *param = NULL, old_param;
7206 WERROR status = WERR_OK;
7207 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7209 DEBUG(5,("spoolss_setprinterdata\n"));
7212 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7216 if (!get_printer_snum(p,handle, &snum))
7219 ZERO_STRUCT(old_param);
7222 * Access check : NT returns "access denied" if you make a
7223 * SetPrinterData call without the necessary privildge.
7224 * we were originally returning OK if nothing changed
7225 * which made Win2k issue **a lot** of SetPrinterData
7226 * when connecting to a printer --jerry
7229 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7230 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7231 status = WERR_ACCESS_DENIED;
7235 /* Check if we are making any changes or not. Return true if
7236 nothing is actually changing. This is not needed anymore but
7237 has been left in as an optimization to keep from from
7238 writing to disk as often --jerry */
7240 status = get_a_printer(&printer, 2, lp_servicename(snum));
7241 if (!W_ERROR_IS_OK(status))
7244 convert_specific_param(¶m, value , type, data, real_len);
7246 unlink_specific_param_if_exist(printer->info_2, param);
7249 * When client side code sets a magic printer data key, detect it and save
7250 * the current printer data and the magic key's data (its the DEVMODE) for
7251 * future printer/driver initializations.
7253 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
7255 * Set devmode and printer initialization info
7257 status = save_driver_init(printer, 2, param);
7260 add_a_specific_param(printer->info_2, ¶m);
7261 status = mod_a_printer(*printer, 2);
7265 free_a_printer(&printer, 2);
7267 free_nt_printer_param(¶m);
7268 SAFE_FREE(old_param.data);
7273 /****************************************************************************
7274 ****************************************************************************/
7276 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7278 POLICY_HND *handle = &q_u->handle;
7279 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7282 DEBUG(5,("_spoolss_resetprinter\n"));
7285 * All we do is to check to see if the handle and queue is valid.
7286 * This call really doesn't mean anything to us because we only
7287 * support RAW printing. --jerry
7291 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7295 if (!get_printer_snum(p,handle, &snum))
7299 /* blindly return success */
7304 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7306 POLICY_HND *handle = &q_u->handle;
7307 UNISTR2 *value = &q_u->valuename;
7309 NT_PRINTER_INFO_LEVEL *printer = NULL;
7310 NT_PRINTER_PARAM param;
7312 WERROR status = WERR_OK;
7313 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7315 DEBUG(5,("spoolss_deleteprinterdata\n"));
7318 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7322 if (!get_printer_snum(p, handle, &snum))
7325 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7326 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7327 return WERR_ACCESS_DENIED;
7330 status = get_a_printer(&printer, 2, lp_servicename(snum));
7331 if (!W_ERROR_IS_OK(status))
7334 ZERO_STRUCTP(¶m);
7335 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
7337 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
7338 status = WERR_INVALID_PARAM;
7340 status = mod_a_printer(*printer, 2);
7342 free_a_printer(&printer, 2);
7346 /****************************************************************************
7347 ****************************************************************************/
7349 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7351 POLICY_HND *handle = &q_u->handle;
7352 /* uint32 level = q_u->level; - notused. */
7353 FORM *form = &q_u->form;
7354 nt_forms_struct tmpForm;
7356 WERROR status = WERR_OK;
7357 NT_PRINTER_INFO_LEVEL *printer = NULL;
7360 nt_forms_struct *list=NULL;
7361 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7363 DEBUG(5,("spoolss_addform\n"));
7366 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7370 if (!get_printer_snum(p,handle, &snum))
7373 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7374 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7375 status = WERR_ACCESS_DENIED;
7379 /* can't add if builtin */
7380 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7381 return WERR_ALREADY_EXISTS;
7384 count=get_ntforms(&list);
7385 if(!add_a_form(&list, form, &count))
7387 write_ntforms(&list, count);
7390 * ChangeID must always be set
7393 status = get_a_printer(&printer, 2, lp_servicename(snum));
7394 if (!W_ERROR_IS_OK(status))
7397 status = mod_a_printer(*printer, 2);
7398 if (!W_ERROR_IS_OK(status))
7402 free_a_printer(&printer, 2);
7408 /****************************************************************************
7409 ****************************************************************************/
7411 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7413 POLICY_HND *handle = &q_u->handle;
7414 UNISTR2 *form_name = &q_u->name;
7415 nt_forms_struct tmpForm;
7417 WERROR ret = WERR_OK;
7418 nt_forms_struct *list=NULL;
7419 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7421 WERROR status = WERR_OK;
7422 NT_PRINTER_INFO_LEVEL *printer = NULL;
7424 DEBUG(5,("spoolss_deleteform\n"));
7427 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7431 if (!get_printer_snum(p, handle, &snum))
7434 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7435 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
7436 return WERR_ACCESS_DENIED;
7439 /* can't delete if builtin */
7440 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7441 return WERR_INVALID_PARAM;
7444 count = get_ntforms(&list);
7445 if(!delete_a_form(&list, form_name, &count, &ret))
7446 return WERR_INVALID_PARAM;
7449 * ChangeID must always be set
7452 status = get_a_printer(&printer, 2, lp_servicename(snum));
7453 if (!W_ERROR_IS_OK(status))
7456 status = mod_a_printer(*printer, 2);
7457 if (!W_ERROR_IS_OK(status))
7461 free_a_printer(&printer, 2);
7467 /****************************************************************************
7468 ****************************************************************************/
7470 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7472 POLICY_HND *handle = &q_u->handle;
7473 FORM *form = &q_u->form;
7474 nt_forms_struct tmpForm;
7476 WERROR status = WERR_OK;
7477 NT_PRINTER_INFO_LEVEL *printer = NULL;
7480 nt_forms_struct *list=NULL;
7481 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7483 DEBUG(5,("spoolss_setform\n"));
7486 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7490 if (!get_printer_snum(p, handle, &snum))
7493 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7494 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7495 return WERR_ACCESS_DENIED;
7498 /* can't set if builtin */
7499 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7500 return WERR_INVALID_PARAM;
7503 count=get_ntforms(&list);
7504 update_a_form(&list, form, count);
7505 write_ntforms(&list, count);
7508 * ChangeID must always be set
7511 status = get_a_printer(&printer, 2, lp_servicename(snum));
7512 if (!W_ERROR_IS_OK(status))
7515 status = mod_a_printer(*printer, 2);
7516 if (!W_ERROR_IS_OK(status))
7520 free_a_printer(&printer, 2);
7526 /****************************************************************************
7527 enumprintprocessors level 1.
7528 ****************************************************************************/
7530 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7532 PRINTPROCESSOR_1 *info_1=NULL;
7534 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7539 init_unistr(&info_1->name, "winprint");
7541 *needed += spoolss_size_printprocessor_info_1(info_1);
7543 if (!alloc_buffer_size(buffer, *needed))
7544 return WERR_INSUFFICIENT_BUFFER;
7546 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7550 if (*needed > offered) {
7552 return WERR_INSUFFICIENT_BUFFER;
7558 /****************************************************************************
7559 ****************************************************************************/
7561 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7563 uint32 level = q_u->level;
7564 NEW_BUFFER *buffer = NULL;
7565 uint32 offered = q_u->offered;
7566 uint32 *needed = &r_u->needed;
7567 uint32 *returned = &r_u->returned;
7569 /* that's an [in out] buffer */
7570 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7571 buffer = r_u->buffer;
7573 DEBUG(5,("spoolss_enumprintprocessors\n"));
7576 * Enumerate the print processors ...
7578 * Just reply with "winprint", to keep NT happy
7579 * and I can use my nice printer checker.
7587 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7589 return WERR_UNKNOWN_LEVEL;
7593 /****************************************************************************
7594 enumprintprocdatatypes level 1.
7595 ****************************************************************************/
7597 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7599 PRINTPROCDATATYPE_1 *info_1=NULL;
7601 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7606 init_unistr(&info_1->name, "RAW");
7608 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7610 if (!alloc_buffer_size(buffer, *needed))
7611 return WERR_INSUFFICIENT_BUFFER;
7613 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7617 if (*needed > offered) {
7619 return WERR_INSUFFICIENT_BUFFER;
7625 /****************************************************************************
7626 ****************************************************************************/
7628 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7630 uint32 level = q_u->level;
7631 NEW_BUFFER *buffer = NULL;
7632 uint32 offered = q_u->offered;
7633 uint32 *needed = &r_u->needed;
7634 uint32 *returned = &r_u->returned;
7636 /* that's an [in out] buffer */
7637 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7638 buffer = r_u->buffer;
7640 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7647 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7649 return WERR_UNKNOWN_LEVEL;
7653 /****************************************************************************
7654 enumprintmonitors level 1.
7655 ****************************************************************************/
7657 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7659 PRINTMONITOR_1 *info_1=NULL;
7661 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7666 init_unistr(&info_1->name, "Local Port");
7668 *needed += spoolss_size_printmonitor_info_1(info_1);
7670 if (!alloc_buffer_size(buffer, *needed))
7671 return WERR_INSUFFICIENT_BUFFER;
7673 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7677 if (*needed > offered) {
7679 return WERR_INSUFFICIENT_BUFFER;
7685 /****************************************************************************
7686 enumprintmonitors level 2.
7687 ****************************************************************************/
7689 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7691 PRINTMONITOR_2 *info_2=NULL;
7693 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7698 init_unistr(&info_2->name, "Local Port");
7699 init_unistr(&info_2->environment, "Windows NT X86");
7700 init_unistr(&info_2->dll_name, "localmon.dll");
7702 *needed += spoolss_size_printmonitor_info_2(info_2);
7704 if (!alloc_buffer_size(buffer, *needed))
7705 return WERR_INSUFFICIENT_BUFFER;
7707 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7711 if (*needed > offered) {
7713 return WERR_INSUFFICIENT_BUFFER;
7719 /****************************************************************************
7720 ****************************************************************************/
7722 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7724 uint32 level = q_u->level;
7725 NEW_BUFFER *buffer = NULL;
7726 uint32 offered = q_u->offered;
7727 uint32 *needed = &r_u->needed;
7728 uint32 *returned = &r_u->returned;
7730 /* that's an [in out] buffer */
7731 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7732 buffer = r_u->buffer;
7734 DEBUG(5,("spoolss_enumprintmonitors\n"));
7737 * Enumerate the print monitors ...
7739 * Just reply with "Local Port", to keep NT happy
7740 * and I can use my nice printer checker.
7748 return enumprintmonitors_level_1(buffer, offered, needed, returned);
7750 return enumprintmonitors_level_2(buffer, offered, needed, returned);
7752 return WERR_UNKNOWN_LEVEL;
7756 /****************************************************************************
7757 ****************************************************************************/
7759 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7763 JOB_INFO_1 *info_1=NULL;
7765 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
7767 if (info_1 == NULL) {
7772 for (i=0; i<count && found==False; i++) {
7773 if (queue[i].job==(int)jobid)
7780 /* NT treats not found as bad param... yet another bad choice */
7781 return WERR_INVALID_PARAM;
7784 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
7788 *needed += spoolss_size_job_info_1(info_1);
7790 if (!alloc_buffer_size(buffer, *needed)) {
7792 return WERR_INSUFFICIENT_BUFFER;
7795 smb_io_job_info_1("", buffer, info_1, 0);
7799 if (*needed > offered)
7800 return WERR_INSUFFICIENT_BUFFER;
7805 /****************************************************************************
7806 ****************************************************************************/
7808 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7813 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
7815 DEVICEMODE *devmode = NULL;
7817 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
7819 ZERO_STRUCTP(info_2);
7821 if (info_2 == NULL) {
7826 for (i=0; i<count && found==False; i++) {
7827 if (queue[i].job==(int)jobid)
7832 /* NT treats not found as bad param... yet another bad
7834 ret = WERR_INVALID_PARAM;
7838 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
7839 if (!W_ERROR_IS_OK(ret))
7841 if (construct_dev_mode(snum) == NULL) {
7846 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
7848 *needed += spoolss_size_job_info_2(info_2);
7850 if (!alloc_buffer_size(buffer, *needed)) {
7851 ret = WERR_INSUFFICIENT_BUFFER;
7855 smb_io_job_info_2("", buffer, info_2, 0);
7857 if (*needed > offered) {
7858 ret = WERR_INSUFFICIENT_BUFFER;
7865 /* Cleanup allocated memory */
7868 free_job_info_2(info_2); /* Also frees devmode */
7870 free_a_printer(&ntprinter, 2);
7875 /****************************************************************************
7876 ****************************************************************************/
7878 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
7880 POLICY_HND *handle = &q_u->handle;
7881 uint32 jobid = q_u->jobid;
7882 uint32 level = q_u->level;
7883 NEW_BUFFER *buffer = NULL;
7884 uint32 offered = q_u->offered;
7885 uint32 *needed = &r_u->needed;
7889 print_queue_struct *queue=NULL;
7890 print_status_struct prt_status;
7892 /* that's an [in out] buffer */
7893 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7894 buffer = r_u->buffer;
7896 DEBUG(5,("spoolss_getjob\n"));
7900 if (!get_printer_snum(p, handle, &snum))
7903 count = print_queue_status(snum, &queue, &prt_status);
7905 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7906 count, prt_status.status, prt_status.message));
7910 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
7912 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
7915 return WERR_UNKNOWN_LEVEL;
7919 /********************************************************************
7920 * spoolss_getprinterdataex
7921 ********************************************************************/
7923 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
7925 POLICY_HND *handle = &q_u->handle;
7926 uint32 in_size = q_u->size;
7927 uint32 *type = &r_u->type;
7928 uint32 *out_size = &r_u->size;
7929 uint8 **data = &r_u->data;
7930 uint32 *needed = &r_u->needed;
7933 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7936 DEBUG(4,("_spoolss_getprinterdataex\n"));
7938 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7939 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
7941 /* in case of problem, return some default values */
7948 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
7950 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7955 /* Is the handle to a printer or to the server? */
7957 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
7959 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7960 return WERR_INVALID_PARAM;
7965 * From MSDN documentation of GetPrinterDataEx: pass request
7966 * to GetPrinterData if key is "PrinterDriverData". This is
7967 * the only key we really support. Other keys to implement:
7973 if (strcmp(key, "PrinterDriverData") != 0)
7974 return WERR_BADFILE;
7976 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7977 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
7978 type, data, needed, in_size);
7983 DEBUG(5, ("value not found, allocating %d\n", *out_size));
7985 /* reply this param doesn't exist */
7987 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
7993 return WERR_INVALID_PARAM;
7996 if (*needed > *out_size)
7997 return WERR_MORE_DATA;
8002 /********************************************************************
8003 * spoolss_setprinterdata
8004 ********************************************************************/
8006 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8008 SPOOL_Q_SETPRINTERDATA q_u_local;
8009 SPOOL_R_SETPRINTERDATA r_u_local;
8012 DEBUG(4,("_spoolss_setprinterdataex\n"));
8014 /* From MSDN documentation of SetPrinterDataEx: pass request to
8015 SetPrinterData if key is "PrinterDriverData" */
8017 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8019 if (strcmp(key, "PrinterDriverData") != 0)
8020 return WERR_INVALID_PARAM;
8022 ZERO_STRUCT(q_u_local);
8023 ZERO_STRUCT(r_u_local);
8025 /* make a copy to call _spoolss_setprinterdata() */
8027 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
8028 copy_unistr2(&q_u_local.value, &q_u->value);
8029 q_u_local.type = q_u->type;
8030 q_u_local.max_len = q_u->max_len;
8031 q_u_local.data = q_u->data;
8032 q_u_local.real_len = q_u->real_len;
8033 q_u_local.numeric_data = q_u->numeric_data;
8035 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
8039 /********************************************************************
8040 * spoolss_deleteprinterdataex
8041 ********************************************************************/
8043 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8045 SPOOL_Q_DELETEPRINTERDATA q_u_local;
8046 SPOOL_R_DELETEPRINTERDATA r_u_local;
8049 /* From MSDN documentation of SetPrinterDataEx: pass request to
8050 SetPrinterData if key is "PrinterDriverData" */
8052 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8054 if (strcmp(key, "PrinterDriverData") != 0)
8055 return WERR_INVALID_PARAM;
8057 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
8058 copy_unistr2(&q_u_local.valuename, &q_u->valuename);
8060 return _spoolss_deleteprinterdata( p, &q_u_local, &r_u_local );
8066 /********************************************************************
8067 * spoolss_enumprinterkey
8068 ********************************************************************/
8070 /* constants for EnumPrinterKey() */
8071 #define ENUMERATED_KEY_SIZE 19
8073 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8076 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
8079 char *PrinterKey = "PrinterDriverData";
8081 DEBUG(4,("_spoolss_enumprinterkey\n"));
8083 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8086 * we only support enumating all keys (key == "")
8087 * Of course, the only key we support is the "PrinterDriverData"
8090 if (strlen(key) == 0)
8092 r_u->needed = ENUMERATED_KEY_SIZE *2;
8093 if (q_u->size < r_u->needed)
8094 return WERR_MORE_DATA;
8097 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
8099 enumkeys[i] = (uint16)(*ptr);
8103 /* tag of with 2 '\0's */
8104 enumkeys[i++] = '\0';
8107 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
8108 return WERR_BADFILE;
8113 /* The "PrinterDriverData" key should have no subkeys */
8114 if (strcmp(key, PrinterKey) == 0)
8117 if (q_u->size < r_u->needed)
8118 return WERR_MORE_DATA;
8120 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
8121 return WERR_BADFILE;
8127 /* The return value for an unknown key is documented in MSDN
8128 EnumPrinterKey description */
8129 return WERR_BADFILE;
8132 /********************************************************************
8133 * spoolss_deleteprinterkey
8134 ********************************************************************/
8136 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8138 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8142 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
8146 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8148 if (strcmp(key, "PrinterDriverData") != 0)
8149 return WERR_INVALID_PARAM;
8152 * this is what 2k returns when you try to delete the "PrinterDriverData"
8156 return WERR_ACCESS_DENIED;
8160 /********************************************************************
8161 * spoolss_enumprinterdataex
8162 ********************************************************************/
8164 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8166 POLICY_HND *handle = &q_u->handle;
8167 uint32 in_size = q_u->size;
8170 NT_PRINTER_INFO_LEVEL *printer = NULL;
8171 PRINTER_ENUM_VALUES *enum_values = NULL;
8173 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8182 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8185 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8191 * The only key we support is "PrinterDriverData". This should return
8192 > an array of all the key/value pairs returned by EnumPrinterDataSee
8193 * _spoolss_getprinterdataex() for details --jerry
8196 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8197 if (strcmp(key, "PrinterDriverData") != 0)
8199 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8200 return WERR_INVALID_PARAM;
8204 if (!get_printer_snum(p,handle, &snum))
8207 ZERO_STRUCT(printer);
8208 result = get_a_printer(&printer, 2, lp_servicename(snum));
8209 if (!W_ERROR_IS_OK(result))
8214 * loop through all params and build the array to pass
8215 * back to the client
8222 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
8224 PRINTER_ENUM_VALUES *ptr;
8227 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
8229 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
8231 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
8232 result = WERR_NOMEM;
8238 init_unistr(&enum_values[num_entries].valuename, value);
8239 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
8240 enum_values[num_entries].type = type;
8242 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
8243 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
8244 result = WERR_NOMEM;
8247 memcpy(enum_values[num_entries].data, data, data_len);
8248 enum_values[num_entries].data_len = data_len + add_len;
8250 /* keep track of the size of the array in bytes */
8252 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
8258 r_u->needed = needed;
8259 r_u->returned = num_entries;
8261 if (needed > in_size) {
8262 result = WERR_MORE_DATA;
8266 /* copy data into the reply */
8268 r_u->ctr.size = r_u->needed;
8269 r_u->ctr.size_of_array = r_u->returned;
8270 r_u->ctr.values = enum_values;
8275 free_a_printer(&printer, 2);
8280 /****************************************************************************
8281 ****************************************************************************/
8283 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8285 init_unistr(&info->name, name);
8288 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8289 UNISTR2 *environment,
8296 pstring short_archi;
8297 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8299 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8301 if (get_short_archi(short_archi, long_archi)==False)
8302 return WERR_INVALID_ENVIRONMENT;
8304 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8307 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8309 fill_printprocessordirectory_1(info, path);
8311 *needed += spoolss_size_printprocessordirectory_info_1(info);
8313 if (!alloc_buffer_size(buffer, *needed)) {
8315 return WERR_INSUFFICIENT_BUFFER;
8318 smb_io_printprocessordirectory_1("", buffer, info, 0);
8322 if (*needed > offered)
8323 return WERR_INSUFFICIENT_BUFFER;
8328 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8330 uint32 level = q_u->level;
8331 NEW_BUFFER *buffer = NULL;
8332 uint32 offered = q_u->offered;
8333 uint32 *needed = &r_u->needed;
8336 /* that's an [in out] buffer */
8337 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8338 buffer = r_u->buffer;
8340 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8346 result = getprintprocessordirectory_level_1
8347 (&q_u->name, &q_u->environment, buffer, offered, needed);
8349 result = WERR_UNKNOWN_LEVEL;