a 0 length printer data value is not a memory allocation error; fix CR601
[Samba/gbeck.git] / source3 / rpc_server / srv_spoolss_nt.c
blob279bbb86ffce22c23cf0715ee62cdd58b7a7308f
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2002,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
36 #endif
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
40 #define PRINTER_HANDLE_IS_PRINTER 0
41 #define PRINTER_HANDLE_IS_PRINTSERVER 1
43 /* Table to map the driver version */
44 /* to OS */
45 static const char * drv_ver_to_os[] = {
46 "WIN9X", /* driver version/cversion 0 */
47 "", /* unused ? */
48 "WINNT", /* driver version/cversion 2 */
49 "WIN2K", /* driver version/cversion 3 */
52 struct table_node {
53 const char *long_archi;
54 const char *short_archi;
55 int version;
59 /* structure to store the printer handles */
60 /* and a reference to what it's pointing to */
61 /* and the notify info asked about */
62 /* that's the central struct */
63 typedef struct _Printer{
64 struct _Printer *prev, *next;
65 BOOL document_started;
66 BOOL page_started;
67 uint32 jobid; /* jobid in printing backend */
68 BOOL printer_type;
69 union {
70 fstring handlename;
71 fstring printerservername;
72 } dev;
73 uint32 type;
74 uint32 access_granted;
75 struct {
76 uint32 flags;
77 uint32 options;
78 fstring localmachine;
79 uint32 printerlocal;
80 SPOOL_NOTIFY_OPTION *option;
81 POLICY_HND client_hnd;
82 uint32 client_connected;
83 uint32 change;
84 } notify;
85 struct {
86 fstring machine;
87 fstring user;
88 } client;
90 /* devmode sent in the OpenPrinter() call */
91 NT_DEVICEMODE *nt_devmode;
93 } Printer_entry;
95 static Printer_entry *printers_list;
97 typedef struct _counter_printer_0 {
98 ubi_dlNode Next;
99 ubi_dlNode Prev;
101 int snum;
102 uint32 counter;
103 } counter_printer_0;
105 static ubi_dlList counter_list;
107 static struct cli_state notify_cli; /* print notify back-channel */
108 static uint32 smb_connections=0;
111 /* in printing/nt_printing.c */
113 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
115 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
116 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
118 /* translate between internal status numbers and NT status numbers */
119 static int nt_printj_status(int v)
121 switch (v) {
122 case LPQ_QUEUED:
123 return 0;
124 case LPQ_PAUSED:
125 return JOB_STATUS_PAUSED;
126 case LPQ_SPOOLING:
127 return JOB_STATUS_SPOOLING;
128 case LPQ_PRINTING:
129 return JOB_STATUS_PRINTING;
130 case LPQ_ERROR:
131 return JOB_STATUS_ERROR;
132 case LPQ_DELETING:
133 return JOB_STATUS_DELETING;
134 case LPQ_OFFLINE:
135 return JOB_STATUS_OFFLINE;
136 case LPQ_PAPEROUT:
137 return JOB_STATUS_PAPEROUT;
138 case LPQ_PRINTED:
139 return JOB_STATUS_PRINTED;
140 case LPQ_DELETED:
141 return JOB_STATUS_DELETED;
142 case LPQ_BLOCKED:
143 return JOB_STATUS_BLOCKED;
144 case LPQ_USER_INTERVENTION:
145 return JOB_STATUS_USER_INTERVENTION;
147 return 0;
150 static int nt_printq_status(int v)
152 switch (v) {
153 case LPQ_PAUSED:
154 return PRINTER_STATUS_PAUSED;
155 case LPQ_QUEUED:
156 case LPQ_SPOOLING:
157 case LPQ_PRINTING:
158 return 0;
160 return 0;
163 /****************************************************************************
164 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
165 ****************************************************************************/
167 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
169 if (*pp == NULL)
170 return;
172 SAFE_FREE((*pp)->ctr.type);
173 SAFE_FREE(*pp);
176 /***************************************************************************
177 Disconnect from the client
178 ****************************************************************************/
180 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
182 WERROR result;
185 * Tell the specific printing tdb we no longer want messages for this printer
186 * by deregistering our PID.
189 if (!print_notify_deregister_pid(snum))
190 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
192 /* weird if the test succeds !!! */
193 if (smb_connections==0) {
194 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
195 return;
198 result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
200 if (!W_ERROR_IS_OK(result))
201 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
202 dos_errstr(result)));
204 /* if it's the last connection, deconnect the IPC$ share */
205 if (smb_connections==1) {
206 cli_nt_session_close(&notify_cli);
207 cli_ulogoff(&notify_cli);
208 cli_shutdown(&notify_cli);
209 message_deregister(MSG_PRINTER_NOTIFY2);
211 /* Tell the connections db we're no longer interested in
212 * printer notify messages. */
214 register_message_flags( False, FLAG_MSG_PRINTING );
217 smb_connections--;
220 /****************************************************************************
221 Functions to free a printer entry datastruct.
222 ****************************************************************************/
224 static void free_printer_entry(void *ptr)
226 Printer_entry *Printer = (Printer_entry *)ptr;
228 if (Printer->notify.client_connected==True) {
229 int snum = -1;
231 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
232 snum = -1;
233 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
234 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
235 snum = print_queue_snum(Printer->dev.handlename);
236 if (snum != -1)
237 srv_spoolss_replycloseprinter(snum,
238 &Printer->notify.client_hnd);
242 Printer->notify.flags=0;
243 Printer->notify.options=0;
244 Printer->notify.localmachine[0]='\0';
245 Printer->notify.printerlocal=0;
246 free_spool_notify_option(&Printer->notify.option);
247 Printer->notify.option=NULL;
248 Printer->notify.client_connected=False;
250 free_nt_devicemode( &Printer->nt_devmode );
252 /* Remove from the internal list. */
253 DLIST_REMOVE(printers_list, Printer);
255 SAFE_FREE(Printer);
258 /****************************************************************************
259 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
260 ****************************************************************************/
262 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
264 SPOOL_NOTIFY_OPTION *new_sp = NULL;
266 if (!sp)
267 return NULL;
269 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
270 if (!new_sp)
271 return NULL;
273 *new_sp = *sp;
275 if (sp->ctr.count) {
276 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
278 if (!new_sp->ctr.type) {
279 SAFE_FREE(new_sp);
280 return NULL;
284 return new_sp;
287 /****************************************************************************
288 find printer index by handle
289 ****************************************************************************/
291 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
293 Printer_entry *find_printer = NULL;
295 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
296 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
297 return NULL;
300 return find_printer;
303 /****************************************************************************
304 Close printer index by handle.
305 ****************************************************************************/
307 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
309 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
311 if (!Printer) {
312 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
313 return False;
316 close_policy_hnd(p, hnd);
318 return True;
321 /****************************************************************************
322 Delete a printer given a handle.
323 ****************************************************************************/
325 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
327 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
329 if (!Printer) {
330 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
331 return WERR_BADFID;
335 * It turns out that Windows allows delete printer on a handle
336 * opened by an admin user, then used on a pipe handle created
337 * by an anonymous user..... but they're working on security.... riiight !
338 * JRA.
341 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
342 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
343 return WERR_ACCESS_DENIED;
346 #if 0
347 /* Check calling user has permission to delete printer. Note that
348 since we set the snum parameter to -1 only administrators can
349 delete the printer. This stops people with the Full Control
350 permission from deleting the printer. */
352 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
353 DEBUG(3, ("printer delete denied by security descriptor\n"));
354 return WERR_ACCESS_DENIED;
356 #endif
358 if (del_a_printer(Printer->dev.handlename) != 0) {
359 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
360 return WERR_BADFID;
363 if (*lp_deleteprinter_cmd()) {
365 char *cmd = lp_deleteprinter_cmd();
366 pstring command;
367 int ret;
368 int i;
370 /* Printer->dev.handlename equals portname equals sharename */
371 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
372 Printer->dev.handlename);
374 DEBUG(10,("Running [%s]\n", command));
375 ret = smbrun(command, NULL);
376 if (ret != 0) {
377 return WERR_BADFID; /* What to return here? */
379 DEBUGADD(10,("returned [%d]\n", ret));
381 /* Send SIGHUP to process group... is there a better way? */
382 kill(0, SIGHUP);
384 /* go ahead and re-read the services immediately */
385 reload_services( False );
387 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
388 return WERR_ACCESS_DENIED;
391 return WERR_OK;
394 /****************************************************************************
395 Return the snum of a printer corresponding to an handle.
396 ****************************************************************************/
398 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
400 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
402 if (!Printer) {
403 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
404 return False;
407 switch (Printer->printer_type) {
408 case PRINTER_HANDLE_IS_PRINTER:
409 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
410 *number = print_queue_snum(Printer->dev.handlename);
411 return (*number != -1);
412 case PRINTER_HANDLE_IS_PRINTSERVER:
413 return False;
414 default:
415 return False;
419 /****************************************************************************
420 Set printer handle type.
421 Check if it's \\server or \\server\printer
422 ****************************************************************************/
424 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
426 DEBUG(3,("Setting printer type=%s\n", handlename));
428 if ( strlen(handlename) < 3 ) {
429 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
430 return False;
433 /* it's a print server */
434 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
435 DEBUGADD(4,("Printer is a print server\n"));
436 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
438 /* it's a printer */
439 else {
440 DEBUGADD(4,("Printer is a printer\n"));
441 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
444 return True;
447 /****************************************************************************
448 Set printer handle name.
449 ****************************************************************************/
451 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
453 int snum;
454 int n_services=lp_numservices();
455 char *aprinter;
456 fstring sname;
457 BOOL found=False;
459 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
461 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
462 ZERO_STRUCT(Printer->dev.printerservername);
463 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
464 return True;
467 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
468 return False;
470 if (*handlename=='\\') {
471 aprinter=strchr_m(handlename+2, '\\');
472 aprinter++;
474 else {
475 aprinter=handlename;
478 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
481 * The original code allowed smbd to store a printer name that
482 * was different from the share name. This is not possible
483 * anymore, so I've simplified this loop greatly. Here
484 * we are just verifying that the printer name is a valid
485 * printer service defined in smb.conf
486 * --jerry [Fri Feb 15 11:17:46 CST 2002]
489 for (snum=0; snum<n_services; snum++) {
491 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
492 continue;
494 fstrcpy(sname, lp_servicename(snum));
496 DEBUGADD(5,("share:%s\n",sname));
498 if (! StrCaseCmp(sname, aprinter)) {
499 found = True;
500 break;
506 if (!found) {
507 DEBUGADD(4,("Printer not found\n"));
508 return False;
511 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
513 ZERO_STRUCT(Printer->dev.handlename);
514 fstrcpy(Printer->dev.handlename, sname);
516 return True;
519 /****************************************************************************
520 Find first available printer slot. creates a printer handle for you.
521 ****************************************************************************/
523 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
525 Printer_entry *new_printer;
527 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
529 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
530 return False;
532 ZERO_STRUCTP(new_printer);
534 new_printer->notify.option=NULL;
536 /* Add to the internal list. */
537 DLIST_ADD(printers_list, new_printer);
539 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
540 SAFE_FREE(new_printer);
541 return False;
544 if (!set_printer_hnd_printertype(new_printer, name)) {
545 close_printer_handle(p, hnd);
546 return False;
549 if (!set_printer_hnd_name(new_printer, name)) {
550 close_printer_handle(p, hnd);
551 return False;
554 new_printer->access_granted = access_granted;
556 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
558 return True;
561 /****************************************************************************
562 Allocate more memory for a BUFFER.
563 ****************************************************************************/
565 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
567 prs_struct *ps;
568 uint32 extra_space;
569 uint32 old_offset;
571 ps= &buffer->prs;
573 /* damn, I'm doing the reverse operation of prs_grow() :) */
574 if (buffer_size < prs_data_size(ps))
575 extra_space=0;
576 else
577 extra_space = buffer_size - prs_data_size(ps);
580 * save the offset and move to the end of the buffer
581 * prs_grow() checks the extra_space against the offset
583 old_offset=prs_offset(ps);
584 prs_set_offset(ps, prs_data_size(ps));
586 if (!prs_grow(ps, extra_space))
587 return False;
589 prs_set_offset(ps, old_offset);
591 buffer->string_at_end=prs_data_size(ps);
593 return True;
596 /***************************************************************************
597 check to see if the client motify handle is monitoring the notification
598 given by (notify_type, notify_field).
599 **************************************************************************/
601 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
602 uint16 notify_field)
604 return True;
607 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
608 uint16 notify_field)
610 SPOOL_NOTIFY_OPTION *option = p->notify.option;
611 uint32 i, j;
614 * Flags should always be zero when the change notify
615 * is registered by the cliebnt's spooler. A user Win32 app
616 * might use the flags though instead of the NOTIFY_OPTION_INFO
617 * --jerry
620 if (p->notify.flags)
621 return is_monitoring_event_flags(
622 p->notify.flags, notify_type, notify_field);
624 for (i = 0; i < option->count; i++) {
626 /* Check match for notify_type */
628 if (option->ctr.type[i].type != notify_type)
629 continue;
631 /* Check match for field */
633 for (j = 0; j < option->ctr.type[i].count; j++) {
634 if (option->ctr.type[i].fields[j] == notify_field) {
635 return True;
640 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
641 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
642 p->dev.handlename : p->dev.printerservername,
643 notify_type, notify_field));
645 return False;
648 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
650 static void notify_one_value(struct spoolss_notify_msg *msg,
651 SPOOL_NOTIFY_INFO_DATA *data,
652 TALLOC_CTX *mem_ctx)
654 data->notify_data.value[0] = msg->notify.value[0];
655 data->notify_data.value[1] = 0;
658 static void notify_string(struct spoolss_notify_msg *msg,
659 SPOOL_NOTIFY_INFO_DATA *data,
660 TALLOC_CTX *mem_ctx)
662 UNISTR2 unistr;
664 /* The length of the message includes the trailing \0 */
666 init_unistr2(&unistr, msg->notify.data, msg->len);
668 data->notify_data.data.length = msg->len * 2;
669 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
671 if (!data->notify_data.data.string) {
672 data->notify_data.data.length = 0;
673 return;
676 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
679 static void notify_system_time(struct spoolss_notify_msg *msg,
680 SPOOL_NOTIFY_INFO_DATA *data,
681 TALLOC_CTX *mem_ctx)
683 SYSTEMTIME systime;
684 prs_struct ps;
686 if (msg->len != sizeof(time_t)) {
687 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
688 msg->len));
689 return;
692 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
693 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
694 return;
697 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
698 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
699 return;
702 if (!spoolss_io_system_time("", &ps, 0, &systime))
703 return;
705 data->notify_data.data.length = prs_offset(&ps);
706 data->notify_data.data.string =
707 talloc(mem_ctx, prs_offset(&ps));
709 memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
711 prs_mem_free(&ps);
714 struct notify2_message_table {
715 const char *name;
716 void (*fn)(struct spoolss_notify_msg *msg,
717 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
720 static struct notify2_message_table printer_notify_table[] = {
721 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
722 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
723 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
724 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
725 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
726 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
727 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
728 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
729 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
730 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
731 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
732 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
733 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
734 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
735 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
736 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
737 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
738 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
739 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
742 static struct notify2_message_table job_notify_table[] = {
743 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
744 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
745 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
746 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
747 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
748 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
749 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
750 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
751 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
752 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
753 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
754 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
755 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
756 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
757 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
758 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
759 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
760 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
761 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
762 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
763 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
764 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
765 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
766 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
770 /***********************************************************************
771 Allocate talloc context for container object
772 **********************************************************************/
774 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
776 if ( !ctr )
777 return;
779 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
781 return;
784 /***********************************************************************
785 release all allocated memory and zero out structure
786 **********************************************************************/
788 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
790 if ( !ctr )
791 return;
793 if ( ctr->ctx )
794 talloc_destroy(ctr->ctx);
796 ZERO_STRUCTP(ctr);
798 return;
801 /***********************************************************************
802 **********************************************************************/
804 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
806 if ( !ctr )
807 return NULL;
809 return ctr->ctx;
812 /***********************************************************************
813 **********************************************************************/
815 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
817 if ( !ctr || !ctr->msg_groups )
818 return NULL;
820 if ( idx >= ctr->num_groups )
821 return NULL;
823 return &ctr->msg_groups[idx];
827 /***********************************************************************
828 How many groups of change messages do we have ?
829 **********************************************************************/
831 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
833 if ( !ctr )
834 return 0;
836 return ctr->num_groups;
839 /***********************************************************************
840 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
841 **********************************************************************/
843 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
845 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
846 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
847 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
848 int i, new_slot;
850 if ( !ctr || !msg )
851 return 0;
853 /* loop over all groups looking for a matching printer name */
855 for ( i=0; i<ctr->num_groups; i++ ) {
856 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
857 break;
860 /* add a new group? */
862 if ( i == ctr->num_groups )
864 ctr->num_groups++;
866 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
867 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
868 return 0;
870 ctr->msg_groups = groups;
872 /* clear the new entry and set the printer name */
874 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
875 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
878 /* add the change messages; 'i' is the correct index now regardless */
880 msg_grp = &ctr->msg_groups[i];
882 msg_grp->num_msgs++;
884 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
885 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
886 return 0;
888 msg_grp->msgs = msg_list;
890 new_slot = msg_grp->num_msgs-1;
891 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
893 /* need to allocate own copy of data */
895 if ( msg->len != 0 )
896 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
898 return ctr->num_groups;
901 /***********************************************************************
902 Send a change notication message on all handles which have a call
903 back registered
904 **********************************************************************/
906 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
908 Printer_entry *p;
909 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
910 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
911 SPOOLSS_NOTIFY_MSG *messages;
914 if ( !msg_group ) {
915 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
916 return;
919 messages = msg_group->msgs;
921 if ( !messages ) {
922 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
923 return;
926 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
928 /* loop over all printers */
930 for (p = printers_list; p; p = p->next)
932 SPOOL_NOTIFY_INFO_DATA *data;
933 uint32 data_len = 0;
934 uint32 id;
935 int i;
937 /* Is there notification on this handle? */
939 if ( !p->notify.client_connected )
940 continue;
942 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
944 /* For this printer? Print servers always receive
945 notifications. */
947 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
948 ( !strequal(msg_group->printername, p->dev.handlename) ) )
949 continue;
951 DEBUG(10,("Our printer\n"));
953 /* allocate the max entries possible */
955 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
956 ZERO_STRUCTP(data);
958 /* build the array of change notifications */
960 for ( i=0; i<msg_group->num_msgs; i++ )
962 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
964 /* Are we monitoring this event? */
966 if (!is_monitoring_event(p, msg->type, msg->field))
967 continue;
970 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
971 msg->type, msg->field, p->dev.handlename));
974 * if the is a printer notification handle and not a job notification
975 * type, then set the id to 0. Other wise just use what was specified
976 * in the message.
978 * When registering change notification on a print server handle
979 * we always need to send back the id (snum) matching the printer
980 * for which the change took place. For change notify registered
981 * on a printer handle, this does not matter and the id should be 0.
983 * --jerry
986 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
987 id = 0;
988 else
989 id = msg->id;
992 /* Convert unix jobid to smb jobid */
994 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID)
996 id = sysjob_to_jobid(msg->id);
998 if (id == -1) {
999 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1000 goto done;
1004 construct_info_data( &data[data_len], msg->type, msg->field, id );
1006 switch(msg->type) {
1007 case PRINTER_NOTIFY_TYPE:
1008 if ( !printer_notify_table[msg->field].fn )
1009 goto done;
1010 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1012 break;
1014 case JOB_NOTIFY_TYPE:
1015 if ( !job_notify_table[msg->field].fn )
1016 goto done;
1017 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1019 break;
1021 default:
1022 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1023 goto done;
1026 data_len++;
1029 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1030 data_len, data, p->notify.change, 0 );
1033 done:
1034 DEBUG(8,("send_notify2_changes: Exit...\n"));
1035 return;
1038 /***********************************************************************
1039 **********************************************************************/
1041 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
1044 int offset = 0;
1046 /* Unpack message */
1048 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1049 msg->printer);
1051 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
1052 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1054 if (msg->len == 0)
1055 tdb_unpack((char *)buf + offset, len - offset, "dd",
1056 &msg->notify.value[0], &msg->notify.value[1]);
1057 else
1058 tdb_unpack((char *)buf + offset, len - offset, "B",
1059 &msg->len, &msg->notify.data);
1061 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1062 msg->type, msg->field, msg->flags));
1064 if (msg->len == 0)
1065 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1066 msg->notify.value[1]));
1067 else
1068 dump_data(3, msg->notify.data, msg->len);
1070 return True;
1073 /********************************************************************
1074 Receive a notify2 message list
1075 ********************************************************************/
1077 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1079 size_t msg_count, i;
1080 char *buf = (char *)msg;
1081 char *msg_ptr;
1082 size_t msg_len;
1083 SPOOLSS_NOTIFY_MSG notify;
1084 SPOOLSS_NOTIFY_MSG_CTR messages;
1085 int num_groups;
1087 if (len < 4) {
1088 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1089 return;
1092 msg_count = IVAL(buf, 0);
1093 msg_ptr = buf + 4;
1095 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1097 if (msg_count == 0) {
1098 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1099 return;
1102 /* initialize the container */
1104 ZERO_STRUCT( messages );
1105 notify_msg_ctr_init( &messages );
1108 * build message groups for each printer identified
1109 * in a change_notify msg. Remember that a PCN message
1110 * includes the handle returned for the srv_spoolss_replyopenprinter()
1111 * call. Therefore messages are grouped according to printer handle.
1114 for ( i=0; i<msg_count; i++ )
1116 if (msg_ptr + 4 - buf > len) {
1117 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1118 return;
1121 msg_len = IVAL(msg_ptr,0);
1122 msg_ptr += 4;
1124 if (msg_ptr + msg_len - buf > len) {
1125 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1126 return;
1129 /* unpack messages */
1131 ZERO_STRUCT( notify );
1132 notify2_unpack_msg( &notify, msg_ptr, msg_len );
1133 msg_ptr += msg_len;
1135 /* add to correct list in container */
1137 notify_msg_ctr_addmsg( &messages, &notify );
1139 /* free memory that might have been allocated by notify2_unpack_msg() */
1141 if ( notify.len != 0 )
1142 SAFE_FREE( notify.notify.data );
1145 /* process each group of messages */
1147 num_groups = notify_msg_ctr_numgroups( &messages );
1148 for ( i=0; i<num_groups; i++ )
1149 send_notify2_changes( &messages, i );
1152 /* cleanup */
1154 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1156 notify_msg_ctr_destroy( &messages );
1158 return;
1161 /********************************************************************
1162 Send a message to ourself about new driver being installed
1163 so we can upgrade the information for each printer bound to this
1164 driver
1165 ********************************************************************/
1167 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1169 int len = strlen(drivername);
1171 if (!len)
1172 return False;
1174 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1175 drivername));
1177 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1179 return True;
1182 /**********************************************************************
1183 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1184 over all printers, upgrading ones as neessary
1185 **********************************************************************/
1187 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1189 fstring drivername;
1190 int snum;
1191 int n_services = lp_numservices();
1193 len = MIN(len,sizeof(drivername)-1);
1194 strncpy(drivername, buf, len);
1196 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1198 /* Iterate the printer list */
1200 for (snum=0; snum<n_services; snum++)
1202 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1204 WERROR result;
1205 NT_PRINTER_INFO_LEVEL *printer = NULL;
1207 result = get_a_printer(&printer, 2, lp_servicename(snum));
1208 if (!W_ERROR_IS_OK(result))
1209 continue;
1211 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1213 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1215 /* all we care about currently is the change_id */
1217 result = mod_a_printer(*printer, 2);
1218 if (!W_ERROR_IS_OK(result)) {
1219 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1220 dos_errstr(result)));
1224 free_a_printer(&printer, 2);
1228 /* all done */
1231 /********************************************************************
1232 Send a message to ourself about new driver being installed
1233 so we can upgrade the information for each printer bound to this
1234 driver
1235 ********************************************************************/
1237 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1239 int len = strlen(drivername);
1241 if (!len)
1242 return False;
1244 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1245 drivername));
1247 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1249 return True;
1252 /**********************************************************************
1253 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1254 over all printers, resetting printer data as neessary
1255 **********************************************************************/
1257 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1259 fstring drivername;
1260 int snum;
1261 int n_services = lp_numservices();
1263 len = MIN( len, sizeof(drivername)-1 );
1264 strncpy( drivername, buf, len );
1266 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1268 /* Iterate the printer list */
1270 for ( snum=0; snum<n_services; snum++ )
1272 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1274 WERROR result;
1275 NT_PRINTER_INFO_LEVEL *printer = NULL;
1277 result = get_a_printer( &printer, 2, lp_servicename(snum) );
1278 if ( !W_ERROR_IS_OK(result) )
1279 continue;
1282 * if the printer is bound to the driver,
1283 * then reset to the new driver initdata
1286 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1288 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1290 if ( !set_driver_init(printer, 2) ) {
1291 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1292 printer->info_2->printername, printer->info_2->drivername));
1295 result = mod_a_printer( *printer, 2 );
1296 if ( !W_ERROR_IS_OK(result) ) {
1297 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1298 get_dos_error_msg(result)));
1302 free_a_printer( &printer, 2 );
1306 /* all done */
1308 return;
1311 /********************************************************************
1312 Copy routines used by convert_to_openprinterex()
1313 *******************************************************************/
1315 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1317 DEVICEMODE *d;
1318 int len;
1320 if (!devmode)
1321 return NULL;
1323 DEBUG (8,("dup_devmode\n"));
1325 /* bulk copy first */
1327 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1328 if (!d)
1329 return NULL;
1331 /* dup the pointer members separately */
1333 len = unistrlen(devmode->devicename.buffer);
1334 if (len != -1) {
1335 d->devicename.buffer = talloc(ctx, len*2);
1336 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1337 return NULL;
1341 len = unistrlen(devmode->formname.buffer);
1342 if (len != -1) {
1343 d->devicename.buffer = talloc(ctx, len*2);
1344 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1345 return NULL;
1348 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1350 return d;
1353 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1355 if (!new_ctr || !ctr)
1356 return;
1358 DEBUG(8,("copy_devmode_ctr\n"));
1360 new_ctr->size = ctr->size;
1361 new_ctr->devmode_ptr = ctr->devmode_ptr;
1363 if(ctr->devmode_ptr)
1364 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1367 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1369 if (!new_def || !def)
1370 return;
1372 DEBUG(8,("copy_printer_defaults\n"));
1374 new_def->datatype_ptr = def->datatype_ptr;
1376 if (def->datatype_ptr)
1377 copy_unistr2(&new_def->datatype, &def->datatype);
1379 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1381 new_def->access_required = def->access_required;
1384 /********************************************************************
1385 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1386 * SPOOL_Q_OPEN_PRINTER_EX structure
1387 ********************************************************************/
1389 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1391 if (!q_u_ex || !q_u)
1392 return;
1394 DEBUG(8,("convert_to_openprinterex\n"));
1396 q_u_ex->printername_ptr = q_u->printername_ptr;
1398 if (q_u->printername_ptr)
1399 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1401 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1404 /********************************************************************
1405 * spoolss_open_printer
1407 * called from the spoolss dispatcher
1408 ********************************************************************/
1410 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1412 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1413 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1415 if (!q_u || !r_u)
1416 return WERR_NOMEM;
1418 ZERO_STRUCT(q_u_ex);
1419 ZERO_STRUCT(r_u_ex);
1421 /* convert the OpenPrinter() call to OpenPrinterEx() */
1423 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1425 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1427 /* convert back to OpenPrinter() */
1429 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1431 return r_u->status;
1434 /********************************************************************
1435 * spoolss_open_printer
1437 * If the openprinterex rpc call contains a devmode,
1438 * it's a per-user one. This per-user devmode is derivated
1439 * from the global devmode. Openprinterex() contains a per-user
1440 * devmode for when you do EMF printing and spooling.
1441 * In the EMF case, the NT workstation is only doing half the job
1442 * of rendering the page. The other half is done by running the printer
1443 * driver on the server.
1444 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1445 * The EMF file only contains what is to be printed on the page.
1446 * So in order for the server to know how to print, the NT client sends
1447 * a devicemode attached to the openprinterex call.
1448 * But this devicemode is short lived, it's only valid for the current print job.
1450 * If Samba would have supported EMF spooling, this devicemode would
1451 * have been attached to the handle, to sent it to the driver to correctly
1452 * rasterize the EMF file.
1454 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1455 * we just act as a pass-thru between windows and the printer.
1457 * In order to know that Samba supports only RAW spooling, NT has to call
1458 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1459 * and until NT sends a RAW job, we refuse it.
1461 * But to call getprinter() or startdoc(), you first need a valid handle,
1462 * and to get an handle you have to call openprintex(). Hence why you have
1463 * a devicemode in the openprinterex() call.
1466 * Differences between NT4 and NT 2000.
1467 * NT4:
1468 * ---
1469 * On NT4, you only have a global devicemode. This global devicemode can be changed
1470 * by the administrator (or by a user with enough privs). Everytime a user
1471 * wants to print, the devicemode is resetted to the default. In Word, everytime
1472 * you print, the printer's characteristics are always reset to the global devicemode.
1474 * NT 2000:
1475 * -------
1476 * In W2K, there is the notion of per-user devicemode. The first time you use
1477 * a printer, a per-user devicemode is build from the global devicemode.
1478 * If you change your per-user devicemode, it is saved in the registry, under the
1479 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1480 * printer preferences available.
1482 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1483 * on the General Tab of the printer properties windows.
1485 * To change the global devicemode: it's the "Printing Defaults..." button
1486 * on the Advanced Tab of the printer properties window.
1488 * JFM.
1489 ********************************************************************/
1491 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1493 UNISTR2 *printername = NULL;
1494 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1495 POLICY_HND *handle = &r_u->handle;
1497 fstring name;
1498 int snum;
1499 struct current_user user;
1500 Printer_entry *Printer=NULL;
1502 if (q_u->printername_ptr != 0)
1503 printername = &q_u->printername;
1505 if (printername == NULL)
1506 return WERR_INVALID_PRINTER_NAME;
1508 /* some sanity check because you can open a printer or a print server */
1509 /* aka: \\server\printer or \\server */
1510 unistr2_to_ascii(name, printername, sizeof(name)-1);
1512 DEBUGADD(3,("checking name: %s\n",name));
1514 if (!open_printer_hnd(p, handle, name, 0))
1515 return WERR_INVALID_PRINTER_NAME;
1517 Printer=find_printer_index_by_hnd(p, handle);
1518 if (!Printer) {
1519 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1520 Can't find printer handle we created for printer %s\n", name ));
1521 close_printer_handle(p,handle);
1522 return WERR_INVALID_PRINTER_NAME;
1525 get_current_user(&user, p);
1528 * First case: the user is opening the print server:
1530 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1531 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1533 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1534 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1535 * or if the user is listed in the smb.conf printer admin parameter.
1537 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1538 * client view printer folder, but does not show the MSAPW.
1540 * Note: this test needs code to check access rights here too. Jeremy
1541 * could you look at this?
1543 * Second case: the user is opening a printer:
1544 * NT doesn't let us connect to a printer if the connecting user
1545 * doesn't have print permission.
1548 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1550 /* Printserver handles use global struct... */
1552 snum = -1;
1554 /* Map standard access rights to object specific access rights */
1556 se_map_standard(&printer_default->access_required,
1557 &printserver_std_mapping);
1559 /* Deny any object specific bits that don't apply to print
1560 servers (i.e printer and job specific bits) */
1562 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1564 if (printer_default->access_required &
1565 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1566 DEBUG(3, ("access DENIED for non-printserver bits"));
1567 close_printer_handle(p, handle);
1568 return WERR_ACCESS_DENIED;
1571 /* Allow admin access */
1573 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1575 if (!lp_ms_add_printer_wizard()) {
1576 close_printer_handle(p, handle);
1577 return WERR_ACCESS_DENIED;
1580 /* if the user is not root and not a printer admin, then fail */
1582 if ( user.uid != 0
1583 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
1585 close_printer_handle(p, handle);
1586 return WERR_ACCESS_DENIED;
1589 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1591 else
1593 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1596 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1597 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1599 /* We fall through to return WERR_OK */
1602 else
1604 /* NT doesn't let us connect to a printer if the connecting user
1605 doesn't have print permission. */
1607 if (!get_printer_snum(p, handle, &snum))
1608 return WERR_BADFID;
1610 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1612 /* map an empty access mask to the minimum access mask */
1613 if (printer_default->access_required == 0x0)
1614 printer_default->access_required = PRINTER_ACCESS_USE;
1617 * If we are not serving the printer driver for this printer,
1618 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1619 * will keep NT clients happy --jerry
1622 if (lp_use_client_driver(snum)
1623 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1625 printer_default->access_required = PRINTER_ACCESS_USE;
1628 /* check smb.conf parameters and the the sec_desc */
1630 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1631 DEBUG(3, ("access DENIED for printer open\n"));
1632 close_printer_handle(p, handle);
1633 return WERR_ACCESS_DENIED;
1636 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1637 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1638 close_printer_handle(p, handle);
1639 return WERR_ACCESS_DENIED;
1642 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1643 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1644 else
1645 printer_default->access_required = PRINTER_ACCESS_USE;
1647 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1648 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1652 Printer->access_granted = printer_default->access_required;
1655 * If the client sent a devmode in the OpenPrinter() call, then
1656 * save it here in case we get a job submission on this handle
1659 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1660 && q_u->printer_default.devmode_cont.devmode_ptr )
1662 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1663 &Printer->nt_devmode );
1666 return WERR_OK;
1669 /****************************************************************************
1670 ****************************************************************************/
1672 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1673 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1675 BOOL ret = True;
1677 switch (level) {
1678 case 2:
1679 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1680 break;
1681 default:
1682 break;
1685 return ret;
1688 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1689 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1691 BOOL result = True;
1693 switch (level) {
1694 case 3:
1695 printer->info_3=NULL;
1696 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1697 result = False;
1698 break;
1699 case 6:
1700 printer->info_6=NULL;
1701 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1702 result = False;
1703 break;
1704 default:
1705 break;
1708 return result;
1711 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1712 NT_DEVICEMODE **pp_nt_devmode)
1714 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1717 * Ensure nt_devmode is a valid pointer
1718 * as we will be overwriting it.
1721 if (nt_devmode == NULL) {
1722 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1723 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1724 return False;
1727 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1728 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1730 nt_devmode->specversion=devmode->specversion;
1731 nt_devmode->driverversion=devmode->driverversion;
1732 nt_devmode->size=devmode->size;
1733 nt_devmode->fields=devmode->fields;
1734 nt_devmode->orientation=devmode->orientation;
1735 nt_devmode->papersize=devmode->papersize;
1736 nt_devmode->paperlength=devmode->paperlength;
1737 nt_devmode->paperwidth=devmode->paperwidth;
1738 nt_devmode->scale=devmode->scale;
1739 nt_devmode->copies=devmode->copies;
1740 nt_devmode->defaultsource=devmode->defaultsource;
1741 nt_devmode->printquality=devmode->printquality;
1742 nt_devmode->color=devmode->color;
1743 nt_devmode->duplex=devmode->duplex;
1744 nt_devmode->yresolution=devmode->yresolution;
1745 nt_devmode->ttoption=devmode->ttoption;
1746 nt_devmode->collate=devmode->collate;
1748 nt_devmode->logpixels=devmode->logpixels;
1749 nt_devmode->bitsperpel=devmode->bitsperpel;
1750 nt_devmode->pelswidth=devmode->pelswidth;
1751 nt_devmode->pelsheight=devmode->pelsheight;
1752 nt_devmode->displayflags=devmode->displayflags;
1753 nt_devmode->displayfrequency=devmode->displayfrequency;
1754 nt_devmode->icmmethod=devmode->icmmethod;
1755 nt_devmode->icmintent=devmode->icmintent;
1756 nt_devmode->mediatype=devmode->mediatype;
1757 nt_devmode->dithertype=devmode->dithertype;
1758 nt_devmode->reserved1=devmode->reserved1;
1759 nt_devmode->reserved2=devmode->reserved2;
1760 nt_devmode->panningwidth=devmode->panningwidth;
1761 nt_devmode->panningheight=devmode->panningheight;
1764 * Only change private and driverextra if the incoming devmode
1765 * has a new one. JRA.
1768 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1769 SAFE_FREE(nt_devmode->private);
1770 nt_devmode->driverextra=devmode->driverextra;
1771 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1772 return False;
1773 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1776 *pp_nt_devmode = nt_devmode;
1778 return True;
1781 /********************************************************************
1782 * _spoolss_enddocprinter_internal.
1783 ********************************************************************/
1785 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1787 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1788 int snum;
1790 if (!Printer) {
1791 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1792 return WERR_BADFID;
1795 if (!get_printer_snum(p, handle, &snum))
1796 return WERR_BADFID;
1798 Printer->document_started=False;
1799 print_job_end(snum, Printer->jobid,True);
1800 /* error codes unhandled so far ... */
1802 return WERR_OK;
1805 /********************************************************************
1806 * api_spoolss_closeprinter
1807 ********************************************************************/
1809 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1811 POLICY_HND *handle = &q_u->handle;
1813 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1815 if (Printer && Printer->document_started)
1816 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1818 if (!close_printer_handle(p, handle))
1819 return WERR_BADFID;
1821 /* clear the returned printer handle. Observed behavior
1822 from Win2k server. Don't think this really matters.
1823 Previous code just copied the value of the closed
1824 handle. --jerry */
1826 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1828 return WERR_OK;
1831 /********************************************************************
1832 * api_spoolss_deleteprinter
1834 ********************************************************************/
1836 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1838 POLICY_HND *handle = &q_u->handle;
1839 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1840 WERROR result;
1842 if (Printer && Printer->document_started)
1843 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1845 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1847 result = delete_printer_handle(p, handle);
1849 update_c_setprinter(False);
1851 return result;
1854 /*******************************************************************
1855 * static function to lookup the version id corresponding to an
1856 * long architecture string
1857 ******************************************************************/
1859 static int get_version_id (char * arch)
1861 int i;
1862 struct table_node archi_table[]= {
1864 {"Windows 4.0", "WIN40", 0 },
1865 {"Windows NT x86", "W32X86", 2 },
1866 {"Windows NT R4000", "W32MIPS", 2 },
1867 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1868 {"Windows NT PowerPC", "W32PPC", 2 },
1869 {NULL, "", -1 }
1872 for (i=0; archi_table[i].long_archi != NULL; i++)
1874 if (strcmp(arch, archi_table[i].long_archi) == 0)
1875 return (archi_table[i].version);
1878 return -1;
1881 /********************************************************************
1882 * _spoolss_deleteprinterdriver
1883 ********************************************************************/
1885 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1887 fstring driver;
1888 fstring arch;
1889 NT_PRINTER_DRIVER_INFO_LEVEL info;
1890 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1891 int version;
1892 struct current_user user;
1893 WERROR status;
1894 WERROR status_win2k = WERR_ACCESS_DENIED;
1896 get_current_user(&user, p);
1898 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1899 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1901 /* check that we have a valid driver name first */
1903 if ((version=get_version_id(arch)) == -1)
1904 return WERR_INVALID_ENVIRONMENT;
1906 ZERO_STRUCT(info);
1907 ZERO_STRUCT(info_win2k);
1909 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1911 /* try for Win2k driver if "Windows NT x86" */
1913 if ( version == 2 ) {
1914 version = 3;
1915 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1916 status = WERR_UNKNOWN_PRINTER_DRIVER;
1917 goto done;
1920 /* otherwise it was a failure */
1921 else {
1922 status = WERR_UNKNOWN_PRINTER_DRIVER;
1923 goto done;
1928 if (printer_driver_in_use(info.info_3)) {
1929 status = WERR_PRINTER_DRIVER_IN_USE;
1930 goto done;
1933 if ( version == 2 )
1935 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1937 /* if we get to here, we now have 2 driver info structures to remove */
1938 /* remove the Win2k driver first*/
1940 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1941 free_a_printer_driver( info_win2k, 3 );
1943 /* this should not have failed---if it did, report to client */
1944 if ( !W_ERROR_IS_OK(status_win2k) )
1945 goto done;
1949 status = delete_printer_driver(info.info_3, &user, version, False);
1951 /* if at least one of the deletes succeeded return OK */
1953 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1954 status = WERR_OK;
1956 done:
1957 free_a_printer_driver( info, 3 );
1959 return status;
1962 /********************************************************************
1963 * spoolss_deleteprinterdriverex
1964 ********************************************************************/
1966 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1968 fstring driver;
1969 fstring arch;
1970 NT_PRINTER_DRIVER_INFO_LEVEL info;
1971 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1972 int version;
1973 uint32 flags = q_u->delete_flags;
1974 BOOL delete_files;
1975 struct current_user user;
1976 WERROR status;
1977 WERROR status_win2k = WERR_ACCESS_DENIED;
1979 get_current_user(&user, p);
1981 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1982 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1984 /* check that we have a valid driver name first */
1985 if ((version=get_version_id(arch)) == -1) {
1986 /* this is what NT returns */
1987 return WERR_INVALID_ENVIRONMENT;
1990 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
1991 version = q_u->version;
1993 ZERO_STRUCT(info);
1994 ZERO_STRUCT(info_win2k);
1996 status = get_a_printer_driver(&info, 3, driver, arch, version);
1998 if ( !W_ERROR_IS_OK(status) )
2001 * if the client asked for a specific version,
2002 * or this is something other than Windows NT x86,
2003 * then we've failed
2006 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2007 goto done;
2009 /* try for Win2k driver if "Windows NT x86" */
2011 version = 3;
2012 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2013 status = WERR_UNKNOWN_PRINTER_DRIVER;
2014 goto done;
2018 if ( printer_driver_in_use(info.info_3) ) {
2019 status = WERR_PRINTER_DRIVER_IN_USE;
2020 goto done;
2024 * we have a couple of cases to consider.
2025 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2026 * then the delete should fail if **any** files overlap with
2027 * other drivers
2028 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2029 * non-overlapping files
2030 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2031 * is set, the do not delete any files
2032 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2035 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2037 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2039 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2040 /* no idea of the correct error here */
2041 status = WERR_ACCESS_DENIED;
2042 goto done;
2046 /* also check for W32X86/3 if necessary; maybe we already have? */
2048 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2049 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2052 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2053 /* no idea of the correct error here */
2054 free_a_printer_driver( info_win2k, 3 );
2055 status = WERR_ACCESS_DENIED;
2056 goto done;
2059 /* if we get to here, we now have 2 driver info structures to remove */
2060 /* remove the Win2k driver first*/
2062 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2063 free_a_printer_driver( info_win2k, 3 );
2065 /* this should not have failed---if it did, report to client */
2067 if ( !W_ERROR_IS_OK(status_win2k) )
2068 goto done;
2072 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2074 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2075 status = WERR_OK;
2076 done:
2077 free_a_printer_driver( info, 3 );
2079 return status;
2083 /****************************************************************************
2084 Internal routine for retreiving printerdata
2085 ***************************************************************************/
2087 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2088 const char *key, const char *value, uint32 *type, uint8 **data,
2089 uint32 *needed, uint32 in_size )
2091 REGISTRY_VALUE *val;
2092 int size, data_len;
2094 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2095 return WERR_BADFILE;
2097 *type = regval_type( val );
2099 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2101 size = regval_size( val );
2103 /* copy the min(in_size, len) */
2105 if ( in_size ) {
2106 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2108 /* special case for 0 length values */
2109 if ( data_len ) {
2110 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2111 return WERR_NOMEM;
2113 else {
2114 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2115 return WERR_NOMEM;
2118 else
2119 *data = NULL;
2121 *needed = size;
2123 DEBUG(5,("get_printer_dataex: copy done\n"));
2125 return WERR_OK;
2128 /****************************************************************************
2129 Internal routine for removing printerdata
2130 ***************************************************************************/
2132 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2134 delete_printer_data( printer->info_2, key, value );
2136 return mod_a_printer(*printer, 2);
2139 /****************************************************************************
2140 Internal routine for storing printerdata
2141 ***************************************************************************/
2143 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2144 uint32 type, uint8 *data, int real_len )
2146 delete_printer_data( printer->info_2, key, value );
2148 add_printer_data( printer->info_2, key, value, type, data, real_len );
2150 return mod_a_printer(*printer, 2);
2153 /********************************************************************
2154 GetPrinterData on a printer server Handle.
2155 ********************************************************************/
2157 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2159 int i;
2161 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2163 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2164 *type = 0x4;
2165 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2166 return WERR_NOMEM;
2167 *needed = 0x4;
2168 return WERR_OK;
2171 if (!StrCaseCmp(value, "BeepEnabled")) {
2172 *type = 0x4;
2173 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2174 return WERR_NOMEM;
2175 SIVAL(*data, 0, 0x00);
2176 *needed = 0x4;
2177 return WERR_OK;
2180 if (!StrCaseCmp(value, "EventLog")) {
2181 *type = 0x4;
2182 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2183 return WERR_NOMEM;
2184 /* formally was 0x1b */
2185 SIVAL(*data, 0, 0x0);
2186 *needed = 0x4;
2187 return WERR_OK;
2190 if (!StrCaseCmp(value, "NetPopup")) {
2191 *type = 0x4;
2192 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2193 return WERR_NOMEM;
2194 SIVAL(*data, 0, 0x00);
2195 *needed = 0x4;
2196 return WERR_OK;
2199 if (!StrCaseCmp(value, "MajorVersion")) {
2200 *type = 0x4;
2201 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2202 return WERR_NOMEM;
2203 #ifdef HAVE_ADS
2204 SIVAL(*data, 0, 3);
2205 #else
2206 SIVAL(*data, 0, 2);
2207 #endif
2208 *needed = 0x4;
2209 return WERR_OK;
2212 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2213 fstring string;
2215 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2216 *type = 0x1;
2217 *needed = 2*(strlen(string)+1);
2218 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2219 return WERR_NOMEM;
2220 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2222 /* it's done by hand ready to go on the wire */
2223 for (i=0; i<strlen(string); i++) {
2224 (*data)[2*i]=string[i];
2225 (*data)[2*i+1]='\0';
2227 return WERR_OK;
2230 if (!StrCaseCmp(value, "Architecture")) {
2231 pstring string="Windows NT x86";
2232 *type = 0x1;
2233 *needed = 2*(strlen(string)+1);
2234 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2235 return WERR_NOMEM;
2236 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2237 for (i=0; i<strlen(string); i++) {
2238 (*data)[2*i]=string[i];
2239 (*data)[2*i+1]='\0';
2241 return WERR_OK;
2244 if (!StrCaseCmp(value, "DsPresent")) {
2245 *type = 0x4;
2246 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2247 return WERR_NOMEM;
2248 SIVAL(*data, 0, 0x01);
2249 *needed = 0x4;
2250 return WERR_OK;
2253 if (!StrCaseCmp(value, "DNSMachineName")) {
2254 pstring hostname;
2256 if (!get_myfullname(hostname))
2257 return WERR_BADFILE;
2258 *type = 0x1;
2259 *needed = 2*(strlen(hostname)+1);
2260 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2261 return WERR_NOMEM;
2262 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2263 for (i=0; i<strlen(hostname); i++) {
2264 (*data)[2*i]=hostname[i];
2265 (*data)[2*i+1]='\0';
2267 return WERR_OK;
2271 return WERR_BADFILE;
2274 /********************************************************************
2275 * spoolss_getprinterdata
2276 ********************************************************************/
2278 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2280 POLICY_HND *handle = &q_u->handle;
2281 UNISTR2 *valuename = &q_u->valuename;
2282 uint32 in_size = q_u->size;
2283 uint32 *type = &r_u->type;
2284 uint32 *out_size = &r_u->size;
2285 uint8 **data = &r_u->data;
2286 uint32 *needed = &r_u->needed;
2287 WERROR status;
2288 fstring value;
2289 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2290 NT_PRINTER_INFO_LEVEL *printer = NULL;
2291 int snum = 0;
2294 * Reminder: when it's a string, the length is in BYTES
2295 * even if UNICODE is negociated.
2297 * JFM, 4/19/1999
2300 *out_size = in_size;
2302 /* in case of problem, return some default values */
2304 *needed = 0;
2305 *type = 0;
2307 DEBUG(4,("_spoolss_getprinterdata\n"));
2309 if ( !Printer ) {
2310 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2311 status = WERR_BADFID;
2312 goto done;
2315 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2317 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2318 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2319 else
2321 if ( !get_printer_snum(p,handle, &snum) ) {
2322 status = WERR_BADFID;
2323 goto done;
2326 status = get_a_printer(&printer, 2, lp_servicename(snum));
2327 if ( !W_ERROR_IS_OK(status) )
2328 goto done;
2330 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2332 if ( strequal(value, "ChangeId") ) {
2333 *type = REG_DWORD;
2334 *needed = sizeof(uint32);
2335 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2336 status = WERR_NOMEM;
2337 goto done;
2339 **data = printer->info_2->changeid;
2340 status = WERR_OK;
2342 else
2343 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2346 if (*needed > *out_size)
2347 status = WERR_MORE_DATA;
2349 done:
2350 if ( !W_ERROR_IS_OK(status) )
2352 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2354 /* reply this param doesn't exist */
2356 if ( *out_size ) {
2357 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2358 if ( printer )
2359 free_a_printer( &printer, 2 );
2360 return WERR_NOMEM;
2363 else {
2364 *data = NULL;
2368 /* cleanup & exit */
2370 if ( printer )
2371 free_a_printer( &printer, 2 );
2373 return status;
2376 /*********************************************************
2377 Connect to the client machine.
2378 **********************************************************/
2380 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, const char *remote_machine)
2382 ZERO_STRUCTP(the_cli);
2383 if(cli_initialise(the_cli) == NULL) {
2384 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2385 return False;
2388 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2389 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2390 cli_shutdown(the_cli);
2391 return False;
2394 if (ismyip(the_cli->dest_ip)) {
2395 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2396 cli_shutdown(the_cli);
2397 return False;
2400 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2401 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2402 cli_shutdown(the_cli);
2403 return False;
2406 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2407 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2408 remote_machine));
2409 cli_shutdown(the_cli);
2410 return False;
2413 the_cli->protocol = PROTOCOL_NT1;
2415 if (!cli_negprot(the_cli)) {
2416 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2417 cli_shutdown(the_cli);
2418 return False;
2421 if (the_cli->protocol != PROTOCOL_NT1) {
2422 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2423 cli_shutdown(the_cli);
2424 return False;
2428 * Do an anonymous session setup.
2431 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2432 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2433 cli_shutdown(the_cli);
2434 return False;
2437 if (!(the_cli->sec_mode & 1)) {
2438 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2439 cli_shutdown(the_cli);
2440 return False;
2443 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2444 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2445 cli_shutdown(the_cli);
2446 return False;
2450 * Ok - we have an anonymous connection to the IPC$ share.
2451 * Now start the NT Domain stuff :-).
2454 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2455 DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2456 cli_nt_session_close(the_cli);
2457 cli_ulogoff(the_cli);
2458 cli_shutdown(the_cli);
2459 return False;
2462 return True;
2465 /***************************************************************************
2466 Connect to the client.
2467 ****************************************************************************/
2469 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2471 WERROR result;
2474 * If it's the first connection, contact the client
2475 * and connect to the IPC$ share anonumously
2477 if (smb_connections==0) {
2478 fstring unix_printer;
2480 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2482 if(!spoolss_connect_to_client(&notify_cli, unix_printer))
2483 return False;
2485 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2486 /* Tell the connections db we're now interested in printer
2487 * notify messages. */
2488 register_message_flags( True, FLAG_MSG_PRINTING );
2492 * Tell the specific printing tdb we want messages for this printer
2493 * by registering our PID.
2496 if (!print_notify_register_pid(snum))
2497 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2499 smb_connections++;
2501 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2502 type, handle);
2504 if (!W_ERROR_IS_OK(result))
2505 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2506 dos_errstr(result)));
2508 return (W_ERROR_IS_OK(result));
2511 /********************************************************************
2512 * _spoolss_rffpcnex
2513 * ReplyFindFirstPrinterChangeNotifyEx
2515 * before replying OK: status=0 a rpc call is made to the workstation
2516 * asking ReplyOpenPrinter
2518 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2519 * called from api_spoolss_rffpcnex
2520 ********************************************************************/
2522 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2524 POLICY_HND *handle = &q_u->handle;
2525 uint32 flags = q_u->flags;
2526 uint32 options = q_u->options;
2527 UNISTR2 *localmachine = &q_u->localmachine;
2528 uint32 printerlocal = q_u->printerlocal;
2529 int snum = -1;
2530 SPOOL_NOTIFY_OPTION *option = q_u->option;
2532 /* store the notify value in the printer struct */
2534 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2536 if (!Printer) {
2537 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2538 return WERR_BADFID;
2541 Printer->notify.flags=flags;
2542 Printer->notify.options=options;
2543 Printer->notify.printerlocal=printerlocal;
2545 if (Printer->notify.option)
2546 free_spool_notify_option(&Printer->notify.option);
2548 Printer->notify.option=dup_spool_notify_option(option);
2550 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2551 sizeof(Printer->notify.localmachine)-1);
2553 /* Connect to the client machine and send a ReplyOpenPrinter */
2555 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2556 snum = -1;
2557 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2558 !get_printer_snum(p, handle, &snum) )
2559 return WERR_BADFID;
2561 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2562 Printer->notify.printerlocal, 1,
2563 &Printer->notify.client_hnd))
2564 return WERR_SERVER_UNAVAILABLE;
2566 Printer->notify.client_connected=True;
2568 return WERR_OK;
2571 /*******************************************************************
2572 * fill a notify_info_data with the servername
2573 ********************************************************************/
2575 void spoolss_notify_server_name(int snum,
2576 SPOOL_NOTIFY_INFO_DATA *data,
2577 print_queue_struct *queue,
2578 NT_PRINTER_INFO_LEVEL *printer,
2579 TALLOC_CTX *mem_ctx)
2581 pstring temp_name, temp;
2582 uint32 len;
2584 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2586 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2588 data->notify_data.data.length = len;
2589 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2591 if (!data->notify_data.data.string) {
2592 data->notify_data.data.length = 0;
2593 return;
2596 memcpy(data->notify_data.data.string, temp, len);
2599 /*******************************************************************
2600 * fill a notify_info_data with the printername (not including the servername).
2601 ********************************************************************/
2603 void spoolss_notify_printer_name(int snum,
2604 SPOOL_NOTIFY_INFO_DATA *data,
2605 print_queue_struct *queue,
2606 NT_PRINTER_INFO_LEVEL *printer,
2607 TALLOC_CTX *mem_ctx)
2609 pstring temp;
2610 uint32 len;
2612 /* the notify name should not contain the \\server\ part */
2613 char *p = strrchr(printer->info_2->printername, '\\');
2615 if (!p) {
2616 p = printer->info_2->printername;
2617 } else {
2618 p++;
2621 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2623 data->notify_data.data.length = len;
2624 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2626 if (!data->notify_data.data.string) {
2627 data->notify_data.data.length = 0;
2628 return;
2631 memcpy(data->notify_data.data.string, temp, len);
2634 /*******************************************************************
2635 * fill a notify_info_data with the servicename
2636 ********************************************************************/
2638 void spoolss_notify_share_name(int snum,
2639 SPOOL_NOTIFY_INFO_DATA *data,
2640 print_queue_struct *queue,
2641 NT_PRINTER_INFO_LEVEL *printer,
2642 TALLOC_CTX *mem_ctx)
2644 pstring temp;
2645 uint32 len;
2647 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2649 data->notify_data.data.length = len;
2650 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2652 if (!data->notify_data.data.string) {
2653 data->notify_data.data.length = 0;
2654 return;
2657 memcpy(data->notify_data.data.string, temp, len);
2660 /*******************************************************************
2661 * fill a notify_info_data with the port name
2662 ********************************************************************/
2664 void spoolss_notify_port_name(int snum,
2665 SPOOL_NOTIFY_INFO_DATA *data,
2666 print_queue_struct *queue,
2667 NT_PRINTER_INFO_LEVEL *printer,
2668 TALLOC_CTX *mem_ctx)
2670 pstring temp;
2671 uint32 len;
2673 /* even if it's strange, that's consistant in all the code */
2675 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2677 data->notify_data.data.length = len;
2678 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2680 if (!data->notify_data.data.string) {
2681 data->notify_data.data.length = 0;
2682 return;
2685 memcpy(data->notify_data.data.string, temp, len);
2688 /*******************************************************************
2689 * fill a notify_info_data with the printername
2690 * but it doesn't exist, have to see what to do
2691 ********************************************************************/
2693 void spoolss_notify_driver_name(int snum,
2694 SPOOL_NOTIFY_INFO_DATA *data,
2695 print_queue_struct *queue,
2696 NT_PRINTER_INFO_LEVEL *printer,
2697 TALLOC_CTX *mem_ctx)
2699 pstring temp;
2700 uint32 len;
2702 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2704 data->notify_data.data.length = len;
2705 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2707 if (!data->notify_data.data.string) {
2708 data->notify_data.data.length = 0;
2709 return;
2712 memcpy(data->notify_data.data.string, temp, len);
2715 /*******************************************************************
2716 * fill a notify_info_data with the comment
2717 ********************************************************************/
2719 void spoolss_notify_comment(int snum,
2720 SPOOL_NOTIFY_INFO_DATA *data,
2721 print_queue_struct *queue,
2722 NT_PRINTER_INFO_LEVEL *printer,
2723 TALLOC_CTX *mem_ctx)
2725 pstring temp;
2726 uint32 len;
2728 if (*printer->info_2->comment == '\0')
2729 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2730 else
2731 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2733 data->notify_data.data.length = len;
2734 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2736 if (!data->notify_data.data.string) {
2737 data->notify_data.data.length = 0;
2738 return;
2741 memcpy(data->notify_data.data.string, temp, len);
2744 /*******************************************************************
2745 * fill a notify_info_data with the comment
2746 * location = "Room 1, floor 2, building 3"
2747 ********************************************************************/
2749 void spoolss_notify_location(int snum,
2750 SPOOL_NOTIFY_INFO_DATA *data,
2751 print_queue_struct *queue,
2752 NT_PRINTER_INFO_LEVEL *printer,
2753 TALLOC_CTX *mem_ctx)
2755 pstring temp;
2756 uint32 len;
2758 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2760 data->notify_data.data.length = len;
2761 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2763 if (!data->notify_data.data.string) {
2764 data->notify_data.data.length = 0;
2765 return;
2768 memcpy(data->notify_data.data.string, temp, len);
2771 /*******************************************************************
2772 * fill a notify_info_data with the device mode
2773 * jfm:xxxx don't to it for know but that's a real problem !!!
2774 ********************************************************************/
2776 static void spoolss_notify_devmode(int snum,
2777 SPOOL_NOTIFY_INFO_DATA *data,
2778 print_queue_struct *queue,
2779 NT_PRINTER_INFO_LEVEL *printer,
2780 TALLOC_CTX *mem_ctx)
2784 /*******************************************************************
2785 * fill a notify_info_data with the separator file name
2786 ********************************************************************/
2788 void spoolss_notify_sepfile(int snum,
2789 SPOOL_NOTIFY_INFO_DATA *data,
2790 print_queue_struct *queue,
2791 NT_PRINTER_INFO_LEVEL *printer,
2792 TALLOC_CTX *mem_ctx)
2794 pstring temp;
2795 uint32 len;
2797 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2799 data->notify_data.data.length = len;
2800 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2802 if (!data->notify_data.data.string) {
2803 data->notify_data.data.length = 0;
2804 return;
2807 memcpy(data->notify_data.data.string, temp, len);
2810 /*******************************************************************
2811 * fill a notify_info_data with the print processor
2812 * jfm:xxxx return always winprint to indicate we don't do anything to it
2813 ********************************************************************/
2815 void spoolss_notify_print_processor(int snum,
2816 SPOOL_NOTIFY_INFO_DATA *data,
2817 print_queue_struct *queue,
2818 NT_PRINTER_INFO_LEVEL *printer,
2819 TALLOC_CTX *mem_ctx)
2821 pstring temp;
2822 uint32 len;
2824 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2826 data->notify_data.data.length = len;
2827 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2829 if (!data->notify_data.data.string) {
2830 data->notify_data.data.length = 0;
2831 return;
2834 memcpy(data->notify_data.data.string, temp, len);
2837 /*******************************************************************
2838 * fill a notify_info_data with the print processor options
2839 * jfm:xxxx send an empty string
2840 ********************************************************************/
2842 void spoolss_notify_parameters(int snum,
2843 SPOOL_NOTIFY_INFO_DATA *data,
2844 print_queue_struct *queue,
2845 NT_PRINTER_INFO_LEVEL *printer,
2846 TALLOC_CTX *mem_ctx)
2848 pstring temp;
2849 uint32 len;
2851 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2853 data->notify_data.data.length = len;
2854 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2856 if (!data->notify_data.data.string) {
2857 data->notify_data.data.length = 0;
2858 return;
2861 memcpy(data->notify_data.data.string, temp, len);
2864 /*******************************************************************
2865 * fill a notify_info_data with the data type
2866 * jfm:xxxx always send RAW as data type
2867 ********************************************************************/
2869 void spoolss_notify_datatype(int snum,
2870 SPOOL_NOTIFY_INFO_DATA *data,
2871 print_queue_struct *queue,
2872 NT_PRINTER_INFO_LEVEL *printer,
2873 TALLOC_CTX *mem_ctx)
2875 pstring temp;
2876 uint32 len;
2878 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2880 data->notify_data.data.length = len;
2881 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2883 if (!data->notify_data.data.string) {
2884 data->notify_data.data.length = 0;
2885 return;
2888 memcpy(data->notify_data.data.string, temp, len);
2891 /*******************************************************************
2892 * fill a notify_info_data with the security descriptor
2893 * jfm:xxxx send an null pointer to say no security desc
2894 * have to implement security before !
2895 ********************************************************************/
2897 static void spoolss_notify_security_desc(int snum,
2898 SPOOL_NOTIFY_INFO_DATA *data,
2899 print_queue_struct *queue,
2900 NT_PRINTER_INFO_LEVEL *printer,
2901 TALLOC_CTX *mem_ctx)
2903 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2904 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2907 /*******************************************************************
2908 * fill a notify_info_data with the attributes
2909 * jfm:xxxx a samba printer is always shared
2910 ********************************************************************/
2912 void spoolss_notify_attributes(int snum,
2913 SPOOL_NOTIFY_INFO_DATA *data,
2914 print_queue_struct *queue,
2915 NT_PRINTER_INFO_LEVEL *printer,
2916 TALLOC_CTX *mem_ctx)
2918 data->notify_data.value[0] = printer->info_2->attributes;
2919 data->notify_data.value[1] = 0;
2922 /*******************************************************************
2923 * fill a notify_info_data with the priority
2924 ********************************************************************/
2926 static void spoolss_notify_priority(int snum,
2927 SPOOL_NOTIFY_INFO_DATA *data,
2928 print_queue_struct *queue,
2929 NT_PRINTER_INFO_LEVEL *printer,
2930 TALLOC_CTX *mem_ctx)
2932 data->notify_data.value[0] = printer->info_2->priority;
2933 data->notify_data.value[1] = 0;
2936 /*******************************************************************
2937 * fill a notify_info_data with the default priority
2938 ********************************************************************/
2940 static void spoolss_notify_default_priority(int snum,
2941 SPOOL_NOTIFY_INFO_DATA *data,
2942 print_queue_struct *queue,
2943 NT_PRINTER_INFO_LEVEL *printer,
2944 TALLOC_CTX *mem_ctx)
2946 data->notify_data.value[0] = printer->info_2->default_priority;
2947 data->notify_data.value[1] = 0;
2950 /*******************************************************************
2951 * fill a notify_info_data with the start time
2952 ********************************************************************/
2954 static void spoolss_notify_start_time(int snum,
2955 SPOOL_NOTIFY_INFO_DATA *data,
2956 print_queue_struct *queue,
2957 NT_PRINTER_INFO_LEVEL *printer,
2958 TALLOC_CTX *mem_ctx)
2960 data->notify_data.value[0] = printer->info_2->starttime;
2961 data->notify_data.value[1] = 0;
2964 /*******************************************************************
2965 * fill a notify_info_data with the until time
2966 ********************************************************************/
2968 static void spoolss_notify_until_time(int snum,
2969 SPOOL_NOTIFY_INFO_DATA *data,
2970 print_queue_struct *queue,
2971 NT_PRINTER_INFO_LEVEL *printer,
2972 TALLOC_CTX *mem_ctx)
2974 data->notify_data.value[0] = printer->info_2->untiltime;
2975 data->notify_data.value[1] = 0;
2978 /*******************************************************************
2979 * fill a notify_info_data with the status
2980 ********************************************************************/
2982 static void spoolss_notify_status(int snum,
2983 SPOOL_NOTIFY_INFO_DATA *data,
2984 print_queue_struct *queue,
2985 NT_PRINTER_INFO_LEVEL *printer,
2986 TALLOC_CTX *mem_ctx)
2988 print_status_struct status;
2990 print_queue_length(snum, &status);
2991 data->notify_data.value[0]=(uint32) status.status;
2992 data->notify_data.value[1] = 0;
2995 /*******************************************************************
2996 * fill a notify_info_data with the number of jobs queued
2997 ********************************************************************/
2999 void spoolss_notify_cjobs(int snum,
3000 SPOOL_NOTIFY_INFO_DATA *data,
3001 print_queue_struct *queue,
3002 NT_PRINTER_INFO_LEVEL *printer,
3003 TALLOC_CTX *mem_ctx)
3005 data->notify_data.value[0] = print_queue_length(snum, NULL);
3006 data->notify_data.value[1] = 0;
3009 /*******************************************************************
3010 * fill a notify_info_data with the average ppm
3011 ********************************************************************/
3013 static void spoolss_notify_average_ppm(int snum,
3014 SPOOL_NOTIFY_INFO_DATA *data,
3015 print_queue_struct *queue,
3016 NT_PRINTER_INFO_LEVEL *printer,
3017 TALLOC_CTX *mem_ctx)
3019 /* always respond 8 pages per minutes */
3020 /* a little hard ! */
3021 data->notify_data.value[0] = printer->info_2->averageppm;
3022 data->notify_data.value[1] = 0;
3025 /*******************************************************************
3026 * fill a notify_info_data with username
3027 ********************************************************************/
3029 static void spoolss_notify_username(int snum,
3030 SPOOL_NOTIFY_INFO_DATA *data,
3031 print_queue_struct *queue,
3032 NT_PRINTER_INFO_LEVEL *printer,
3033 TALLOC_CTX *mem_ctx)
3035 pstring temp;
3036 uint32 len;
3038 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3040 data->notify_data.data.length = len;
3041 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3043 if (!data->notify_data.data.string) {
3044 data->notify_data.data.length = 0;
3045 return;
3048 memcpy(data->notify_data.data.string, temp, len);
3051 /*******************************************************************
3052 * fill a notify_info_data with job status
3053 ********************************************************************/
3055 static void spoolss_notify_job_status(int snum,
3056 SPOOL_NOTIFY_INFO_DATA *data,
3057 print_queue_struct *queue,
3058 NT_PRINTER_INFO_LEVEL *printer,
3059 TALLOC_CTX *mem_ctx)
3061 data->notify_data.value[0]=nt_printj_status(queue->status);
3062 data->notify_data.value[1] = 0;
3065 /*******************************************************************
3066 * fill a notify_info_data with job name
3067 ********************************************************************/
3069 static void spoolss_notify_job_name(int snum,
3070 SPOOL_NOTIFY_INFO_DATA *data,
3071 print_queue_struct *queue,
3072 NT_PRINTER_INFO_LEVEL *printer,
3073 TALLOC_CTX *mem_ctx)
3075 pstring temp;
3076 uint32 len;
3078 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3080 data->notify_data.data.length = len;
3081 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3083 if (!data->notify_data.data.string) {
3084 data->notify_data.data.length = 0;
3085 return;
3088 memcpy(data->notify_data.data.string, temp, len);
3091 /*******************************************************************
3092 * fill a notify_info_data with job status
3093 ********************************************************************/
3095 static void spoolss_notify_job_status_string(int snum,
3096 SPOOL_NOTIFY_INFO_DATA *data,
3097 print_queue_struct *queue,
3098 NT_PRINTER_INFO_LEVEL *printer,
3099 TALLOC_CTX *mem_ctx)
3102 * Now we're returning job status codes we just return a "" here. JRA.
3105 const char *p = "";
3106 pstring temp;
3107 uint32 len;
3109 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3110 p = "unknown";
3112 switch (queue->status) {
3113 case LPQ_QUEUED:
3114 p = "Queued";
3115 break;
3116 case LPQ_PAUSED:
3117 p = ""; /* NT provides the paused string */
3118 break;
3119 case LPQ_SPOOLING:
3120 p = "Spooling";
3121 break;
3122 case LPQ_PRINTING:
3123 p = "Printing";
3124 break;
3126 #endif /* NO LONGER NEEDED. */
3128 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3130 data->notify_data.data.length = len;
3131 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3133 if (!data->notify_data.data.string) {
3134 data->notify_data.data.length = 0;
3135 return;
3138 memcpy(data->notify_data.data.string, temp, len);
3141 /*******************************************************************
3142 * fill a notify_info_data with job time
3143 ********************************************************************/
3145 static void spoolss_notify_job_time(int snum,
3146 SPOOL_NOTIFY_INFO_DATA *data,
3147 print_queue_struct *queue,
3148 NT_PRINTER_INFO_LEVEL *printer,
3149 TALLOC_CTX *mem_ctx)
3151 data->notify_data.value[0]=0x0;
3152 data->notify_data.value[1]=0;
3155 /*******************************************************************
3156 * fill a notify_info_data with job size
3157 ********************************************************************/
3159 static void spoolss_notify_job_size(int snum,
3160 SPOOL_NOTIFY_INFO_DATA *data,
3161 print_queue_struct *queue,
3162 NT_PRINTER_INFO_LEVEL *printer,
3163 TALLOC_CTX *mem_ctx)
3165 data->notify_data.value[0]=queue->size;
3166 data->notify_data.value[1]=0;
3169 /*******************************************************************
3170 * fill a notify_info_data with page info
3171 ********************************************************************/
3172 static void spoolss_notify_total_pages(int snum,
3173 SPOOL_NOTIFY_INFO_DATA *data,
3174 print_queue_struct *queue,
3175 NT_PRINTER_INFO_LEVEL *printer,
3176 TALLOC_CTX *mem_ctx)
3178 data->notify_data.value[0]=queue->page_count;
3179 data->notify_data.value[1]=0;
3182 /*******************************************************************
3183 * fill a notify_info_data with pages printed info.
3184 ********************************************************************/
3185 static void spoolss_notify_pages_printed(int snum,
3186 SPOOL_NOTIFY_INFO_DATA *data,
3187 print_queue_struct *queue,
3188 NT_PRINTER_INFO_LEVEL *printer,
3189 TALLOC_CTX *mem_ctx)
3191 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3192 data->notify_data.value[1]=0;
3195 /*******************************************************************
3196 Fill a notify_info_data with job position.
3197 ********************************************************************/
3199 static void spoolss_notify_job_position(int snum,
3200 SPOOL_NOTIFY_INFO_DATA *data,
3201 print_queue_struct *queue,
3202 NT_PRINTER_INFO_LEVEL *printer,
3203 TALLOC_CTX *mem_ctx)
3205 data->notify_data.value[0]=queue->job;
3206 data->notify_data.value[1]=0;
3209 /*******************************************************************
3210 Fill a notify_info_data with submitted time.
3211 ********************************************************************/
3213 static void spoolss_notify_submitted_time(int snum,
3214 SPOOL_NOTIFY_INFO_DATA *data,
3215 print_queue_struct *queue,
3216 NT_PRINTER_INFO_LEVEL *printer,
3217 TALLOC_CTX *mem_ctx)
3219 struct tm *t;
3220 uint32 len;
3221 SYSTEMTIME st;
3222 char *p;
3224 t=gmtime(&queue->time);
3226 len = sizeof(SYSTEMTIME);
3228 data->notify_data.data.length = len;
3229 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3231 if (!data->notify_data.data.string) {
3232 data->notify_data.data.length = 0;
3233 return;
3236 make_systemtime(&st, t);
3239 * Systemtime must be linearized as a set of UINT16's.
3240 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3243 p = (char *)data->notify_data.data.string;
3244 SSVAL(p, 0, st.year);
3245 SSVAL(p, 2, st.month);
3246 SSVAL(p, 4, st.dayofweek);
3247 SSVAL(p, 6, st.day);
3248 SSVAL(p, 8, st.hour);
3249 SSVAL(p, 10, st.minute);
3250 SSVAL(p, 12, st.second);
3251 SSVAL(p, 14, st.milliseconds);
3254 struct s_notify_info_data_table
3256 uint16 type;
3257 uint16 field;
3258 const char *name;
3259 uint32 size;
3260 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3261 print_queue_struct *queue,
3262 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3265 /* A table describing the various print notification constants and
3266 whether the notification data is a pointer to a variable sized
3267 buffer, a one value uint32 or a two value uint32. */
3269 static const struct s_notify_info_data_table notify_info_data_table[] =
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3322 /*******************************************************************
3323 Return the size of info_data structure.
3324 ********************************************************************/
3326 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3328 int i=0;
3330 for (i = 0; i < sizeof(notify_info_data_table); i++)
3332 if ( (notify_info_data_table[i].type == type)
3333 && (notify_info_data_table[i].field == field) )
3335 switch(notify_info_data_table[i].size)
3337 case NOTIFY_ONE_VALUE:
3338 case NOTIFY_TWO_VALUE:
3339 return 1;
3340 case NOTIFY_STRING:
3341 return 2;
3343 /* The only pointer notify data I have seen on
3344 the wire is the submitted time and this has
3345 the notify size set to 4. -tpot */
3347 case NOTIFY_POINTER:
3348 return 4;
3350 case NOTIFY_SECDESC:
3351 return 5;
3356 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3358 return 0;
3361 /*******************************************************************
3362 Return the type of notify_info_data.
3363 ********************************************************************/
3365 static int type_of_notify_info_data(uint16 type, uint16 field)
3367 int i=0;
3369 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3370 if (notify_info_data_table[i].type == type &&
3371 notify_info_data_table[i].field == field)
3372 return notify_info_data_table[i].size;
3375 return False;
3378 /****************************************************************************
3379 ****************************************************************************/
3381 static int search_notify(uint16 type, uint16 field, int *value)
3383 int i;
3385 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3386 if (notify_info_data_table[i].type == type &&
3387 notify_info_data_table[i].field == field &&
3388 notify_info_data_table[i].fn != NULL) {
3389 *value = i;
3390 return True;
3394 return False;
3397 /****************************************************************************
3398 ****************************************************************************/
3400 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3402 info_data->type = type;
3403 info_data->field = field;
3404 info_data->reserved = 0;
3406 info_data->size = size_of_notify_info_data(type, field);
3407 info_data->enc_type = type_of_notify_info_data(type, field);
3409 info_data->id = id;
3414 /*******************************************************************
3416 * fill a notify_info struct with info asked
3418 ********************************************************************/
3420 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
3421 snum, SPOOL_NOTIFY_OPTION_TYPE
3422 *option_type, uint32 id,
3423 TALLOC_CTX *mem_ctx)
3425 int field_num,j;
3426 uint16 type;
3427 uint16 field;
3429 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3430 NT_PRINTER_INFO_LEVEL *printer = NULL;
3431 print_queue_struct *queue=NULL;
3433 type=option_type->type;
3435 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3436 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3437 option_type->count, lp_servicename(snum)));
3439 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3440 return False;
3442 for(field_num=0; field_num<option_type->count; field_num++)
3444 field = option_type->fields[field_num];
3446 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3448 if (!search_notify(type, field, &j) )
3449 continue;
3451 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
3453 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3454 return False;
3456 else
3457 info->data = tid;
3459 current_data = &info->data[info->count];
3461 construct_info_data(current_data, type, field, id);
3463 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3464 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3466 notify_info_data_table[j].fn(snum, current_data, queue,
3467 printer, mem_ctx);
3469 info->count++;
3472 free_a_printer(&printer, 2);
3473 return True;
3476 /*******************************************************************
3478 * fill a notify_info struct with info asked
3480 ********************************************************************/
3482 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3483 SPOOL_NOTIFY_INFO *info,
3484 NT_PRINTER_INFO_LEVEL *printer,
3485 int snum, SPOOL_NOTIFY_OPTION_TYPE
3486 *option_type, uint32 id,
3487 TALLOC_CTX *mem_ctx)
3489 int field_num,j;
3490 uint16 type;
3491 uint16 field;
3493 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3495 DEBUG(4,("construct_notify_jobs_info\n"));
3497 type = option_type->type;
3499 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3500 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3501 option_type->count));
3503 for(field_num=0; field_num<option_type->count; field_num++) {
3504 field = option_type->fields[field_num];
3506 if (!search_notify(type, field, &j) )
3507 continue;
3509 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3510 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3511 return False;
3513 else info->data = tid;
3515 current_data=&(info->data[info->count]);
3517 construct_info_data(current_data, type, field, id);
3518 notify_info_data_table[j].fn(snum, current_data, queue,
3519 printer, mem_ctx);
3520 info->count++;
3523 return True;
3527 * JFM: The enumeration is not that simple, it's even non obvious.
3529 * let's take an example: I want to monitor the PRINTER SERVER for
3530 * the printer's name and the number of jobs currently queued.
3531 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3532 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3534 * I have 3 printers on the back of my server.
3536 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3537 * structures.
3538 * Number Data Id
3539 * 1 printer 1 name 1
3540 * 2 printer 1 cjob 1
3541 * 3 printer 2 name 2
3542 * 4 printer 2 cjob 2
3543 * 5 printer 3 name 3
3544 * 6 printer 3 name 3
3546 * that's the print server case, the printer case is even worse.
3549 /*******************************************************************
3551 * enumerate all printers on the printserver
3552 * fill a notify_info struct with info asked
3554 ********************************************************************/
3556 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3557 SPOOL_NOTIFY_INFO *info,
3558 TALLOC_CTX *mem_ctx)
3560 int snum;
3561 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3562 int n_services=lp_numservices();
3563 int i;
3564 uint32 id;
3565 SPOOL_NOTIFY_OPTION *option;
3566 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3568 DEBUG(4,("printserver_notify_info\n"));
3570 if (!Printer)
3571 return WERR_BADFID;
3573 option=Printer->notify.option;
3574 id=1;
3575 info->version=2;
3576 info->data=NULL;
3577 info->count=0;
3579 for (i=0; i<option->count; i++) {
3580 option_type=&(option->ctr.type[i]);
3582 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3583 continue;
3585 for (snum=0; snum<n_services; snum++)
3587 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3588 construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
3592 #if 0
3594 * Debugging information, don't delete.
3597 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3598 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3599 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3601 for (i=0; i<info->count; i++) {
3602 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3603 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3604 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3606 #endif
3608 return WERR_OK;
3611 /*******************************************************************
3613 * fill a notify_info struct with info asked
3615 ********************************************************************/
3617 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3618 TALLOC_CTX *mem_ctx)
3620 int snum;
3621 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3622 int i;
3623 uint32 id;
3624 SPOOL_NOTIFY_OPTION *option;
3625 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3626 int count,j;
3627 print_queue_struct *queue=NULL;
3628 print_status_struct status;
3630 DEBUG(4,("printer_notify_info\n"));
3632 if (!Printer)
3633 return WERR_BADFID;
3635 option=Printer->notify.option;
3636 id = 0x0;
3637 info->version=2;
3638 info->data=NULL;
3639 info->count=0;
3641 get_printer_snum(p, hnd, &snum);
3643 for (i=0; i<option->count; i++) {
3644 option_type=&option->ctr.type[i];
3646 switch ( option_type->type ) {
3647 case PRINTER_NOTIFY_TYPE:
3648 if(construct_notify_printer_info(info, snum,
3649 option_type, id,
3650 mem_ctx))
3651 id--;
3652 break;
3654 case JOB_NOTIFY_TYPE: {
3655 NT_PRINTER_INFO_LEVEL *printer = NULL;
3657 count = print_queue_status(snum, &queue, &status);
3659 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3660 lp_servicename(snum))))
3661 goto done;
3663 for (j=0; j<count; j++) {
3664 construct_notify_jobs_info(&queue[j], info,
3665 printer, snum,
3666 option_type,
3667 queue[j].job,
3668 mem_ctx);
3671 free_a_printer(&printer, 2);
3673 done:
3674 SAFE_FREE(queue);
3675 break;
3681 * Debugging information, don't delete.
3684 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3685 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3686 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3688 for (i=0; i<info->count; i++) {
3689 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3690 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3691 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3694 return WERR_OK;
3697 /********************************************************************
3698 * spoolss_rfnpcnex
3699 ********************************************************************/
3701 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3703 POLICY_HND *handle = &q_u->handle;
3704 SPOOL_NOTIFY_INFO *info = &r_u->info;
3706 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3707 WERROR result = WERR_BADFID;
3709 /* we always have a NOTIFY_INFO struct */
3710 r_u->info_ptr=0x1;
3712 if (!Printer) {
3713 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3714 OUR_HANDLE(handle)));
3715 goto done;
3718 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3721 * We are now using the change value, and
3722 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3723 * I don't have a global notification system, I'm sending back all the
3724 * informations even when _NOTHING_ has changed.
3727 /* We need to keep track of the change value to send back in
3728 RRPCN replies otherwise our updates are ignored. */
3730 if (Printer->notify.client_connected) {
3731 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3732 Printer->notify.change = q_u->change;
3735 /* just ignore the SPOOL_NOTIFY_OPTION */
3737 switch (Printer->printer_type) {
3738 case PRINTER_HANDLE_IS_PRINTSERVER:
3739 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3740 break;
3742 case PRINTER_HANDLE_IS_PRINTER:
3743 result = printer_notify_info(p, handle, info, p->mem_ctx);
3744 break;
3747 done:
3748 return result;
3751 /********************************************************************
3752 * construct_printer_info_0
3753 * fill a printer_info_0 struct
3754 ********************************************************************/
3756 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3758 pstring chaine;
3759 int count;
3760 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3761 counter_printer_0 *session_counter;
3762 uint32 global_counter;
3763 struct tm *t;
3764 time_t setuptime;
3765 print_status_struct status;
3767 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3768 return False;
3770 count = print_queue_length(snum, &status);
3772 /* check if we already have a counter for this printer */
3773 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3775 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3776 if (session_counter->snum == snum)
3777 break;
3780 /* it's the first time, add it to the list */
3781 if (session_counter==NULL) {
3782 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3783 free_a_printer(&ntprinter, 2);
3784 return False;
3786 ZERO_STRUCTP(session_counter);
3787 session_counter->snum=snum;
3788 session_counter->counter=0;
3789 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3792 /* increment it */
3793 session_counter->counter++;
3795 /* JFM:
3796 * the global_counter should be stored in a TDB as it's common to all the clients
3797 * and should be zeroed on samba startup
3799 global_counter=session_counter->counter;
3801 pstrcpy(chaine,ntprinter->info_2->printername);
3803 init_unistr(&printer->printername, chaine);
3805 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3806 init_unistr(&printer->servername, chaine);
3808 printer->cjobs = count;
3809 printer->total_jobs = 0;
3810 printer->total_bytes = 0;
3812 setuptime = (time_t)ntprinter->info_2->setuptime;
3813 t=gmtime(&setuptime);
3815 printer->year = t->tm_year+1900;
3816 printer->month = t->tm_mon+1;
3817 printer->dayofweek = t->tm_wday;
3818 printer->day = t->tm_mday;
3819 printer->hour = t->tm_hour;
3820 printer->minute = t->tm_min;
3821 printer->second = t->tm_sec;
3822 printer->milliseconds = 0;
3824 printer->global_counter = global_counter;
3825 printer->total_pages = 0;
3826 #ifdef HAVE_ADS
3827 printer->major_version = 0x0005; /* NT 5 */
3828 printer->build_version = 0x0893; /* build 2195 */
3829 #else
3830 printer->major_version = 0x0004; /* NT 4 */
3831 printer->build_version = 0x0565; /* build 1381 */
3832 #endif
3833 printer->unknown7 = 0x1;
3834 printer->unknown8 = 0x0;
3835 printer->unknown9 = 0x0;
3836 printer->session_counter = session_counter->counter;
3837 printer->unknown11 = 0x0;
3838 printer->printer_errors = 0x0; /* number of print failure */
3839 printer->unknown13 = 0x0;
3840 printer->unknown14 = 0x1;
3841 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3842 printer->unknown16 = 0x0;
3843 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3844 printer->unknown18 = 0x0;
3845 printer->status = nt_printq_status(status.status);
3846 printer->unknown20 = 0x0;
3847 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3848 printer->unknown22 = 0x0;
3849 printer->unknown23 = 0x6; /* 6 ???*/
3850 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3851 printer->unknown25 = 0;
3852 printer->unknown26 = 0;
3853 printer->unknown27 = 0;
3854 printer->unknown28 = 0;
3855 printer->unknown29 = 0;
3857 free_a_printer(&ntprinter,2);
3858 return (True);
3861 /********************************************************************
3862 * construct_printer_info_1
3863 * fill a printer_info_1 struct
3864 ********************************************************************/
3865 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3867 pstring chaine;
3868 pstring chaine2;
3869 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3871 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3872 return False;
3874 printer->flags=flags;
3876 if (*ntprinter->info_2->comment == '\0') {
3877 init_unistr(&printer->comment, lp_comment(snum));
3878 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3879 ntprinter->info_2->drivername, lp_comment(snum));
3881 else {
3882 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3883 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3884 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3887 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3889 init_unistr(&printer->description, chaine);
3890 init_unistr(&printer->name, chaine2);
3892 free_a_printer(&ntprinter,2);
3894 return True;
3897 /****************************************************************************
3898 Free a DEVMODE struct.
3899 ****************************************************************************/
3901 static void free_dev_mode(DEVICEMODE *dev)
3903 if (dev == NULL)
3904 return;
3906 SAFE_FREE(dev->private);
3907 SAFE_FREE(dev);
3911 /****************************************************************************
3912 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3913 should be valid upon entry
3914 ****************************************************************************/
3916 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
3918 if ( !devmode || !ntdevmode )
3919 return False;
3921 init_unistr(&devmode->devicename, ntdevmode->devicename);
3923 init_unistr(&devmode->formname, ntdevmode->formname);
3925 devmode->specversion = ntdevmode->specversion;
3926 devmode->driverversion = ntdevmode->driverversion;
3927 devmode->size = ntdevmode->size;
3928 devmode->driverextra = ntdevmode->driverextra;
3929 devmode->fields = ntdevmode->fields;
3931 devmode->orientation = ntdevmode->orientation;
3932 devmode->papersize = ntdevmode->papersize;
3933 devmode->paperlength = ntdevmode->paperlength;
3934 devmode->paperwidth = ntdevmode->paperwidth;
3935 devmode->scale = ntdevmode->scale;
3936 devmode->copies = ntdevmode->copies;
3937 devmode->defaultsource = ntdevmode->defaultsource;
3938 devmode->printquality = ntdevmode->printquality;
3939 devmode->color = ntdevmode->color;
3940 devmode->duplex = ntdevmode->duplex;
3941 devmode->yresolution = ntdevmode->yresolution;
3942 devmode->ttoption = ntdevmode->ttoption;
3943 devmode->collate = ntdevmode->collate;
3944 devmode->icmmethod = ntdevmode->icmmethod;
3945 devmode->icmintent = ntdevmode->icmintent;
3946 devmode->mediatype = ntdevmode->mediatype;
3947 devmode->dithertype = ntdevmode->dithertype;
3949 if (ntdevmode->private != NULL) {
3950 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3951 return False;
3954 return True;
3957 /****************************************************************************
3958 Create a DEVMODE struct. Returns malloced memory.
3959 ****************************************************************************/
3961 DEVICEMODE *construct_dev_mode(int snum)
3963 NT_PRINTER_INFO_LEVEL *printer = NULL;
3964 DEVICEMODE *devmode = NULL;
3966 DEBUG(7,("construct_dev_mode\n"));
3968 DEBUGADD(8,("getting printer characteristics\n"));
3970 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3971 return NULL;
3973 if ( !printer->info_2->devmode ) {
3974 DEBUG(5, ("BONG! There was no device mode!\n"));
3975 goto done;
3978 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3979 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3980 goto done;
3983 ZERO_STRUCTP(devmode);
3985 DEBUGADD(8,("loading DEVICEMODE\n"));
3987 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
3988 free_dev_mode( devmode );
3989 devmode = NULL;
3992 done:
3993 free_a_printer(&printer,2);
3995 return devmode;
3998 /********************************************************************
3999 * construct_printer_info_2
4000 * fill a printer_info_2 struct
4001 ********************************************************************/
4003 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
4005 int count;
4006 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4008 print_status_struct status;
4010 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4011 return False;
4013 count = print_queue_length(snum, &status);
4015 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4016 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4017 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4018 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4019 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4021 if (*ntprinter->info_2->comment == '\0')
4022 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4023 else
4024 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4026 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4027 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4028 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4029 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4030 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4032 printer->attributes = ntprinter->info_2->attributes;
4034 printer->priority = ntprinter->info_2->priority; /* priority */
4035 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4036 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4037 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4038 printer->status = nt_printq_status(status.status); /* status */
4039 printer->cjobs = count; /* jobs */
4040 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4042 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4043 DEBUG(8, ("Returning NULL Devicemode!\n"));
4046 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4047 /* steal the printer info sec_desc structure. [badly done]. */
4048 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4049 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4050 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4051 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4053 else {
4054 printer->secdesc = NULL;
4057 free_a_printer(&ntprinter, 2);
4058 return True;
4061 /********************************************************************
4062 * construct_printer_info_3
4063 * fill a printer_info_3 struct
4064 ********************************************************************/
4066 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
4068 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4069 PRINTER_INFO_3 *printer = NULL;
4071 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4072 return False;
4074 *pp_printer = NULL;
4075 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4076 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4077 return False;
4080 ZERO_STRUCTP(printer);
4082 printer->flags = 4; /* These are the components of the SD we are returning. */
4083 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4084 /* steal the printer info sec_desc structure. [badly done]. */
4085 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4087 #if 0
4089 * Set the flags for the components we are returning.
4092 if (printer->secdesc->owner_sid)
4093 printer->flags |= OWNER_SECURITY_INFORMATION;
4095 if (printer->secdesc->grp_sid)
4096 printer->flags |= GROUP_SECURITY_INFORMATION;
4098 if (printer->secdesc->dacl)
4099 printer->flags |= DACL_SECURITY_INFORMATION;
4101 if (printer->secdesc->sacl)
4102 printer->flags |= SACL_SECURITY_INFORMATION;
4103 #endif
4105 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4106 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4107 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4110 free_a_printer(&ntprinter, 2);
4112 *pp_printer = printer;
4113 return True;
4116 /********************************************************************
4117 * construct_printer_info_4
4118 * fill a printer_info_4 struct
4119 ********************************************************************/
4121 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
4123 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4125 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4126 return False;
4128 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4129 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4130 printer->attributes = ntprinter->info_2->attributes;
4132 free_a_printer(&ntprinter, 2);
4133 return True;
4136 /********************************************************************
4137 * construct_printer_info_5
4138 * fill a printer_info_5 struct
4139 ********************************************************************/
4141 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
4143 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4145 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4146 return False;
4148 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4149 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
4150 printer->attributes = ntprinter->info_2->attributes;
4151 printer->device_not_selected_timeout = 0x3a98;
4152 printer->transmission_retry_timeout = 0xafc8;
4154 free_a_printer(&ntprinter, 2);
4155 return True;
4158 /********************************************************************
4159 * construct_printer_info_7
4160 * fill a printer_info_7 struct
4161 ********************************************************************/
4163 static BOOL construct_printer_info_7(PRINTER_INFO_7 *printer, int snum)
4165 char *guid_str = NULL;
4166 GUID guid;
4168 if (is_printer_published(snum, &guid)) {
4169 asprintf(&guid_str, "{%s}", uuid_string_static(guid));
4170 strupper(guid_str);
4171 init_unistr(&printer->guid, guid_str);
4172 printer->action = SPOOL_DS_PUBLISH;
4173 } else {
4174 init_unistr(&printer->guid, "");
4175 printer->action = SPOOL_DS_UNPUBLISH;
4178 return True;
4181 /********************************************************************
4182 Spoolss_enumprinters.
4183 ********************************************************************/
4185 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4187 int snum;
4188 int i;
4189 int n_services=lp_numservices();
4190 PRINTER_INFO_1 *tp, *printers=NULL;
4191 PRINTER_INFO_1 current_prt;
4193 DEBUG(4,("enum_all_printers_info_1\n"));
4195 for (snum=0; snum<n_services; snum++) {
4196 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4197 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4199 if (construct_printer_info_1(flags, &current_prt, snum)) {
4200 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4201 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4202 SAFE_FREE(printers);
4203 *returned=0;
4204 return WERR_NOMEM;
4206 else printers = tp;
4207 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4209 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4210 (*returned)++;
4215 /* check the required size. */
4216 for (i=0; i<*returned; i++)
4217 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4219 if (!alloc_buffer_size(buffer, *needed))
4220 return WERR_INSUFFICIENT_BUFFER;
4222 /* fill the buffer with the structures */
4223 for (i=0; i<*returned; i++)
4224 smb_io_printer_info_1("", buffer, &printers[i], 0);
4226 /* clear memory */
4227 SAFE_FREE(printers);
4229 if (*needed > offered) {
4230 *returned=0;
4231 return WERR_INSUFFICIENT_BUFFER;
4233 else
4234 return WERR_OK;
4237 /********************************************************************
4238 enum_all_printers_info_1_local.
4239 *********************************************************************/
4241 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4243 DEBUG(4,("enum_all_printers_info_1_local\n"));
4245 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4248 /********************************************************************
4249 enum_all_printers_info_1_name.
4250 *********************************************************************/
4252 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4254 char *s = name;
4256 DEBUG(4,("enum_all_printers_info_1_name\n"));
4258 if ((name[0] == '\\') && (name[1] == '\\'))
4259 s = name + 2;
4261 if (is_myname_or_ipaddr(s)) {
4262 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4264 else
4265 return WERR_INVALID_NAME;
4268 /********************************************************************
4269 enum_all_printers_info_1_remote.
4270 *********************************************************************/
4272 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4274 PRINTER_INFO_1 *printer;
4275 fstring printername;
4276 fstring desc;
4277 fstring comment;
4278 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4280 /* JFM: currently it's more a place holder than anything else.
4281 * In the spooler world there is a notion of server registration.
4282 * the print servers are registring (sp ?) on the PDC (in the same domain)
4284 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4287 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4288 return WERR_NOMEM;
4290 *returned=1;
4292 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4293 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4294 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4296 init_unistr(&printer->description, desc);
4297 init_unistr(&printer->name, printername);
4298 init_unistr(&printer->comment, comment);
4299 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4301 /* check the required size. */
4302 *needed += spoolss_size_printer_info_1(printer);
4304 if (!alloc_buffer_size(buffer, *needed)) {
4305 SAFE_FREE(printer);
4306 return WERR_INSUFFICIENT_BUFFER;
4309 /* fill the buffer with the structures */
4310 smb_io_printer_info_1("", buffer, printer, 0);
4312 /* clear memory */
4313 SAFE_FREE(printer);
4315 if (*needed > offered) {
4316 *returned=0;
4317 return WERR_INSUFFICIENT_BUFFER;
4319 else
4320 return WERR_OK;
4323 /********************************************************************
4324 enum_all_printers_info_1_network.
4325 *********************************************************************/
4327 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4329 char *s = name;
4331 DEBUG(4,("enum_all_printers_info_1_network\n"));
4333 /* If we respond to a enum_printers level 1 on our name with flags
4334 set to PRINTER_ENUM_REMOTE with a list of printers then these
4335 printers incorrectly appear in the APW browse list.
4336 Specifically the printers for the server appear at the workgroup
4337 level where all the other servers in the domain are
4338 listed. Windows responds to this call with a
4339 WERR_CAN_NOT_COMPLETE so we should do the same. */
4341 if (name[0] == '\\' && name[1] == '\\')
4342 s = name + 2;
4344 if (is_myname_or_ipaddr(s))
4345 return WERR_CAN_NOT_COMPLETE;
4347 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4350 /********************************************************************
4351 * api_spoolss_enumprinters
4353 * called from api_spoolss_enumprinters (see this to understand)
4354 ********************************************************************/
4356 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4358 int snum;
4359 int i;
4360 int n_services=lp_numservices();
4361 PRINTER_INFO_2 *tp, *printers=NULL;
4362 PRINTER_INFO_2 current_prt;
4364 for (snum=0; snum<n_services; snum++) {
4365 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4366 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4368 if (construct_printer_info_2(&current_prt, snum)) {
4369 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4370 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4371 SAFE_FREE(printers);
4372 *returned = 0;
4373 return WERR_NOMEM;
4375 else printers = tp;
4376 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4377 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4378 (*returned)++;
4383 /* check the required size. */
4384 for (i=0; i<*returned; i++)
4385 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4387 if (!alloc_buffer_size(buffer, *needed)) {
4388 for (i=0; i<*returned; i++) {
4389 free_devmode(printers[i].devmode);
4391 SAFE_FREE(printers);
4392 return WERR_INSUFFICIENT_BUFFER;
4395 /* fill the buffer with the structures */
4396 for (i=0; i<*returned; i++)
4397 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4399 /* clear memory */
4400 for (i=0; i<*returned; i++) {
4401 free_devmode(printers[i].devmode);
4403 SAFE_FREE(printers);
4405 if (*needed > offered) {
4406 *returned=0;
4407 return WERR_INSUFFICIENT_BUFFER;
4409 else
4410 return WERR_OK;
4413 /********************************************************************
4414 * handle enumeration of printers at level 1
4415 ********************************************************************/
4417 static WERROR enumprinters_level1( uint32 flags, fstring name,
4418 NEW_BUFFER *buffer, uint32 offered,
4419 uint32 *needed, uint32 *returned)
4421 /* Not all the flags are equals */
4423 if (flags & PRINTER_ENUM_LOCAL)
4424 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4426 if (flags & PRINTER_ENUM_NAME)
4427 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4429 if (flags & PRINTER_ENUM_REMOTE)
4430 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4432 if (flags & PRINTER_ENUM_NETWORK)
4433 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4435 return WERR_OK; /* NT4sp5 does that */
4438 /********************************************************************
4439 * handle enumeration of printers at level 2
4440 ********************************************************************/
4442 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4443 NEW_BUFFER *buffer, uint32 offered,
4444 uint32 *needed, uint32 *returned)
4446 char *s = servername;
4448 if (flags & PRINTER_ENUM_LOCAL) {
4449 return enum_all_printers_info_2(buffer, offered, needed, returned);
4452 if (flags & PRINTER_ENUM_NAME) {
4453 if ((servername[0] == '\\') && (servername[1] == '\\'))
4454 s = servername + 2;
4455 if (is_myname_or_ipaddr(s))
4456 return enum_all_printers_info_2(buffer, offered, needed, returned);
4457 else
4458 return WERR_INVALID_NAME;
4461 if (flags & PRINTER_ENUM_REMOTE)
4462 return WERR_UNKNOWN_LEVEL;
4464 return WERR_OK;
4467 /********************************************************************
4468 * handle enumeration of printers at level 5
4469 ********************************************************************/
4471 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4472 NEW_BUFFER *buffer, uint32 offered,
4473 uint32 *needed, uint32 *returned)
4475 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4476 return WERR_OK;
4479 /********************************************************************
4480 * api_spoolss_enumprinters
4482 * called from api_spoolss_enumprinters (see this to understand)
4483 ********************************************************************/
4485 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4487 uint32 flags = q_u->flags;
4488 UNISTR2 *servername = &q_u->servername;
4489 uint32 level = q_u->level;
4490 NEW_BUFFER *buffer = NULL;
4491 uint32 offered = q_u->offered;
4492 uint32 *needed = &r_u->needed;
4493 uint32 *returned = &r_u->returned;
4495 fstring name;
4497 /* that's an [in out] buffer */
4498 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4499 buffer = r_u->buffer;
4501 DEBUG(4,("_spoolss_enumprinters\n"));
4503 *needed=0;
4504 *returned=0;
4507 * Level 1:
4508 * flags==PRINTER_ENUM_NAME
4509 * if name=="" then enumerates all printers
4510 * if name!="" then enumerate the printer
4511 * flags==PRINTER_ENUM_REMOTE
4512 * name is NULL, enumerate printers
4513 * Level 2: name!="" enumerates printers, name can't be NULL
4514 * Level 3: doesn't exist
4515 * Level 4: does a local registry lookup
4516 * Level 5: same as Level 2
4519 unistr2_to_ascii(name, servername, sizeof(name)-1);
4520 strupper(name);
4522 switch (level) {
4523 case 1:
4524 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4525 case 2:
4526 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4527 case 5:
4528 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4529 case 3:
4530 case 4:
4531 break;
4533 return WERR_UNKNOWN_LEVEL;
4536 /****************************************************************************
4537 ****************************************************************************/
4539 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4541 PRINTER_INFO_0 *printer=NULL;
4543 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4544 return WERR_NOMEM;
4546 construct_printer_info_0(printer, snum);
4548 /* check the required size. */
4549 *needed += spoolss_size_printer_info_0(printer);
4551 if (!alloc_buffer_size(buffer, *needed)) {
4552 SAFE_FREE(printer);
4553 return WERR_INSUFFICIENT_BUFFER;
4556 /* fill the buffer with the structures */
4557 smb_io_printer_info_0("", buffer, printer, 0);
4559 /* clear memory */
4560 SAFE_FREE(printer);
4562 if (*needed > offered) {
4563 return WERR_INSUFFICIENT_BUFFER;
4566 return WERR_OK;
4569 /****************************************************************************
4570 ****************************************************************************/
4572 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4574 PRINTER_INFO_1 *printer=NULL;
4576 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4577 return WERR_NOMEM;
4579 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4581 /* check the required size. */
4582 *needed += spoolss_size_printer_info_1(printer);
4584 if (!alloc_buffer_size(buffer, *needed)) {
4585 SAFE_FREE(printer);
4586 return WERR_INSUFFICIENT_BUFFER;
4589 /* fill the buffer with the structures */
4590 smb_io_printer_info_1("", buffer, printer, 0);
4592 /* clear memory */
4593 SAFE_FREE(printer);
4595 if (*needed > offered) {
4596 return WERR_INSUFFICIENT_BUFFER;
4599 return WERR_OK;
4602 /****************************************************************************
4603 ****************************************************************************/
4605 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4607 PRINTER_INFO_2 *printer=NULL;
4609 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4610 return WERR_NOMEM;
4612 construct_printer_info_2(printer, snum);
4614 /* check the required size. */
4615 *needed += spoolss_size_printer_info_2(printer);
4617 if (!alloc_buffer_size(buffer, *needed)) {
4618 free_printer_info_2(printer);
4619 return WERR_INSUFFICIENT_BUFFER;
4622 /* fill the buffer with the structures */
4623 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4624 free_printer_info_2(printer);
4625 return WERR_NOMEM;
4628 /* clear memory */
4629 free_printer_info_2(printer);
4631 if (*needed > offered) {
4632 return WERR_INSUFFICIENT_BUFFER;
4635 return WERR_OK;
4638 /****************************************************************************
4639 ****************************************************************************/
4641 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4643 PRINTER_INFO_3 *printer=NULL;
4645 if (!construct_printer_info_3(&printer, snum))
4646 return WERR_NOMEM;
4648 /* check the required size. */
4649 *needed += spoolss_size_printer_info_3(printer);
4651 if (!alloc_buffer_size(buffer, *needed)) {
4652 free_printer_info_3(printer);
4653 return WERR_INSUFFICIENT_BUFFER;
4656 /* fill the buffer with the structures */
4657 smb_io_printer_info_3("", buffer, printer, 0);
4659 /* clear memory */
4660 free_printer_info_3(printer);
4662 if (*needed > offered) {
4663 return WERR_INSUFFICIENT_BUFFER;
4666 return WERR_OK;
4669 /****************************************************************************
4670 ****************************************************************************/
4672 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4674 PRINTER_INFO_4 *printer=NULL;
4676 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4677 return WERR_NOMEM;
4679 if (!construct_printer_info_4(printer, snum))
4680 return WERR_NOMEM;
4682 /* check the required size. */
4683 *needed += spoolss_size_printer_info_4(printer);
4685 if (!alloc_buffer_size(buffer, *needed)) {
4686 free_printer_info_4(printer);
4687 return WERR_INSUFFICIENT_BUFFER;
4690 /* fill the buffer with the structures */
4691 smb_io_printer_info_4("", buffer, printer, 0);
4693 /* clear memory */
4694 free_printer_info_4(printer);
4696 if (*needed > offered) {
4697 return WERR_INSUFFICIENT_BUFFER;
4700 return WERR_OK;
4703 /****************************************************************************
4704 ****************************************************************************/
4706 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4708 PRINTER_INFO_5 *printer=NULL;
4710 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4711 return WERR_NOMEM;
4713 if (!construct_printer_info_5(printer, snum))
4714 return WERR_NOMEM;
4716 /* check the required size. */
4717 *needed += spoolss_size_printer_info_5(printer);
4719 if (!alloc_buffer_size(buffer, *needed)) {
4720 free_printer_info_5(printer);
4721 return WERR_INSUFFICIENT_BUFFER;
4724 /* fill the buffer with the structures */
4725 smb_io_printer_info_5("", buffer, printer, 0);
4727 /* clear memory */
4728 free_printer_info_5(printer);
4730 if (*needed > offered) {
4731 return WERR_INSUFFICIENT_BUFFER;
4734 return WERR_OK;
4737 static WERROR getprinter_level_7(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4739 PRINTER_INFO_7 *printer=NULL;
4741 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4742 return WERR_NOMEM;
4744 if (!construct_printer_info_7(printer, snum))
4745 return WERR_NOMEM;
4747 /* check the required size. */
4748 *needed += spoolss_size_printer_info_7(printer);
4750 if (!alloc_buffer_size(buffer, *needed)) {
4751 free_printer_info_7(printer);
4752 return WERR_INSUFFICIENT_BUFFER;
4755 /* fill the buffer with the structures */
4756 smb_io_printer_info_7("", buffer, printer, 0);
4758 /* clear memory */
4759 free_printer_info_7(printer);
4761 if (*needed > offered) {
4762 return WERR_INSUFFICIENT_BUFFER;
4765 return WERR_OK;
4768 /****************************************************************************
4769 ****************************************************************************/
4771 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4773 POLICY_HND *handle = &q_u->handle;
4774 uint32 level = q_u->level;
4775 NEW_BUFFER *buffer = NULL;
4776 uint32 offered = q_u->offered;
4777 uint32 *needed = &r_u->needed;
4779 int snum;
4781 /* that's an [in out] buffer */
4782 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4783 buffer = r_u->buffer;
4785 *needed=0;
4787 if (!get_printer_snum(p, handle, &snum))
4788 return WERR_BADFID;
4790 switch (level) {
4791 case 0:
4792 return getprinter_level_0(snum, buffer, offered, needed);
4793 case 1:
4794 return getprinter_level_1(snum, buffer, offered, needed);
4795 case 2:
4796 return getprinter_level_2(snum, buffer, offered, needed);
4797 case 3:
4798 return getprinter_level_3(snum, buffer, offered, needed);
4799 case 4:
4800 return getprinter_level_4(snum, buffer, offered, needed);
4801 case 5:
4802 return getprinter_level_5(snum, buffer, offered, needed);
4803 case 7:
4804 return getprinter_level_7(snum, buffer, offered, needed);
4806 return WERR_UNKNOWN_LEVEL;
4809 /********************************************************************
4810 * fill a DRIVER_INFO_1 struct
4811 ********************************************************************/
4813 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4815 init_unistr( &info->name, driver.info_3->name);
4818 /********************************************************************
4819 * construct_printer_driver_info_1
4820 ********************************************************************/
4822 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4824 NT_PRINTER_INFO_LEVEL *printer = NULL;
4825 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4827 ZERO_STRUCT(driver);
4829 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4830 return WERR_INVALID_PRINTER_NAME;
4832 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4833 return WERR_UNKNOWN_PRINTER_DRIVER;
4835 fill_printer_driver_info_1(info, driver, servername, architecture);
4837 free_a_printer(&printer,2);
4839 return WERR_OK;
4842 /********************************************************************
4843 * construct_printer_driver_info_2
4844 * fill a printer_info_2 struct
4845 ********************************************************************/
4847 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4849 pstring temp;
4851 info->version=driver.info_3->cversion;
4853 init_unistr( &info->name, driver.info_3->name );
4854 init_unistr( &info->architecture, driver.info_3->environment );
4857 if (strlen(driver.info_3->driverpath)) {
4858 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4859 init_unistr( &info->driverpath, temp );
4860 } else
4861 init_unistr( &info->driverpath, "" );
4863 if (strlen(driver.info_3->datafile)) {
4864 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4865 init_unistr( &info->datafile, temp );
4866 } else
4867 init_unistr( &info->datafile, "" );
4869 if (strlen(driver.info_3->configfile)) {
4870 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4871 init_unistr( &info->configfile, temp );
4872 } else
4873 init_unistr( &info->configfile, "" );
4876 /********************************************************************
4877 * construct_printer_driver_info_2
4878 * fill a printer_info_2 struct
4879 ********************************************************************/
4881 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4883 NT_PRINTER_INFO_LEVEL *printer = NULL;
4884 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4886 ZERO_STRUCT(printer);
4887 ZERO_STRUCT(driver);
4889 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4890 return WERR_INVALID_PRINTER_NAME;
4892 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4893 return WERR_UNKNOWN_PRINTER_DRIVER;
4895 fill_printer_driver_info_2(info, driver, servername);
4897 free_a_printer(&printer,2);
4899 return WERR_OK;
4902 /********************************************************************
4903 * copy a strings array and convert to UNICODE
4905 * convert an array of ascii string to a UNICODE string
4906 ********************************************************************/
4908 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
4910 int i=0;
4911 int j=0;
4912 const char *v;
4913 pstring line;
4914 uint16 *tuary;
4916 DEBUG(6,("init_unistr_array\n"));
4917 *uni_array=NULL;
4919 while (True)
4921 if ( !char_array )
4922 v = "";
4923 else
4925 v = char_array[i];
4926 if (!v)
4927 v = ""; /* hack to handle null lists */
4930 /* hack to allow this to be used in places other than when generating
4931 the list of dependent files */
4933 if ( servername )
4934 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4935 else
4936 pstrcpy( line, v );
4938 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4940 /* add one extra unit16 for the second terminating NULL */
4942 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4943 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4944 return 0;
4945 } else
4946 *uni_array = tuary;
4948 if ( !strlen(v) )
4949 break;
4951 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4952 i++;
4955 if (*uni_array) {
4956 /* special case for ""; we need to add both NULL's here */
4957 if (!j)
4958 (*uni_array)[j++]=0x0000;
4959 (*uni_array)[j]=0x0000;
4962 DEBUGADD(6,("last one:done\n"));
4964 /* return size of array in uint16's */
4966 return j+1;
4969 /********************************************************************
4970 * construct_printer_info_3
4971 * fill a printer_info_3 struct
4972 ********************************************************************/
4974 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4976 pstring temp;
4978 ZERO_STRUCTP(info);
4980 info->version=driver.info_3->cversion;
4982 init_unistr( &info->name, driver.info_3->name );
4983 init_unistr( &info->architecture, driver.info_3->environment );
4985 if (strlen(driver.info_3->driverpath)) {
4986 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4987 init_unistr( &info->driverpath, temp );
4988 } else
4989 init_unistr( &info->driverpath, "" );
4991 if (strlen(driver.info_3->datafile)) {
4992 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4993 init_unistr( &info->datafile, temp );
4994 } else
4995 init_unistr( &info->datafile, "" );
4997 if (strlen(driver.info_3->configfile)) {
4998 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4999 init_unistr( &info->configfile, temp );
5000 } else
5001 init_unistr( &info->configfile, "" );
5003 if (strlen(driver.info_3->helpfile)) {
5004 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5005 init_unistr( &info->helpfile, temp );
5006 } else
5007 init_unistr( &info->helpfile, "" );
5009 init_unistr( &info->monitorname, driver.info_3->monitorname );
5010 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5012 info->dependentfiles=NULL;
5013 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5016 /********************************************************************
5017 * construct_printer_info_3
5018 * fill a printer_info_3 struct
5019 ********************************************************************/
5021 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5023 NT_PRINTER_INFO_LEVEL *printer = NULL;
5024 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5025 WERROR status;
5026 ZERO_STRUCT(driver);
5028 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5029 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5030 if (!W_ERROR_IS_OK(status))
5031 return WERR_INVALID_PRINTER_NAME;
5033 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5034 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5036 #if 0 /* JERRY */
5039 * I put this code in during testing. Helpful when commenting out the
5040 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5041 * as win2k always queries the driver using an infor level of 6.
5042 * I've left it in (but ifdef'd out) because I'll probably
5043 * use it in experimentation again in the future. --jerry 22/01/2002
5046 if (!W_ERROR_IS_OK(status)) {
5048 * Is this a W2k client ?
5050 if (version == 3) {
5051 /* Yes - try again with a WinNT driver. */
5052 version = 2;
5053 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5054 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5056 #endif
5058 if (!W_ERROR_IS_OK(status)) {
5059 free_a_printer(&printer,2);
5060 return WERR_UNKNOWN_PRINTER_DRIVER;
5063 #if 0 /* JERRY */
5065 #endif
5068 fill_printer_driver_info_3(info, driver, servername);
5070 free_a_printer(&printer,2);
5072 return WERR_OK;
5075 /********************************************************************
5076 * construct_printer_info_6
5077 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5078 ********************************************************************/
5080 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5082 pstring temp;
5083 fstring nullstr;
5085 ZERO_STRUCTP(info);
5086 memset(&nullstr, '\0', sizeof(fstring));
5088 info->version=driver.info_3->cversion;
5090 init_unistr( &info->name, driver.info_3->name );
5091 init_unistr( &info->architecture, driver.info_3->environment );
5093 if (strlen(driver.info_3->driverpath)) {
5094 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5095 init_unistr( &info->driverpath, temp );
5096 } else
5097 init_unistr( &info->driverpath, "" );
5099 if (strlen(driver.info_3->datafile)) {
5100 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5101 init_unistr( &info->datafile, temp );
5102 } else
5103 init_unistr( &info->datafile, "" );
5105 if (strlen(driver.info_3->configfile)) {
5106 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5107 init_unistr( &info->configfile, temp );
5108 } else
5109 init_unistr( &info->configfile, "" );
5111 if (strlen(driver.info_3->helpfile)) {
5112 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5113 init_unistr( &info->helpfile, temp );
5114 } else
5115 init_unistr( &info->helpfile, "" );
5117 init_unistr( &info->monitorname, driver.info_3->monitorname );
5118 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5120 info->dependentfiles = NULL;
5121 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5123 info->previousdrivernames=NULL;
5124 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5126 info->driver_date.low=0;
5127 info->driver_date.high=0;
5129 info->padding=0;
5130 info->driver_version_low=0;
5131 info->driver_version_high=0;
5133 init_unistr( &info->mfgname, "");
5134 init_unistr( &info->oem_url, "");
5135 init_unistr( &info->hardware_id, "");
5136 init_unistr( &info->provider, "");
5139 /********************************************************************
5140 * construct_printer_info_6
5141 * fill a printer_info_6 struct
5142 ********************************************************************/
5144 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5145 fstring servername, fstring architecture, uint32 version)
5147 NT_PRINTER_INFO_LEVEL *printer = NULL;
5148 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5149 WERROR status;
5151 ZERO_STRUCT(driver);
5153 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5155 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5157 if (!W_ERROR_IS_OK(status))
5158 return WERR_INVALID_PRINTER_NAME;
5160 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5162 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5164 if (!W_ERROR_IS_OK(status))
5167 * Is this a W2k client ?
5170 if (version < 3) {
5171 free_a_printer(&printer,2);
5172 return WERR_UNKNOWN_PRINTER_DRIVER;
5175 /* Yes - try again with a WinNT driver. */
5176 version = 2;
5177 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5178 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5179 if (!W_ERROR_IS_OK(status)) {
5180 free_a_printer(&printer,2);
5181 return WERR_UNKNOWN_PRINTER_DRIVER;
5185 fill_printer_driver_info_6(info, driver, servername);
5187 free_a_printer(&printer,2);
5188 free_a_printer_driver(driver, 3);
5190 return WERR_OK;
5193 /****************************************************************************
5194 ****************************************************************************/
5196 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5198 SAFE_FREE(info->dependentfiles);
5201 /****************************************************************************
5202 ****************************************************************************/
5204 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5206 SAFE_FREE(info->dependentfiles);
5210 /****************************************************************************
5211 ****************************************************************************/
5213 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5215 DRIVER_INFO_1 *info=NULL;
5216 WERROR status;
5218 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5219 return WERR_NOMEM;
5221 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5222 if (!W_ERROR_IS_OK(status)) {
5223 SAFE_FREE(info);
5224 return status;
5227 /* check the required size. */
5228 *needed += spoolss_size_printer_driver_info_1(info);
5230 if (!alloc_buffer_size(buffer, *needed)) {
5231 SAFE_FREE(info);
5232 return WERR_INSUFFICIENT_BUFFER;
5235 /* fill the buffer with the structures */
5236 smb_io_printer_driver_info_1("", buffer, info, 0);
5238 /* clear memory */
5239 SAFE_FREE(info);
5241 if (*needed > offered)
5242 return WERR_INSUFFICIENT_BUFFER;
5244 return WERR_OK;
5247 /****************************************************************************
5248 ****************************************************************************/
5250 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5252 DRIVER_INFO_2 *info=NULL;
5253 WERROR status;
5255 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5256 return WERR_NOMEM;
5258 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5259 if (!W_ERROR_IS_OK(status)) {
5260 SAFE_FREE(info);
5261 return status;
5264 /* check the required size. */
5265 *needed += spoolss_size_printer_driver_info_2(info);
5267 if (!alloc_buffer_size(buffer, *needed)) {
5268 SAFE_FREE(info);
5269 return WERR_INSUFFICIENT_BUFFER;
5272 /* fill the buffer with the structures */
5273 smb_io_printer_driver_info_2("", buffer, info, 0);
5275 /* clear memory */
5276 SAFE_FREE(info);
5278 if (*needed > offered)
5279 return WERR_INSUFFICIENT_BUFFER;
5281 return WERR_OK;
5284 /****************************************************************************
5285 ****************************************************************************/
5287 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5289 DRIVER_INFO_3 info;
5290 WERROR status;
5292 ZERO_STRUCT(info);
5294 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5295 if (!W_ERROR_IS_OK(status)) {
5296 return status;
5299 /* check the required size. */
5300 *needed += spoolss_size_printer_driver_info_3(&info);
5302 if (!alloc_buffer_size(buffer, *needed)) {
5303 free_printer_driver_info_3(&info);
5304 return WERR_INSUFFICIENT_BUFFER;
5307 /* fill the buffer with the structures */
5308 smb_io_printer_driver_info_3("", buffer, &info, 0);
5310 free_printer_driver_info_3(&info);
5312 if (*needed > offered)
5313 return WERR_INSUFFICIENT_BUFFER;
5315 return WERR_OK;
5318 /****************************************************************************
5319 ****************************************************************************/
5321 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5323 DRIVER_INFO_6 info;
5324 WERROR status;
5326 ZERO_STRUCT(info);
5328 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5329 if (!W_ERROR_IS_OK(status)) {
5330 return status;
5333 /* check the required size. */
5334 *needed += spoolss_size_printer_driver_info_6(&info);
5336 if (!alloc_buffer_size(buffer, *needed)) {
5337 free_printer_driver_info_6(&info);
5338 return WERR_INSUFFICIENT_BUFFER;
5341 /* fill the buffer with the structures */
5342 smb_io_printer_driver_info_6("", buffer, &info, 0);
5344 free_printer_driver_info_6(&info);
5346 if (*needed > offered)
5347 return WERR_INSUFFICIENT_BUFFER;
5349 return WERR_OK;
5352 /****************************************************************************
5353 ****************************************************************************/
5355 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5357 POLICY_HND *handle = &q_u->handle;
5358 UNISTR2 *uni_arch = &q_u->architecture;
5359 uint32 level = q_u->level;
5360 uint32 clientmajorversion = q_u->clientmajorversion;
5361 NEW_BUFFER *buffer = NULL;
5362 uint32 offered = q_u->offered;
5363 uint32 *needed = &r_u->needed;
5364 uint32 *servermajorversion = &r_u->servermajorversion;
5365 uint32 *serverminorversion = &r_u->serverminorversion;
5367 fstring servername;
5368 fstring architecture;
5369 int snum;
5371 /* that's an [in out] buffer */
5372 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5373 buffer = r_u->buffer;
5375 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5377 *needed = 0;
5378 *servermajorversion = 0;
5379 *serverminorversion = 0;
5381 pstrcpy(servername, get_called_name());
5382 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5384 if (!get_printer_snum(p, handle, &snum))
5385 return WERR_BADFID;
5387 switch (level) {
5388 case 1:
5389 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5390 case 2:
5391 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5392 case 3:
5393 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5394 case 6:
5395 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5398 return WERR_UNKNOWN_LEVEL;
5401 /****************************************************************************
5402 ****************************************************************************/
5404 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5406 POLICY_HND *handle = &q_u->handle;
5408 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5410 if (!Printer) {
5411 DEBUG(3,("Error in startpageprinter printer handle\n"));
5412 return WERR_BADFID;
5415 Printer->page_started=True;
5416 return WERR_OK;
5419 /****************************************************************************
5420 ****************************************************************************/
5422 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5424 POLICY_HND *handle = &q_u->handle;
5425 int snum;
5427 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5429 if (!Printer) {
5430 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5431 return WERR_BADFID;
5434 if (!get_printer_snum(p, handle, &snum))
5435 return WERR_BADFID;
5437 Printer->page_started=False;
5438 print_job_endpage(snum, Printer->jobid);
5440 return WERR_OK;
5443 /********************************************************************
5444 * api_spoolss_getprinter
5445 * called from the spoolss dispatcher
5447 ********************************************************************/
5449 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5451 POLICY_HND *handle = &q_u->handle;
5452 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5453 uint32 *jobid = &r_u->jobid;
5455 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5456 int snum;
5457 pstring jobname;
5458 fstring datatype;
5459 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5460 struct current_user user;
5462 if (!Printer) {
5463 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5464 return WERR_BADFID;
5467 get_current_user(&user, p);
5470 * a nice thing with NT is it doesn't listen to what you tell it.
5471 * when asked to send _only_ RAW datas, it tries to send datas
5472 * in EMF format.
5474 * So I add checks like in NT Server ...
5477 if (info_1->p_datatype != 0) {
5478 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5479 if (strcmp(datatype, "RAW") != 0) {
5480 (*jobid)=0;
5481 return WERR_INVALID_DATATYPE;
5485 /* get the share number of the printer */
5486 if (!get_printer_snum(p, handle, &snum)) {
5487 return WERR_BADFID;
5490 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5492 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5494 /* An error occured in print_job_start() so return an appropriate
5495 NT error code. */
5497 if (Printer->jobid == -1) {
5498 return map_werror_from_unix(errno);
5501 Printer->document_started=True;
5502 (*jobid) = Printer->jobid;
5504 return WERR_OK;
5507 /********************************************************************
5508 * api_spoolss_getprinter
5509 * called from the spoolss dispatcher
5511 ********************************************************************/
5513 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5515 POLICY_HND *handle = &q_u->handle;
5517 return _spoolss_enddocprinter_internal(p, handle);
5520 /****************************************************************************
5521 ****************************************************************************/
5523 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5525 POLICY_HND *handle = &q_u->handle;
5526 uint32 buffer_size = q_u->buffer_size;
5527 uint8 *buffer = q_u->buffer;
5528 uint32 *buffer_written = &q_u->buffer_size2;
5529 int snum;
5530 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5532 if (!Printer) {
5533 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5534 r_u->buffer_written = q_u->buffer_size2;
5535 return WERR_BADFID;
5538 if (!get_printer_snum(p, handle, &snum))
5539 return WERR_BADFID;
5541 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5542 if (*buffer_written == -1) {
5543 r_u->buffer_written = 0;
5544 if (errno == ENOSPC)
5545 return WERR_NO_SPOOL_SPACE;
5546 else
5547 return WERR_ACCESS_DENIED;
5550 r_u->buffer_written = q_u->buffer_size2;
5552 return WERR_OK;
5555 /********************************************************************
5556 * api_spoolss_getprinter
5557 * called from the spoolss dispatcher
5559 ********************************************************************/
5561 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5562 pipes_struct *p)
5564 struct current_user user;
5565 int snum;
5566 WERROR errcode = WERR_BADFUNC;
5567 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5569 get_current_user(&user, p);
5571 if (!Printer) {
5572 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5573 return WERR_BADFID;
5576 if (!get_printer_snum(p, handle, &snum))
5577 return WERR_BADFID;
5579 switch (command) {
5580 case PRINTER_CONTROL_PAUSE:
5581 if (print_queue_pause(&user, snum, &errcode)) {
5582 errcode = WERR_OK;
5584 break;
5585 case PRINTER_CONTROL_RESUME:
5586 case PRINTER_CONTROL_UNPAUSE:
5587 if (print_queue_resume(&user, snum, &errcode)) {
5588 errcode = WERR_OK;
5590 break;
5591 case PRINTER_CONTROL_PURGE:
5592 if (print_queue_purge(&user, snum, &errcode)) {
5593 errcode = WERR_OK;
5595 break;
5596 default:
5597 return WERR_UNKNOWN_LEVEL;
5600 return errcode;
5603 /********************************************************************
5604 * api_spoolss_abortprinter
5605 * From MSDN: "Deletes printer's spool file if printer is configured
5606 * for spooling"
5607 ********************************************************************/
5609 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5611 POLICY_HND *handle = &q_u->handle;
5612 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5613 int snum;
5614 struct current_user user;
5615 WERROR errcode = WERR_OK;
5617 if (!Printer) {
5618 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5619 return WERR_BADFID;
5622 if (!get_printer_snum(p, handle, &snum))
5623 return WERR_BADFID;
5625 get_current_user( &user, p );
5627 print_job_delete( &user, snum, Printer->jobid, &errcode );
5629 return errcode;
5632 /********************************************************************
5633 * called by spoolss_api_setprinter
5634 * when updating a printer description
5635 ********************************************************************/
5637 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5638 const SPOOL_PRINTER_INFO_LEVEL *info,
5639 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5641 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5642 struct current_user user;
5643 WERROR result;
5644 int snum;
5646 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5648 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5649 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5650 OUR_HANDLE(handle)));
5652 result = WERR_BADFID;
5653 goto done;
5656 /* NT seems to like setting the security descriptor even though
5657 nothing may have actually changed. This causes annoying
5658 dialog boxes when the user doesn't have permission to change
5659 the security descriptor. */
5661 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5663 if (DEBUGLEVEL >= 10) {
5664 SEC_ACL *the_acl;
5665 int i;
5667 the_acl = old_secdesc_ctr->sec->dacl;
5668 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5669 PRINTERNAME(snum), the_acl->num_aces));
5671 for (i = 0; i < the_acl->num_aces; i++) {
5672 fstring sid_str;
5674 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5676 DEBUG(10, ("%s 0x%08x\n", sid_str,
5677 the_acl->ace[i].info.mask));
5680 the_acl = secdesc_ctr->sec->dacl;
5682 if (the_acl) {
5683 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5684 PRINTERNAME(snum), the_acl->num_aces));
5686 for (i = 0; i < the_acl->num_aces; i++) {
5687 fstring sid_str;
5689 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5691 DEBUG(10, ("%s 0x%08x\n", sid_str,
5692 the_acl->ace[i].info.mask));
5694 } else {
5695 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5699 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5701 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5702 result = WERR_OK;
5703 goto done;
5706 /* Work out which user is performing the operation */
5708 get_current_user(&user, p);
5710 /* Check the user has permissions to change the security
5711 descriptor. By experimentation with two NT machines, the user
5712 requires Full Access to the printer to change security
5713 information. */
5715 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5716 result = WERR_ACCESS_DENIED;
5717 goto done;
5720 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5722 done:
5724 return result;
5727 /********************************************************************
5728 Do Samba sanity checks on a printer info struct.
5729 this has changed purpose: it now "canonicalises" printer
5730 info from a client rather than just checking it is correct
5731 ********************************************************************/
5733 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5735 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5736 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5738 /* we force some elements to "correct" values */
5739 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5740 fstrcpy(info->sharename, lp_servicename(snum));
5741 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5742 get_called_name(), info->sharename);
5743 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5745 return True;
5748 /****************************************************************************
5749 ****************************************************************************/
5751 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5753 extern userdom_struct current_user_info;
5754 char *cmd = lp_addprinter_cmd();
5755 char **qlines;
5756 pstring command;
5757 int numlines;
5758 int ret;
5759 int fd;
5760 fstring remote_machine = "%m";
5762 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5764 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5765 cmd, printer->info_2->printername, printer->info_2->sharename,
5766 printer->info_2->portname, printer->info_2->drivername,
5767 printer->info_2->location, printer->info_2->comment, remote_machine);
5769 DEBUG(10,("Running [%s]\n", command));
5770 ret = smbrun(command, &fd);
5771 DEBUGADD(10,("returned [%d]\n", ret));
5773 if ( ret != 0 ) {
5774 if (fd != -1)
5775 close(fd);
5776 return False;
5779 numlines = 0;
5780 /* Get lines and convert them back to dos-codepage */
5781 qlines = fd_lines_load(fd, &numlines);
5782 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5783 close(fd);
5785 if(numlines) {
5786 /* Set the portname to what the script says the portname should be. */
5787 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5788 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5790 /* Send SIGHUP to process group... is there a better way? */
5791 kill(0, SIGHUP);
5793 /* reload our services immediately */
5794 reload_services( False );
5797 file_lines_free(qlines);
5798 return True;
5801 /********************************************************************
5802 * Called by spoolss_api_setprinter
5803 * when updating a printer description.
5804 ********************************************************************/
5806 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5807 const SPOOL_PRINTER_INFO_LEVEL *info,
5808 DEVICEMODE *devmode)
5810 int snum;
5811 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5812 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5813 WERROR result;
5815 DEBUG(8,("update_printer\n"));
5817 result = WERR_OK;
5819 if (level!=2) {
5820 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5821 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5822 result = WERR_UNKNOWN_LEVEL;
5823 goto done;
5826 if (!Printer) {
5827 result = WERR_BADFID;
5828 goto done;
5831 if (!get_printer_snum(p, handle, &snum)) {
5832 result = WERR_BADFID;
5833 goto done;
5836 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5837 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5838 result = WERR_BADFID;
5839 goto done;
5842 DEBUGADD(8,("Converting info_2 struct\n"));
5845 * convert_printer_info converts the incoming
5846 * info from the client and overwrites the info
5847 * just read from the tdb in the pointer 'printer'.
5850 if (!convert_printer_info(info, printer, level)) {
5851 result = WERR_NOMEM;
5852 goto done;
5855 if (devmode) {
5856 /* we have a valid devmode
5857 convert it and link it*/
5859 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5860 if (!convert_devicemode(printer->info_2->printername, devmode,
5861 &printer->info_2->devmode)) {
5862 result = WERR_NOMEM;
5863 goto done;
5867 * make sure we actually reload the services after
5868 * this as smb.conf could have a new section in it
5869 * .... shouldn't .... but could
5871 reload_services(False);
5874 /* Do sanity check on the requested changes for Samba */
5876 if (!check_printer_ok(printer->info_2, snum)) {
5877 result = WERR_INVALID_PARAM;
5878 goto done;
5881 /* Check calling user has permission to update printer description */
5883 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5884 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5885 result = WERR_ACCESS_DENIED;
5886 goto done;
5889 /* Call addprinter hook */
5890 /* Check changes to see if this is really needed */
5892 if ( *lp_addprinter_cmd()
5893 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5894 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5895 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5896 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5898 if ( !add_printer_hook(printer) ) {
5899 result = WERR_ACCESS_DENIED;
5900 goto done;
5905 * When a *new* driver is bound to a printer, the drivername is used to
5906 * lookup previously saved driver initialization info, which is then
5907 * bound to the printer, simulating what happens in the Windows arch.
5909 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5911 if (!set_driver_init(printer, 2))
5913 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5914 printer->info_2->drivername));
5917 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5918 printer->info_2->drivername));
5920 notify_printer_driver(snum, printer->info_2->drivername);
5923 /* Update printer info */
5924 result = mod_a_printer(*printer, 2);
5926 /* flag which changes actually occured. This is a small subset of
5927 all the possible changes */
5929 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5930 notify_printer_comment(snum, printer->info_2->comment);
5932 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5933 notify_printer_sharename(snum, printer->info_2->sharename);
5935 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5936 notify_printer_port(snum, printer->info_2->portname);
5938 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5939 notify_printer_location(snum, printer->info_2->location);
5941 done:
5942 free_a_printer(&printer, 2);
5943 free_a_printer(&old_printer, 2);
5946 return result;
5949 /****************************************************************************
5950 ****************************************************************************/
5951 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
5952 const SPOOL_PRINTER_INFO_LEVEL *info)
5954 #ifdef HAVE_ADS
5955 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
5956 int snum;
5957 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5958 WERROR result;
5960 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5962 result = WERR_OK;
5964 if (!Printer)
5965 return WERR_BADFID;
5967 if (!get_printer_snum(p, handle, &snum))
5968 return WERR_BADFID;
5970 nt_printer_publish(snum, info7->action);
5972 return WERR_OK;
5973 #else
5974 return WERR_UNKNOWN_LEVEL;
5975 #endif
5977 /****************************************************************************
5978 ****************************************************************************/
5980 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5982 POLICY_HND *handle = &q_u->handle;
5983 uint32 level = q_u->level;
5984 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5985 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5986 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5987 uint32 command = q_u->command;
5989 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5991 if (!Printer) {
5992 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5993 return WERR_BADFID;
5996 /* check the level */
5997 switch (level) {
5998 case 0:
5999 return control_printer(handle, command, p);
6000 case 2:
6001 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6002 case 3:
6003 return update_printer_sec(handle, level, info, p,
6004 secdesc_ctr);
6005 case 7:
6006 return publish_or_unpublish_printer(p, handle, info);
6007 default:
6008 return WERR_UNKNOWN_LEVEL;
6012 /****************************************************************************
6013 ****************************************************************************/
6015 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6017 POLICY_HND *handle = &q_u->handle;
6018 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6020 if (!Printer) {
6021 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6022 return WERR_BADFID;
6025 if (Printer->notify.client_connected==True) {
6026 int snum = -1;
6028 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6029 snum = -1;
6030 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6031 !get_printer_snum(p, handle, &snum) )
6032 return WERR_BADFID;
6034 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6037 Printer->notify.flags=0;
6038 Printer->notify.options=0;
6039 Printer->notify.localmachine[0]='\0';
6040 Printer->notify.printerlocal=0;
6041 if (Printer->notify.option)
6042 free_spool_notify_option(&Printer->notify.option);
6043 Printer->notify.client_connected=False;
6045 return WERR_OK;
6048 /****************************************************************************
6049 ****************************************************************************/
6051 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6053 /* that's an [in out] buffer (despite appearences to the contrary) */
6054 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6056 r_u->needed = 0;
6057 return WERR_INVALID_PARAM; /* this is what a NT server
6058 returns for AddJob. AddJob
6059 must fail on non-local
6060 printers */
6063 /****************************************************************************
6064 ****************************************************************************/
6066 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6067 int position, int snum)
6069 pstring temp_name;
6071 struct tm *t;
6073 t=gmtime(&queue->time);
6074 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6076 job_info->jobid=queue->job;
6077 init_unistr(&job_info->printername, lp_servicename(snum));
6078 init_unistr(&job_info->machinename, temp_name);
6079 init_unistr(&job_info->username, queue->fs_user);
6080 init_unistr(&job_info->document, queue->fs_file);
6081 init_unistr(&job_info->datatype, "RAW");
6082 init_unistr(&job_info->text_status, "");
6083 job_info->status=nt_printj_status(queue->status);
6084 job_info->priority=queue->priority;
6085 job_info->position=position;
6086 job_info->totalpages=queue->page_count;
6087 job_info->pagesprinted=0;
6089 make_systemtime(&job_info->submitted, t);
6092 /****************************************************************************
6093 ****************************************************************************/
6095 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6096 int position, int snum,
6097 NT_PRINTER_INFO_LEVEL *ntprinter,
6098 DEVICEMODE *devmode)
6100 pstring temp_name;
6101 pstring chaine;
6102 struct tm *t;
6104 t=gmtime(&queue->time);
6105 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6107 job_info->jobid=queue->job;
6109 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
6111 init_unistr(&job_info->printername, chaine);
6113 init_unistr(&job_info->machinename, temp_name);
6114 init_unistr(&job_info->username, queue->fs_user);
6115 init_unistr(&job_info->document, queue->fs_file);
6116 init_unistr(&job_info->notifyname, queue->fs_user);
6117 init_unistr(&job_info->datatype, "RAW");
6118 init_unistr(&job_info->printprocessor, "winprint");
6119 init_unistr(&job_info->parameters, "");
6120 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6121 init_unistr(&job_info->text_status, "");
6123 /* and here the security descriptor */
6125 job_info->status=nt_printj_status(queue->status);
6126 job_info->priority=queue->priority;
6127 job_info->position=position;
6128 job_info->starttime=0;
6129 job_info->untiltime=0;
6130 job_info->totalpages=queue->page_count;
6131 job_info->size=queue->size;
6132 make_systemtime(&(job_info->submitted), t);
6133 job_info->timeelapsed=0;
6134 job_info->pagesprinted=0;
6136 job_info->devmode = devmode;
6138 return (True);
6141 /****************************************************************************
6142 Enumjobs at level 1.
6143 ****************************************************************************/
6145 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6146 NEW_BUFFER *buffer, uint32 offered,
6147 uint32 *needed, uint32 *returned)
6149 JOB_INFO_1 *info;
6150 int i;
6152 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6153 if (info==NULL) {
6154 SAFE_FREE(queue);
6155 *returned=0;
6156 return WERR_NOMEM;
6159 for (i=0; i<*returned; i++)
6160 fill_job_info_1(&info[i], &queue[i], i, snum);
6162 SAFE_FREE(queue);
6164 /* check the required size. */
6165 for (i=0; i<*returned; i++)
6166 (*needed) += spoolss_size_job_info_1(&info[i]);
6168 if (!alloc_buffer_size(buffer, *needed)) {
6169 SAFE_FREE(info);
6170 return WERR_INSUFFICIENT_BUFFER;
6173 /* fill the buffer with the structures */
6174 for (i=0; i<*returned; i++)
6175 smb_io_job_info_1("", buffer, &info[i], 0);
6177 /* clear memory */
6178 SAFE_FREE(info);
6180 if (*needed > offered) {
6181 *returned=0;
6182 return WERR_INSUFFICIENT_BUFFER;
6185 return WERR_OK;
6188 /****************************************************************************
6189 Enumjobs at level 2.
6190 ****************************************************************************/
6192 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6193 NEW_BUFFER *buffer, uint32 offered,
6194 uint32 *needed, uint32 *returned)
6196 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6197 JOB_INFO_2 *info = NULL;
6198 int i;
6199 WERROR result;
6200 DEVICEMODE *devmode = NULL;
6202 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6203 if (info==NULL) {
6204 *returned=0;
6205 result = WERR_NOMEM;
6206 goto done;
6209 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6210 if (!W_ERROR_IS_OK(result)) {
6211 *returned = 0;
6212 goto done;
6215 /* this should not be a failure condition if the devmode is NULL */
6217 devmode = construct_dev_mode(snum);
6219 for (i=0; i<*returned; i++)
6220 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6221 devmode);
6223 free_a_printer(&ntprinter, 2);
6224 SAFE_FREE(queue);
6226 /* check the required size. */
6227 for (i=0; i<*returned; i++)
6228 (*needed) += spoolss_size_job_info_2(&info[i]);
6230 if (*needed > offered) {
6231 *returned=0;
6232 result = WERR_INSUFFICIENT_BUFFER;
6233 goto done;
6236 if (!alloc_buffer_size(buffer, *needed)) {
6237 SAFE_FREE(info);
6238 result = WERR_INSUFFICIENT_BUFFER;
6239 goto done;
6242 /* fill the buffer with the structures */
6243 for (i=0; i<*returned; i++)
6244 smb_io_job_info_2("", buffer, &info[i], 0);
6246 result = WERR_OK;
6248 done:
6249 free_a_printer(&ntprinter, 2);
6250 free_devmode(devmode);
6251 SAFE_FREE(queue);
6252 SAFE_FREE(info);
6254 return result;
6258 /****************************************************************************
6259 Enumjobs.
6260 ****************************************************************************/
6262 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6264 POLICY_HND *handle = &q_u->handle;
6265 uint32 level = q_u->level;
6266 NEW_BUFFER *buffer = NULL;
6267 uint32 offered = q_u->offered;
6268 uint32 *needed = &r_u->needed;
6269 uint32 *returned = &r_u->returned;
6271 int snum;
6272 print_status_struct prt_status;
6273 print_queue_struct *queue=NULL;
6275 /* that's an [in out] buffer */
6276 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6277 buffer = r_u->buffer;
6279 DEBUG(4,("_spoolss_enumjobs\n"));
6281 *needed=0;
6282 *returned=0;
6284 if (!get_printer_snum(p, handle, &snum))
6285 return WERR_BADFID;
6287 *returned = print_queue_status(snum, &queue, &prt_status);
6288 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6290 if (*returned == 0) {
6291 SAFE_FREE(queue);
6292 return WERR_OK;
6295 switch (level) {
6296 case 1:
6297 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6298 case 2:
6299 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6300 default:
6301 SAFE_FREE(queue);
6302 *returned=0;
6303 return WERR_UNKNOWN_LEVEL;
6307 /****************************************************************************
6308 ****************************************************************************/
6310 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6312 return WERR_OK;
6315 /****************************************************************************
6316 ****************************************************************************/
6318 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6320 POLICY_HND *handle = &q_u->handle;
6321 uint32 jobid = q_u->jobid;
6322 uint32 command = q_u->command;
6324 struct current_user user;
6325 int snum;
6326 WERROR errcode = WERR_BADFUNC;
6328 if (!get_printer_snum(p, handle, &snum)) {
6329 return WERR_BADFID;
6332 if (!print_job_exists(snum, jobid)) {
6333 return WERR_INVALID_PRINTER_NAME;
6336 get_current_user(&user, p);
6338 switch (command) {
6339 case JOB_CONTROL_CANCEL:
6340 case JOB_CONTROL_DELETE:
6341 if (print_job_delete(&user, snum, jobid, &errcode)) {
6342 errcode = WERR_OK;
6344 break;
6345 case JOB_CONTROL_PAUSE:
6346 if (print_job_pause(&user, snum, jobid, &errcode)) {
6347 errcode = WERR_OK;
6349 break;
6350 case JOB_CONTROL_RESTART:
6351 case JOB_CONTROL_RESUME:
6352 if (print_job_resume(&user, snum, jobid, &errcode)) {
6353 errcode = WERR_OK;
6355 break;
6356 default:
6357 return WERR_UNKNOWN_LEVEL;
6360 return errcode;
6363 /****************************************************************************
6364 Enumerates all printer drivers at level 1.
6365 ****************************************************************************/
6367 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6369 int i;
6370 int ndrivers;
6371 uint32 version;
6372 fstring *list = NULL;
6374 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6375 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6377 *returned=0;
6379 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6380 list=NULL;
6381 ndrivers=get_ntdrivers(&list, architecture, version);
6382 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6384 if(ndrivers == -1)
6385 return WERR_NOMEM;
6387 if(ndrivers != 0) {
6388 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6389 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6390 SAFE_FREE(driver_info_1);
6391 SAFE_FREE(list);
6392 return WERR_NOMEM;
6394 else driver_info_1 = tdi1;
6397 for (i=0; i<ndrivers; i++) {
6398 WERROR status;
6399 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6400 ZERO_STRUCT(driver);
6401 status = get_a_printer_driver(&driver, 3, list[i],
6402 architecture, version);
6403 if (!W_ERROR_IS_OK(status)) {
6404 SAFE_FREE(list);
6405 return status;
6407 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6408 free_a_printer_driver(driver, 3);
6411 *returned+=ndrivers;
6412 SAFE_FREE(list);
6415 /* check the required size. */
6416 for (i=0; i<*returned; i++) {
6417 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6418 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6421 if (!alloc_buffer_size(buffer, *needed)) {
6422 SAFE_FREE(driver_info_1);
6423 return WERR_INSUFFICIENT_BUFFER;
6426 /* fill the buffer with the driver structures */
6427 for (i=0; i<*returned; i++) {
6428 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6429 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6432 SAFE_FREE(driver_info_1);
6434 if (*needed > offered) {
6435 *returned=0;
6436 return WERR_INSUFFICIENT_BUFFER;
6439 return WERR_OK;
6442 /****************************************************************************
6443 Enumerates all printer drivers at level 2.
6444 ****************************************************************************/
6446 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6448 int i;
6449 int ndrivers;
6450 uint32 version;
6451 fstring *list = NULL;
6453 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6454 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6456 *returned=0;
6458 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6459 list=NULL;
6460 ndrivers=get_ntdrivers(&list, architecture, version);
6461 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6463 if(ndrivers == -1)
6464 return WERR_NOMEM;
6466 if(ndrivers != 0) {
6467 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6468 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6469 SAFE_FREE(driver_info_2);
6470 SAFE_FREE(list);
6471 return WERR_NOMEM;
6473 else driver_info_2 = tdi2;
6476 for (i=0; i<ndrivers; i++) {
6477 WERROR status;
6479 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6480 ZERO_STRUCT(driver);
6481 status = get_a_printer_driver(&driver, 3, list[i],
6482 architecture, version);
6483 if (!W_ERROR_IS_OK(status)) {
6484 SAFE_FREE(list);
6485 return status;
6487 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6488 free_a_printer_driver(driver, 3);
6491 *returned+=ndrivers;
6492 SAFE_FREE(list);
6495 /* check the required size. */
6496 for (i=0; i<*returned; i++) {
6497 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6498 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6501 if (!alloc_buffer_size(buffer, *needed)) {
6502 SAFE_FREE(driver_info_2);
6503 return WERR_INSUFFICIENT_BUFFER;
6506 /* fill the buffer with the form structures */
6507 for (i=0; i<*returned; i++) {
6508 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6509 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6512 SAFE_FREE(driver_info_2);
6514 if (*needed > offered) {
6515 *returned=0;
6516 return WERR_INSUFFICIENT_BUFFER;
6519 return WERR_OK;
6522 /****************************************************************************
6523 Enumerates all printer drivers at level 3.
6524 ****************************************************************************/
6526 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6528 int i;
6529 int ndrivers;
6530 uint32 version;
6531 fstring *list = NULL;
6533 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6534 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6536 *returned=0;
6538 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6539 list=NULL;
6540 ndrivers=get_ntdrivers(&list, architecture, version);
6541 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6543 if(ndrivers == -1)
6544 return WERR_NOMEM;
6546 if(ndrivers != 0) {
6547 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6548 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6549 SAFE_FREE(driver_info_3);
6550 SAFE_FREE(list);
6551 return WERR_NOMEM;
6553 else driver_info_3 = tdi3;
6556 for (i=0; i<ndrivers; i++) {
6557 WERROR status;
6559 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6560 ZERO_STRUCT(driver);
6561 status = get_a_printer_driver(&driver, 3, list[i],
6562 architecture, version);
6563 if (!W_ERROR_IS_OK(status)) {
6564 SAFE_FREE(list);
6565 return status;
6567 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6568 free_a_printer_driver(driver, 3);
6571 *returned+=ndrivers;
6572 SAFE_FREE(list);
6575 /* check the required size. */
6576 for (i=0; i<*returned; i++) {
6577 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6578 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6581 if (!alloc_buffer_size(buffer, *needed)) {
6582 SAFE_FREE(driver_info_3);
6583 return WERR_INSUFFICIENT_BUFFER;
6586 /* fill the buffer with the driver structures */
6587 for (i=0; i<*returned; i++) {
6588 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6589 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6592 for (i=0; i<*returned; i++)
6593 SAFE_FREE(driver_info_3[i].dependentfiles);
6595 SAFE_FREE(driver_info_3);
6597 if (*needed > offered) {
6598 *returned=0;
6599 return WERR_INSUFFICIENT_BUFFER;
6602 return WERR_OK;
6605 /****************************************************************************
6606 Enumerates all printer drivers.
6607 ****************************************************************************/
6609 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6611 UNISTR2 *environment = &q_u->environment;
6612 uint32 level = q_u->level;
6613 NEW_BUFFER *buffer = NULL;
6614 uint32 offered = q_u->offered;
6615 uint32 *needed = &r_u->needed;
6616 uint32 *returned = &r_u->returned;
6618 fstring *list = NULL;
6619 fstring servername;
6620 fstring architecture;
6622 /* that's an [in out] buffer */
6623 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6624 buffer = r_u->buffer;
6626 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6627 fstrcpy(servername, get_called_name());
6628 *needed=0;
6629 *returned=0;
6631 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6633 switch (level) {
6634 case 1:
6635 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6636 case 2:
6637 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6638 case 3:
6639 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6640 default:
6641 *returned=0;
6642 SAFE_FREE(list);
6643 return WERR_UNKNOWN_LEVEL;
6647 /****************************************************************************
6648 ****************************************************************************/
6650 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6652 form->flag=list->flag;
6653 init_unistr(&form->name, list->name);
6654 form->width=list->width;
6655 form->length=list->length;
6656 form->left=list->left;
6657 form->top=list->top;
6658 form->right=list->right;
6659 form->bottom=list->bottom;
6662 /****************************************************************************
6663 ****************************************************************************/
6665 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6667 uint32 level = q_u->level;
6668 NEW_BUFFER *buffer = NULL;
6669 uint32 offered = q_u->offered;
6670 uint32 *needed = &r_u->needed;
6671 uint32 *numofforms = &r_u->numofforms;
6672 uint32 numbuiltinforms;
6674 nt_forms_struct *list=NULL;
6675 nt_forms_struct *builtinlist=NULL;
6676 FORM_1 *forms_1;
6677 int buffer_size=0;
6678 int i;
6680 /* that's an [in out] buffer */
6681 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6682 buffer = r_u->buffer;
6684 DEBUG(4,("_spoolss_enumforms\n"));
6685 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6686 DEBUGADD(5,("Info level [%d]\n", level));
6688 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6689 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6690 *numofforms = get_ntforms(&list);
6691 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6692 *numofforms += numbuiltinforms;
6694 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6696 switch (level) {
6697 case 1:
6698 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6699 *numofforms=0;
6700 return WERR_NOMEM;
6703 /* construct the list of form structures */
6704 for (i=0; i<numbuiltinforms; i++) {
6705 DEBUGADD(6,("Filling form number [%d]\n",i));
6706 fill_form_1(&forms_1[i], &builtinlist[i]);
6709 SAFE_FREE(builtinlist);
6711 for (; i<*numofforms; i++) {
6712 DEBUGADD(6,("Filling form number [%d]\n",i));
6713 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6716 SAFE_FREE(list);
6718 /* check the required size. */
6719 for (i=0; i<numbuiltinforms; i++) {
6720 DEBUGADD(6,("adding form [%d]'s size\n",i));
6721 buffer_size += spoolss_size_form_1(&forms_1[i]);
6723 for (; i<*numofforms; i++) {
6724 DEBUGADD(6,("adding form [%d]'s size\n",i));
6725 buffer_size += spoolss_size_form_1(&forms_1[i]);
6728 *needed=buffer_size;
6730 if (!alloc_buffer_size(buffer, buffer_size)){
6731 SAFE_FREE(forms_1);
6732 return WERR_INSUFFICIENT_BUFFER;
6735 /* fill the buffer with the form structures */
6736 for (i=0; i<numbuiltinforms; i++) {
6737 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6738 smb_io_form_1("", buffer, &forms_1[i], 0);
6740 for (; i<*numofforms; i++) {
6741 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6742 smb_io_form_1("", buffer, &forms_1[i], 0);
6745 SAFE_FREE(forms_1);
6747 if (*needed > offered) {
6748 *numofforms=0;
6749 return WERR_INSUFFICIENT_BUFFER;
6751 else
6752 return WERR_OK;
6754 default:
6755 SAFE_FREE(list);
6756 SAFE_FREE(builtinlist);
6757 return WERR_UNKNOWN_LEVEL;
6762 /****************************************************************************
6763 ****************************************************************************/
6765 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6767 uint32 level = q_u->level;
6768 UNISTR2 *uni_formname = &q_u->formname;
6769 NEW_BUFFER *buffer = NULL;
6770 uint32 offered = q_u->offered;
6771 uint32 *needed = &r_u->needed;
6773 nt_forms_struct *list=NULL;
6774 nt_forms_struct builtin_form;
6775 BOOL foundBuiltin;
6776 FORM_1 form_1;
6777 fstring form_name;
6778 int buffer_size=0;
6779 int numofforms=0, i=0;
6781 /* that's an [in out] buffer */
6782 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6783 buffer = r_u->buffer;
6785 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6787 DEBUG(4,("_spoolss_getform\n"));
6788 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6789 DEBUGADD(5,("Info level [%d]\n", level));
6791 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6792 if (!foundBuiltin) {
6793 numofforms = get_ntforms(&list);
6794 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6796 if (numofforms == 0)
6797 return WERR_BADFID;
6800 switch (level) {
6801 case 1:
6802 if (foundBuiltin) {
6803 fill_form_1(&form_1, &builtin_form);
6804 } else {
6806 /* Check if the requested name is in the list of form structures */
6807 for (i=0; i<numofforms; i++) {
6809 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6811 if (strequal(form_name, list[i].name)) {
6812 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6813 fill_form_1(&form_1, &list[i]);
6814 break;
6818 SAFE_FREE(list);
6819 if (i == numofforms) {
6820 return WERR_BADFID;
6823 /* check the required size. */
6825 *needed=spoolss_size_form_1(&form_1);
6827 if (!alloc_buffer_size(buffer, buffer_size)){
6828 return WERR_INSUFFICIENT_BUFFER;
6831 if (*needed > offered) {
6832 return WERR_INSUFFICIENT_BUFFER;
6835 /* fill the buffer with the form structures */
6836 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6837 smb_io_form_1("", buffer, &form_1, 0);
6839 return WERR_OK;
6841 default:
6842 SAFE_FREE(list);
6843 return WERR_UNKNOWN_LEVEL;
6847 /****************************************************************************
6848 ****************************************************************************/
6850 static void fill_port_1(PORT_INFO_1 *port, const char *name)
6852 init_unistr(&port->port_name, name);
6855 /****************************************************************************
6856 ****************************************************************************/
6858 static void fill_port_2(PORT_INFO_2 *port, const char *name)
6860 init_unistr(&port->port_name, name);
6861 init_unistr(&port->monitor_name, "Local Monitor");
6862 init_unistr(&port->description, "Local Port");
6863 #define PORT_TYPE_WRITE 1
6864 port->port_type=PORT_TYPE_WRITE;
6865 port->reserved=0x0;
6868 /****************************************************************************
6869 enumports level 1.
6870 ****************************************************************************/
6872 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6874 PORT_INFO_1 *ports=NULL;
6875 int i=0;
6877 if (*lp_enumports_cmd()) {
6878 char *cmd = lp_enumports_cmd();
6879 char **qlines;
6880 pstring command;
6881 int numlines;
6882 int ret;
6883 int fd;
6885 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6887 DEBUG(10,("Running [%s]\n", command));
6888 ret = smbrun(command, &fd);
6889 DEBUG(10,("Returned [%d]\n", ret));
6890 if (ret != 0) {
6891 if (fd != -1)
6892 close(fd);
6893 /* Is this the best error to return here? */
6894 return WERR_ACCESS_DENIED;
6897 numlines = 0;
6898 qlines = fd_lines_load(fd, &numlines);
6899 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6900 close(fd);
6902 if(numlines) {
6903 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6904 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6905 dos_errstr(WERR_NOMEM)));
6906 file_lines_free(qlines);
6907 return WERR_NOMEM;
6910 for (i=0; i<numlines; i++) {
6911 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6912 fill_port_1(&ports[i], qlines[i]);
6915 file_lines_free(qlines);
6918 *returned = numlines;
6920 } else {
6921 *returned = 1; /* Sole Samba port returned. */
6923 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6924 return WERR_NOMEM;
6926 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6928 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6931 /* check the required size. */
6932 for (i=0; i<*returned; i++) {
6933 DEBUGADD(6,("adding port [%d]'s size\n", i));
6934 *needed += spoolss_size_port_info_1(&ports[i]);
6937 if (!alloc_buffer_size(buffer, *needed)) {
6938 SAFE_FREE(ports);
6939 return WERR_INSUFFICIENT_BUFFER;
6942 /* fill the buffer with the ports structures */
6943 for (i=0; i<*returned; i++) {
6944 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6945 smb_io_port_1("", buffer, &ports[i], 0);
6948 SAFE_FREE(ports);
6950 if (*needed > offered) {
6951 *returned=0;
6952 return WERR_INSUFFICIENT_BUFFER;
6955 return WERR_OK;
6958 /****************************************************************************
6959 enumports level 2.
6960 ****************************************************************************/
6962 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6964 PORT_INFO_2 *ports=NULL;
6965 int i=0;
6967 if (*lp_enumports_cmd()) {
6968 char *cmd = lp_enumports_cmd();
6969 char *path;
6970 char **qlines;
6971 pstring tmp_file;
6972 pstring command;
6973 int numlines;
6974 int ret;
6975 int fd;
6977 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6978 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6979 else
6980 path = lp_lockdir();
6982 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6983 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6985 unlink(tmp_file);
6986 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6987 ret = smbrun(command, &fd);
6988 DEBUGADD(10,("returned [%d]\n", ret));
6989 if (ret != 0) {
6990 if (fd != -1)
6991 close(fd);
6992 /* Is this the best error to return here? */
6993 return WERR_ACCESS_DENIED;
6996 numlines = 0;
6997 qlines = fd_lines_load(fd, &numlines);
6998 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6999 close(fd);
7001 if(numlines) {
7002 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7003 file_lines_free(qlines);
7004 return WERR_NOMEM;
7007 for (i=0; i<numlines; i++) {
7008 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7009 fill_port_2(&(ports[i]), qlines[i]);
7012 file_lines_free(qlines);
7015 *returned = numlines;
7017 } else {
7019 *returned = 1;
7021 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7022 return WERR_NOMEM;
7024 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7026 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7029 /* check the required size. */
7030 for (i=0; i<*returned; i++) {
7031 DEBUGADD(6,("adding port [%d]'s size\n", i));
7032 *needed += spoolss_size_port_info_2(&ports[i]);
7035 if (!alloc_buffer_size(buffer, *needed)) {
7036 SAFE_FREE(ports);
7037 return WERR_INSUFFICIENT_BUFFER;
7040 /* fill the buffer with the ports structures */
7041 for (i=0; i<*returned; i++) {
7042 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7043 smb_io_port_2("", buffer, &ports[i], 0);
7046 SAFE_FREE(ports);
7048 if (*needed > offered) {
7049 *returned=0;
7050 return WERR_INSUFFICIENT_BUFFER;
7053 return WERR_OK;
7056 /****************************************************************************
7057 enumports.
7058 ****************************************************************************/
7060 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7062 uint32 level = q_u->level;
7063 NEW_BUFFER *buffer = NULL;
7064 uint32 offered = q_u->offered;
7065 uint32 *needed = &r_u->needed;
7066 uint32 *returned = &r_u->returned;
7068 /* that's an [in out] buffer */
7069 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7070 buffer = r_u->buffer;
7072 DEBUG(4,("_spoolss_enumports\n"));
7074 *returned=0;
7075 *needed=0;
7077 switch (level) {
7078 case 1:
7079 return enumports_level_1(buffer, offered, needed, returned);
7080 case 2:
7081 return enumports_level_2(buffer, offered, needed, returned);
7082 default:
7083 return WERR_UNKNOWN_LEVEL;
7087 /****************************************************************************
7088 ****************************************************************************/
7090 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7091 const SPOOL_PRINTER_INFO_LEVEL *info,
7092 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7093 uint32 user_switch, const SPOOL_USER_CTR *user,
7094 POLICY_HND *handle)
7096 NT_PRINTER_INFO_LEVEL *printer = NULL;
7097 fstring name;
7098 int snum;
7099 WERROR err = WERR_OK;
7101 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7102 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7103 return WERR_NOMEM;
7106 ZERO_STRUCTP(printer);
7108 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7109 if (!convert_printer_info(info, printer, 2)) {
7110 free_a_printer(&printer, 2);
7111 return WERR_NOMEM;
7114 /* check to see if the printer already exists */
7116 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7117 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7118 printer->info_2->sharename));
7119 free_a_printer(&printer, 2);
7120 return WERR_PRINTER_ALREADY_EXISTS;
7123 if (*lp_addprinter_cmd() ) {
7124 if ( !add_printer_hook(printer) ) {
7125 free_a_printer(&printer,2);
7126 return WERR_ACCESS_DENIED;
7130 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7131 printer->info_2->sharename);
7134 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7135 free_a_printer(&printer,2);
7136 return WERR_ACCESS_DENIED;
7139 /* you must be a printer admin to add a new printer */
7140 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7141 free_a_printer(&printer,2);
7142 return WERR_ACCESS_DENIED;
7146 * Do sanity check on the requested changes for Samba.
7149 if (!check_printer_ok(printer->info_2, snum)) {
7150 free_a_printer(&printer,2);
7151 return WERR_INVALID_PARAM;
7155 * When a printer is created, the drivername bound to the printer is used
7156 * to lookup previously saved driver initialization info, which is then
7157 * bound to the new printer, simulating what happens in the Windows arch.
7160 if (!devmode)
7162 set_driver_init(printer, 2);
7164 else
7166 /* A valid devmode was included, convert and link it
7168 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7170 if (!convert_devicemode(printer->info_2->printername, devmode,
7171 &printer->info_2->devmode))
7172 return WERR_NOMEM;
7175 /* write the ASCII on disk */
7176 err = mod_a_printer(*printer, 2);
7177 if (!W_ERROR_IS_OK(err)) {
7178 free_a_printer(&printer,2);
7179 return err;
7182 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7183 /* Handle open failed - remove addition. */
7184 del_a_printer(printer->info_2->sharename);
7185 free_a_printer(&printer,2);
7186 return WERR_ACCESS_DENIED;
7189 update_c_setprinter(False);
7190 free_a_printer(&printer,2);
7192 return WERR_OK;
7195 /****************************************************************************
7196 ****************************************************************************/
7198 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7200 UNISTR2 *uni_srv_name = &q_u->server_name;
7201 uint32 level = q_u->level;
7202 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7203 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7204 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7205 uint32 user_switch = q_u->user_switch;
7206 SPOOL_USER_CTR *user = &q_u->user_ctr;
7207 POLICY_HND *handle = &r_u->handle;
7209 switch (level) {
7210 case 1:
7211 /* we don't handle yet */
7212 /* but I know what to do ... */
7213 return WERR_UNKNOWN_LEVEL;
7214 case 2:
7215 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7216 devmode, sdb,
7217 user_switch, user, handle);
7218 default:
7219 return WERR_UNKNOWN_LEVEL;
7223 /****************************************************************************
7224 ****************************************************************************/
7226 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7228 uint32 level = q_u->level;
7229 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7230 WERROR err = WERR_OK;
7231 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7232 struct current_user user;
7233 fstring driver_name;
7234 uint32 version;
7236 ZERO_STRUCT(driver);
7238 get_current_user(&user, p);
7240 if (!convert_printer_driver_info(info, &driver, level)) {
7241 err = WERR_NOMEM;
7242 goto done;
7245 DEBUG(5,("Cleaning driver's information\n"));
7246 err = clean_up_driver_struct(driver, level, &user);
7247 if (!W_ERROR_IS_OK(err))
7248 goto done;
7250 DEBUG(5,("Moving driver to final destination\n"));
7251 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7252 if (W_ERROR_IS_OK(err))
7253 err = WERR_ACCESS_DENIED;
7254 goto done;
7257 if (add_a_printer_driver(driver, level)!=0) {
7258 err = WERR_ACCESS_DENIED;
7259 goto done;
7262 /* BEGIN_ADMIN_LOG */
7263 switch(level) {
7264 case 3:
7265 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7266 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7267 fstrcpy(driver_name, driver.info_3->name);
7268 break;
7269 case 6:
7270 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7271 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7272 fstrcpy(driver_name, driver.info_6->name);
7273 break;
7275 /* END_ADMIN_LOG */
7278 * I think this is where he DrvUpgradePrinter() hook would be
7279 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7280 * server. Right now, we just need to send ourselves a message
7281 * to update each printer bound to this driver. --jerry
7284 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7285 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7286 driver_name));
7290 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7291 * decide if the driver init data should be deleted. The rules are:
7292 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7293 * 2) delete init data only if there is no 2k/Xp driver
7294 * 3) always delete init data
7295 * The generalized rule is always use init data from the highest order driver.
7296 * It is necessary to follow the driver install by an initialization step to
7297 * finish off this process.
7299 if (level == 3)
7300 version = driver.info_3->cversion;
7301 else if (level == 6)
7302 version = driver.info_6->version;
7303 else
7304 version = -1;
7305 switch (version) {
7307 * 9x printer driver - never delete init data
7309 case 0:
7310 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7311 driver_name));
7312 break;
7315 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7316 * there is no 2k/Xp driver init data for this driver name.
7318 case 2:
7320 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7322 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7324 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7326 if (!del_driver_init(driver_name))
7327 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7328 } else {
7330 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7332 free_a_printer_driver(driver1,3);
7333 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7334 driver_name));
7337 break;
7340 * 2k or Xp printer driver - always delete init data
7342 case 3:
7343 if (!del_driver_init(driver_name))
7344 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7345 break;
7347 default:
7348 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7349 break;
7353 done:
7354 free_a_printer_driver(driver, level);
7355 return err;
7358 /********************************************************************
7359 * spoolss_addprinterdriverex
7360 ********************************************************************/
7362 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7364 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7365 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7368 * we only support the semantics of AddPrinterDriver()
7369 * i.e. only copy files that are newer than existing ones
7372 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7373 return WERR_ACCESS_DENIED;
7375 ZERO_STRUCT(q_u_local);
7376 ZERO_STRUCT(r_u_local);
7378 /* just pass the information off to _spoolss_addprinterdriver() */
7379 q_u_local.server_name_ptr = q_u->server_name_ptr;
7380 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7381 q_u_local.level = q_u->level;
7382 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7384 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7387 /****************************************************************************
7388 ****************************************************************************/
7390 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7392 init_unistr(&info->name, name);
7395 /****************************************************************************
7396 ****************************************************************************/
7398 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7400 pstring path;
7401 pstring long_archi;
7402 pstring short_archi;
7403 DRIVER_DIRECTORY_1 *info=NULL;
7405 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7407 if (get_short_archi(short_archi, long_archi)==False)
7408 return WERR_INVALID_ENVIRONMENT;
7410 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7411 return WERR_NOMEM;
7413 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7415 DEBUG(4,("printer driver directory: [%s]\n", path));
7417 fill_driverdir_1(info, path);
7419 *needed += spoolss_size_driverdir_info_1(info);
7421 if (!alloc_buffer_size(buffer, *needed)) {
7422 SAFE_FREE(info);
7423 return WERR_INSUFFICIENT_BUFFER;
7426 smb_io_driverdir_1("", buffer, info, 0);
7428 SAFE_FREE(info);
7430 if (*needed > offered)
7431 return WERR_INSUFFICIENT_BUFFER;
7433 return WERR_OK;
7436 /****************************************************************************
7437 ****************************************************************************/
7439 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7441 UNISTR2 *name = &q_u->name;
7442 UNISTR2 *uni_environment = &q_u->environment;
7443 uint32 level = q_u->level;
7444 NEW_BUFFER *buffer = NULL;
7445 uint32 offered = q_u->offered;
7446 uint32 *needed = &r_u->needed;
7448 /* that's an [in out] buffer */
7449 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7450 buffer = r_u->buffer;
7452 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7454 *needed=0;
7456 switch(level) {
7457 case 1:
7458 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7459 default:
7460 return WERR_UNKNOWN_LEVEL;
7464 /****************************************************************************
7465 ****************************************************************************/
7467 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7469 POLICY_HND *handle = &q_u->handle;
7470 uint32 idx = q_u->index;
7471 uint32 in_value_len = q_u->valuesize;
7472 uint32 in_data_len = q_u->datasize;
7473 uint32 *out_max_value_len = &r_u->valuesize;
7474 uint16 **out_value = &r_u->value;
7475 uint32 *out_value_len = &r_u->realvaluesize;
7476 uint32 *out_type = &r_u->type;
7477 uint32 *out_max_data_len = &r_u->datasize;
7478 uint8 **data_out = &r_u->data;
7479 uint32 *out_data_len = &r_u->realdatasize;
7481 NT_PRINTER_INFO_LEVEL *printer = NULL;
7483 uint32 param_index;
7484 uint32 biggest_valuesize;
7485 uint32 biggest_datasize;
7486 uint32 data_len;
7487 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7488 int snum;
7489 WERROR result;
7490 REGISTRY_VALUE *val;
7491 NT_PRINTER_DATA *p_data;
7492 int i, key_index, num_values;
7493 int name_length;
7495 ZERO_STRUCT( printer );
7497 *out_type = 0;
7499 *out_max_data_len = 0;
7500 *data_out = NULL;
7501 *out_data_len = 0;
7503 DEBUG(5,("spoolss_enumprinterdata\n"));
7505 if (!Printer) {
7506 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7507 return WERR_BADFID;
7510 if (!get_printer_snum(p,handle, &snum))
7511 return WERR_BADFID;
7513 result = get_a_printer(&printer, 2, lp_servicename(snum));
7514 if (!W_ERROR_IS_OK(result))
7515 return result;
7517 p_data = &printer->info_2->data;
7518 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7520 result = WERR_OK;
7523 * The NT machine wants to know the biggest size of value and data
7525 * cf: MSDN EnumPrinterData remark section
7528 if ( !in_value_len && !in_data_len )
7530 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7532 param_index = 0;
7533 biggest_valuesize = 0;
7534 biggest_datasize = 0;
7536 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7538 for ( i=0; i<num_values; i++ )
7540 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7542 name_length = strlen(val->valuename);
7543 if ( strlen(val->valuename) > biggest_valuesize )
7544 biggest_valuesize = name_length;
7546 if ( val->size > biggest_datasize )
7547 biggest_datasize = val->size;
7549 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7550 biggest_datasize));
7553 /* the value is an UNICODE string but real_value_size is the length
7554 in bytes including the trailing 0 */
7556 *out_value_len = 2 * (1+biggest_valuesize);
7557 *out_data_len = biggest_datasize;
7559 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7561 goto done;
7565 * the value len is wrong in NT sp3
7566 * that's the number of bytes not the number of unicode chars
7569 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7571 if ( !val )
7574 /* out_value should default to "" or else NT4 has
7575 problems unmarshalling the response */
7577 *out_max_value_len = (in_value_len/sizeof(uint16));
7579 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7581 result = WERR_NOMEM;
7582 goto done;
7585 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7587 /* the data is counted in bytes */
7589 *out_max_data_len = in_data_len;
7590 *out_data_len = in_data_len;
7592 /* only allocate when given a non-zero data_len */
7594 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7596 result = WERR_NOMEM;
7597 goto done;
7600 result = WERR_NO_MORE_ITEMS;
7602 else
7605 * the value is:
7606 * - counted in bytes in the request
7607 * - counted in UNICODE chars in the max reply
7608 * - counted in bytes in the real size
7610 * take a pause *before* coding not *during* coding
7613 /* name */
7614 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7615 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7617 result = WERR_NOMEM;
7618 goto done;
7621 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7623 /* type */
7625 *out_type = regval_type( val );
7627 /* data - counted in bytes */
7629 *out_max_data_len = in_data_len;
7630 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7632 result = WERR_NOMEM;
7633 goto done;
7635 data_len = (size_t)regval_size(val);
7636 memcpy( *data_out, regval_data_p(val), data_len );
7637 *out_data_len = data_len;
7640 done:
7641 free_a_printer(&printer, 2);
7642 return result;
7645 /****************************************************************************
7646 ****************************************************************************/
7648 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7650 POLICY_HND *handle = &q_u->handle;
7651 UNISTR2 *value = &q_u->value;
7652 uint32 type = q_u->type;
7653 uint8 *data = q_u->data;
7654 uint32 real_len = q_u->real_len;
7656 NT_PRINTER_INFO_LEVEL *printer = NULL;
7657 int snum=0;
7658 WERROR status = WERR_OK;
7659 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7660 fstring valuename;
7662 DEBUG(5,("spoolss_setprinterdata\n"));
7664 if (!Printer) {
7665 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7666 return WERR_BADFID;
7669 if (!get_printer_snum(p,handle, &snum))
7670 return WERR_BADFID;
7673 * Access check : NT returns "access denied" if you make a
7674 * SetPrinterData call without the necessary privildge.
7675 * we were originally returning OK if nothing changed
7676 * which made Win2k issue **a lot** of SetPrinterData
7677 * when connecting to a printer --jerry
7680 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7682 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7683 status = WERR_ACCESS_DENIED;
7684 goto done;
7687 status = get_a_printer(&printer, 2, lp_servicename(snum));
7688 if (!W_ERROR_IS_OK(status))
7689 return status;
7691 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7694 * When client side code sets a magic printer data key, detect it and save
7695 * the current printer data and the magic key's data (its the DEVMODE) for
7696 * future printer/driver initializations.
7698 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7700 /* Set devmode and printer initialization info */
7701 status = save_driver_init( printer, 2, data, real_len );
7703 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7705 else
7707 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7708 type, data, real_len );
7709 if ( W_ERROR_IS_OK(status) )
7710 status = mod_a_printer(*printer, 2);
7713 done:
7714 free_a_printer(&printer, 2);
7716 return status;
7719 /****************************************************************************
7720 ****************************************************************************/
7722 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7724 POLICY_HND *handle = &q_u->handle;
7725 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7726 int snum;
7728 DEBUG(5,("_spoolss_resetprinter\n"));
7731 * All we do is to check to see if the handle and queue is valid.
7732 * This call really doesn't mean anything to us because we only
7733 * support RAW printing. --jerry
7736 if (!Printer) {
7737 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7738 return WERR_BADFID;
7741 if (!get_printer_snum(p,handle, &snum))
7742 return WERR_BADFID;
7745 /* blindly return success */
7746 return WERR_OK;
7750 /****************************************************************************
7751 ****************************************************************************/
7753 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7755 POLICY_HND *handle = &q_u->handle;
7756 UNISTR2 *value = &q_u->valuename;
7758 NT_PRINTER_INFO_LEVEL *printer = NULL;
7759 int snum=0;
7760 WERROR status = WERR_OK;
7761 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7762 pstring valuename;
7764 DEBUG(5,("spoolss_deleteprinterdata\n"));
7766 if (!Printer) {
7767 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7768 return WERR_BADFID;
7771 if (!get_printer_snum(p, handle, &snum))
7772 return WERR_BADFID;
7774 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7775 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7776 return WERR_ACCESS_DENIED;
7779 status = get_a_printer(&printer, 2, lp_servicename(snum));
7780 if (!W_ERROR_IS_OK(status))
7781 return status;
7783 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7785 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7787 free_a_printer(&printer, 2);
7789 return status;
7792 /****************************************************************************
7793 ****************************************************************************/
7795 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7797 POLICY_HND *handle = &q_u->handle;
7798 FORM *form = &q_u->form;
7799 nt_forms_struct tmpForm;
7800 int snum;
7801 WERROR status = WERR_OK;
7802 NT_PRINTER_INFO_LEVEL *printer = NULL;
7804 int count=0;
7805 nt_forms_struct *list=NULL;
7806 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7808 DEBUG(5,("spoolss_addform\n"));
7810 if (!Printer) {
7811 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7812 return WERR_BADFID;
7816 /* forms can be added on printer of on the print server handle */
7818 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7820 if (!get_printer_snum(p,handle, &snum))
7821 return WERR_BADFID;
7823 status = get_a_printer(&printer, 2, lp_servicename(snum));
7824 if (!W_ERROR_IS_OK(status))
7825 goto done;
7828 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7829 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7830 status = WERR_ACCESS_DENIED;
7831 goto done;
7834 /* can't add if builtin */
7836 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7837 status = WERR_ALREADY_EXISTS;
7838 goto done;
7841 count = get_ntforms(&list);
7843 if(!add_a_form(&list, form, &count)) {
7844 status = WERR_NOMEM;
7845 goto done;
7848 write_ntforms(&list, count);
7851 * ChangeID must always be set if this is a printer
7854 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7855 status = mod_a_printer(*printer, 2);
7857 done:
7858 if ( printer )
7859 free_a_printer(&printer, 2);
7860 SAFE_FREE(list);
7862 return status;
7865 /****************************************************************************
7866 ****************************************************************************/
7868 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7870 POLICY_HND *handle = &q_u->handle;
7871 UNISTR2 *form_name = &q_u->name;
7872 nt_forms_struct tmpForm;
7873 int count=0;
7874 nt_forms_struct *list=NULL;
7875 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7876 int snum;
7877 WERROR status = WERR_OK;
7878 NT_PRINTER_INFO_LEVEL *printer = NULL;
7880 DEBUG(5,("spoolss_deleteform\n"));
7882 if (!Printer) {
7883 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7884 return WERR_BADFID;
7887 /* forms can be deleted on printer of on the print server handle */
7889 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7891 if (!get_printer_snum(p,handle, &snum))
7892 return WERR_BADFID;
7894 status = get_a_printer(&printer, 2, lp_servicename(snum));
7895 if (!W_ERROR_IS_OK(status))
7896 goto done;
7899 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7900 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7901 status = WERR_ACCESS_DENIED;
7902 goto done;
7905 /* can't delete if builtin */
7907 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7908 status = WERR_INVALID_PARAM;
7909 goto done;
7912 count = get_ntforms(&list);
7914 if ( !delete_a_form(&list, form_name, &count, &status ))
7915 goto done;
7918 * ChangeID must always be set if this is a printer
7921 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7922 status = mod_a_printer(*printer, 2);
7924 done:
7925 if ( printer )
7926 free_a_printer(&printer, 2);
7927 SAFE_FREE(list);
7929 return status;
7932 /****************************************************************************
7933 ****************************************************************************/
7935 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7937 POLICY_HND *handle = &q_u->handle;
7938 FORM *form = &q_u->form;
7939 nt_forms_struct tmpForm;
7940 int snum;
7941 WERROR status = WERR_OK;
7942 NT_PRINTER_INFO_LEVEL *printer = NULL;
7944 int count=0;
7945 nt_forms_struct *list=NULL;
7946 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7948 DEBUG(5,("spoolss_setform\n"));
7950 if (!Printer) {
7951 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7952 return WERR_BADFID;
7955 /* forms can be modified on printer of on the print server handle */
7957 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7959 if (!get_printer_snum(p,handle, &snum))
7960 return WERR_BADFID;
7962 status = get_a_printer(&printer, 2, lp_servicename(snum));
7963 if (!W_ERROR_IS_OK(status))
7964 goto done;
7967 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7968 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7969 status = WERR_ACCESS_DENIED;
7970 goto done;
7973 /* can't set if builtin */
7974 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7975 status = WERR_INVALID_PARAM;
7976 goto done;
7979 count = get_ntforms(&list);
7980 update_a_form(&list, form, count);
7981 write_ntforms(&list, count);
7984 * ChangeID must always be set if this is a printer
7987 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7988 status = mod_a_printer(*printer, 2);
7991 done:
7992 if ( printer )
7993 free_a_printer(&printer, 2);
7994 SAFE_FREE(list);
7996 return status;
7999 /****************************************************************************
8000 enumprintprocessors level 1.
8001 ****************************************************************************/
8003 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8005 PRINTPROCESSOR_1 *info_1=NULL;
8007 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8008 return WERR_NOMEM;
8010 (*returned) = 0x1;
8012 init_unistr(&info_1->name, "winprint");
8014 *needed += spoolss_size_printprocessor_info_1(info_1);
8016 if (!alloc_buffer_size(buffer, *needed))
8017 return WERR_INSUFFICIENT_BUFFER;
8019 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8021 SAFE_FREE(info_1);
8023 if (*needed > offered) {
8024 *returned=0;
8025 return WERR_INSUFFICIENT_BUFFER;
8028 return WERR_OK;
8031 /****************************************************************************
8032 ****************************************************************************/
8034 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8036 uint32 level = q_u->level;
8037 NEW_BUFFER *buffer = NULL;
8038 uint32 offered = q_u->offered;
8039 uint32 *needed = &r_u->needed;
8040 uint32 *returned = &r_u->returned;
8042 /* that's an [in out] buffer */
8043 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8044 buffer = r_u->buffer;
8046 DEBUG(5,("spoolss_enumprintprocessors\n"));
8049 * Enumerate the print processors ...
8051 * Just reply with "winprint", to keep NT happy
8052 * and I can use my nice printer checker.
8055 *returned=0;
8056 *needed=0;
8058 switch (level) {
8059 case 1:
8060 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8061 default:
8062 return WERR_UNKNOWN_LEVEL;
8066 /****************************************************************************
8067 enumprintprocdatatypes level 1.
8068 ****************************************************************************/
8070 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8072 PRINTPROCDATATYPE_1 *info_1=NULL;
8074 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8075 return WERR_NOMEM;
8077 (*returned) = 0x1;
8079 init_unistr(&info_1->name, "RAW");
8081 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8083 if (!alloc_buffer_size(buffer, *needed))
8084 return WERR_INSUFFICIENT_BUFFER;
8086 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8088 SAFE_FREE(info_1);
8090 if (*needed > offered) {
8091 *returned=0;
8092 return WERR_INSUFFICIENT_BUFFER;
8095 return WERR_OK;
8098 /****************************************************************************
8099 ****************************************************************************/
8101 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8103 uint32 level = q_u->level;
8104 NEW_BUFFER *buffer = NULL;
8105 uint32 offered = q_u->offered;
8106 uint32 *needed = &r_u->needed;
8107 uint32 *returned = &r_u->returned;
8109 /* that's an [in out] buffer */
8110 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8111 buffer = r_u->buffer;
8113 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8115 *returned=0;
8116 *needed=0;
8118 switch (level) {
8119 case 1:
8120 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8121 default:
8122 return WERR_UNKNOWN_LEVEL;
8126 /****************************************************************************
8127 enumprintmonitors level 1.
8128 ****************************************************************************/
8130 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8132 PRINTMONITOR_1 *info_1=NULL;
8134 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8135 return WERR_NOMEM;
8137 (*returned) = 0x1;
8139 init_unistr(&info_1->name, "Local Port");
8141 *needed += spoolss_size_printmonitor_info_1(info_1);
8143 if (!alloc_buffer_size(buffer, *needed))
8144 return WERR_INSUFFICIENT_BUFFER;
8146 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8148 SAFE_FREE(info_1);
8150 if (*needed > offered) {
8151 *returned=0;
8152 return WERR_INSUFFICIENT_BUFFER;
8155 return WERR_OK;
8158 /****************************************************************************
8159 enumprintmonitors level 2.
8160 ****************************************************************************/
8162 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8164 PRINTMONITOR_2 *info_2=NULL;
8166 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8167 return WERR_NOMEM;
8169 (*returned) = 0x1;
8171 init_unistr(&info_2->name, "Local Port");
8172 init_unistr(&info_2->environment, "Windows NT X86");
8173 init_unistr(&info_2->dll_name, "localmon.dll");
8175 *needed += spoolss_size_printmonitor_info_2(info_2);
8177 if (!alloc_buffer_size(buffer, *needed))
8178 return WERR_INSUFFICIENT_BUFFER;
8180 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8182 SAFE_FREE(info_2);
8184 if (*needed > offered) {
8185 *returned=0;
8186 return WERR_INSUFFICIENT_BUFFER;
8189 return WERR_OK;
8192 /****************************************************************************
8193 ****************************************************************************/
8195 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8197 uint32 level = q_u->level;
8198 NEW_BUFFER *buffer = NULL;
8199 uint32 offered = q_u->offered;
8200 uint32 *needed = &r_u->needed;
8201 uint32 *returned = &r_u->returned;
8203 /* that's an [in out] buffer */
8204 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8205 buffer = r_u->buffer;
8207 DEBUG(5,("spoolss_enumprintmonitors\n"));
8210 * Enumerate the print monitors ...
8212 * Just reply with "Local Port", to keep NT happy
8213 * and I can use my nice printer checker.
8216 *returned=0;
8217 *needed=0;
8219 switch (level) {
8220 case 1:
8221 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8222 case 2:
8223 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8224 default:
8225 return WERR_UNKNOWN_LEVEL;
8229 /****************************************************************************
8230 ****************************************************************************/
8232 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8234 int i=0;
8235 BOOL found=False;
8236 JOB_INFO_1 *info_1=NULL;
8238 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8240 if (info_1 == NULL) {
8241 SAFE_FREE(queue);
8242 return WERR_NOMEM;
8245 for (i=0; i<count && found==False; i++) {
8246 if (queue[i].job==(int)jobid)
8247 found=True;
8250 if (found==False) {
8251 SAFE_FREE(queue);
8252 SAFE_FREE(info_1);
8253 /* NT treats not found as bad param... yet another bad choice */
8254 return WERR_INVALID_PARAM;
8257 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8259 *needed += spoolss_size_job_info_1(info_1);
8261 if (!alloc_buffer_size(buffer, *needed)) {
8262 SAFE_FREE(info_1);
8263 return WERR_INSUFFICIENT_BUFFER;
8266 smb_io_job_info_1("", buffer, info_1, 0);
8268 SAFE_FREE(info_1);
8270 if (*needed > offered)
8271 return WERR_INSUFFICIENT_BUFFER;
8273 return WERR_OK;
8276 /****************************************************************************
8277 ****************************************************************************/
8279 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8281 int i = 0;
8282 BOOL found = False;
8283 JOB_INFO_2 *info_2;
8284 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8285 WERROR ret;
8286 DEVICEMODE *devmode = NULL;
8287 NT_DEVICEMODE *nt_devmode = NULL;
8289 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8291 ZERO_STRUCTP(info_2);
8293 if (info_2 == NULL) {
8294 ret = WERR_NOMEM;
8295 goto done;
8298 for ( i=0; i<count && found==False; i++ )
8300 if (queue[i].job == (int)jobid)
8301 found = True;
8304 if ( !found )
8306 /* NT treats not found as bad param... yet another bad
8307 choice */
8308 ret = WERR_INVALID_PARAM;
8309 goto done;
8312 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
8313 if (!W_ERROR_IS_OK(ret))
8314 goto done;
8317 * if the print job does not have a DEVMODE associated with it,
8318 * just use the one for the printer. A NULL devicemode is not
8319 * a failure condition
8322 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8323 devmode = construct_dev_mode(snum);
8324 else {
8325 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8326 ZERO_STRUCTP( devmode );
8327 convert_nt_devicemode( devmode, nt_devmode );
8331 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8333 *needed += spoolss_size_job_info_2(info_2);
8335 if (!alloc_buffer_size(buffer, *needed)) {
8336 ret = WERR_INSUFFICIENT_BUFFER;
8337 goto done;
8340 smb_io_job_info_2("", buffer, info_2, 0);
8342 if (*needed > offered) {
8343 ret = WERR_INSUFFICIENT_BUFFER;
8344 goto done;
8347 ret = WERR_OK;
8349 done:
8350 /* Cleanup allocated memory */
8352 free_job_info_2(info_2); /* Also frees devmode */
8353 SAFE_FREE(info_2);
8354 free_a_printer(&ntprinter, 2);
8356 return ret;
8359 /****************************************************************************
8360 ****************************************************************************/
8362 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8364 POLICY_HND *handle = &q_u->handle;
8365 uint32 jobid = q_u->jobid;
8366 uint32 level = q_u->level;
8367 NEW_BUFFER *buffer = NULL;
8368 uint32 offered = q_u->offered;
8369 uint32 *needed = &r_u->needed;
8370 WERROR wstatus = WERR_OK;
8372 int snum;
8373 int count;
8374 print_queue_struct *queue = NULL;
8375 print_status_struct prt_status;
8377 /* that's an [in out] buffer */
8378 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8379 buffer = r_u->buffer;
8381 DEBUG(5,("spoolss_getjob\n"));
8383 *needed = 0;
8385 if (!get_printer_snum(p, handle, &snum))
8386 return WERR_BADFID;
8388 count = print_queue_status(snum, &queue, &prt_status);
8390 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8391 count, prt_status.status, prt_status.message));
8393 switch ( level ) {
8394 case 1:
8395 wstatus = getjob_level_1(queue, count, snum, jobid,
8396 buffer, offered, needed);
8397 break;
8398 case 2:
8399 wstatus = getjob_level_2(queue, count, snum, jobid,
8400 buffer, offered, needed);
8401 break;
8402 default:
8403 wstatus = WERR_UNKNOWN_LEVEL;
8404 break;
8407 SAFE_FREE(queue);
8408 return wstatus;
8411 /********************************************************************
8412 spoolss_getprinterdataex
8414 From MSDN documentation of GetPrinterDataEx: pass request
8415 to GetPrinterData if key is "PrinterDriverData".
8416 ********************************************************************/
8418 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8420 POLICY_HND *handle = &q_u->handle;
8421 uint32 in_size = q_u->size;
8422 uint32 *type = &r_u->type;
8423 uint32 *out_size = &r_u->size;
8424 uint8 **data = &r_u->data;
8425 uint32 *needed = &r_u->needed;
8426 fstring keyname, valuename;
8428 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8430 NT_PRINTER_INFO_LEVEL *printer = NULL;
8431 int snum = 0;
8432 WERROR status = WERR_OK;
8434 DEBUG(4,("_spoolss_getprinterdataex\n"));
8436 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8437 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8439 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8440 keyname, valuename));
8442 /* in case of problem, return some default values */
8444 *needed = 0;
8445 *type = 0;
8446 *out_size = in_size;
8448 if (!Printer) {
8449 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8450 status = WERR_BADFID;
8451 goto done;
8454 /* Is the handle to a printer or to the server? */
8456 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8457 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8458 status = WERR_INVALID_PARAM;
8459 goto done;
8462 if ( !get_printer_snum(p,handle, &snum) )
8463 return WERR_BADFID;
8465 status = get_a_printer(&printer, 2, lp_servicename(snum));
8466 if ( !W_ERROR_IS_OK(status) )
8467 goto done;
8469 /* check to see if the keyname is valid */
8470 if ( !strlen(keyname) ) {
8471 status = WERR_INVALID_PARAM;
8472 goto done;
8475 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8476 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8477 free_a_printer( &printer, 2 );
8478 status = WERR_BADFILE;
8479 goto done;
8482 /* When given a new keyname, we should just create it */
8484 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8486 if (*needed > *out_size)
8487 status = WERR_MORE_DATA;
8489 done:
8490 if ( !W_ERROR_IS_OK(status) )
8492 DEBUG(5, ("error: allocating %d\n", *out_size));
8494 /* reply this param doesn't exist */
8496 if ( *out_size )
8498 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8499 status = WERR_NOMEM;
8500 goto done;
8503 else {
8504 *data = NULL;
8508 if ( printer )
8509 free_a_printer( &printer, 2 );
8511 return status;
8514 /********************************************************************
8515 * spoolss_setprinterdataex
8516 ********************************************************************/
8518 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8520 POLICY_HND *handle = &q_u->handle;
8521 uint32 type = q_u->type;
8522 uint8 *data = q_u->data;
8523 uint32 real_len = q_u->real_len;
8525 NT_PRINTER_INFO_LEVEL *printer = NULL;
8526 int snum = 0;
8527 WERROR status = WERR_OK;
8528 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8529 fstring valuename;
8530 fstring keyname;
8531 char *oid_string;
8533 DEBUG(4,("_spoolss_setprinterdataex\n"));
8535 /* From MSDN documentation of SetPrinterDataEx: pass request to
8536 SetPrinterData if key is "PrinterDriverData" */
8538 if (!Printer) {
8539 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8540 return WERR_BADFID;
8543 if ( !get_printer_snum(p,handle, &snum) )
8544 return WERR_BADFID;
8547 * Access check : NT returns "access denied" if you make a
8548 * SetPrinterData call without the necessary privildge.
8549 * we were originally returning OK if nothing changed
8550 * which made Win2k issue **a lot** of SetPrinterData
8551 * when connecting to a printer --jerry
8554 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8556 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8557 return WERR_ACCESS_DENIED;
8560 status = get_a_printer(&printer, 2, lp_servicename(snum));
8561 if (!W_ERROR_IS_OK(status))
8562 return status;
8564 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8565 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8567 /* check for OID in valuename */
8569 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8571 *oid_string = '\0';
8572 oid_string++;
8575 /* save the registry data */
8577 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8579 /* save the OID if one was specified and the previous set call succeeded */
8581 if ( W_ERROR_IS_OK(status) && oid_string )
8584 fstrcat( keyname, "\\" );
8585 fstrcat( keyname, SPOOL_OID_KEY );
8588 * I'm not checking the status here on purpose. Don't know
8589 * if this is right, but I'm returning the status from the
8590 * previous set_printer_dataex() call. I have no idea if
8591 * this is right. --jerry
8594 set_printer_dataex( printer, keyname, valuename,
8595 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8598 free_a_printer(&printer, 2);
8600 return status;
8604 /********************************************************************
8605 * spoolss_deleteprinterdataex
8606 ********************************************************************/
8608 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8610 POLICY_HND *handle = &q_u->handle;
8611 UNISTR2 *value = &q_u->valuename;
8612 UNISTR2 *key = &q_u->keyname;
8614 NT_PRINTER_INFO_LEVEL *printer = NULL;
8615 int snum=0;
8616 WERROR status = WERR_OK;
8617 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8618 pstring valuename, keyname;
8620 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8622 if (!Printer) {
8623 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8624 return WERR_BADFID;
8627 if (!get_printer_snum(p, handle, &snum))
8628 return WERR_BADFID;
8630 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8631 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8632 return WERR_ACCESS_DENIED;
8635 status = get_a_printer(&printer, 2, lp_servicename(snum));
8636 if (!W_ERROR_IS_OK(status))
8637 return status;
8639 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8640 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8642 status = delete_printer_dataex( printer, keyname, valuename );
8644 free_a_printer(&printer, 2);
8646 return status;
8649 /********************************************************************
8650 * spoolss_enumprinterkey
8651 ********************************************************************/
8654 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8656 fstring key;
8657 fstring *keynames = NULL;
8658 uint16 *enumkeys = NULL;
8659 int num_keys;
8660 int printerkey_len;
8661 POLICY_HND *handle = &q_u->handle;
8662 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8663 NT_PRINTER_DATA *data;
8664 NT_PRINTER_INFO_LEVEL *printer = NULL;
8665 int snum = 0;
8666 WERROR status = WERR_BADFILE;
8669 DEBUG(4,("_spoolss_enumprinterkey\n"));
8671 if (!Printer) {
8672 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8673 return WERR_BADFID;
8676 if ( !get_printer_snum(p,handle, &snum) )
8677 return WERR_BADFID;
8679 status = get_a_printer(&printer, 2, lp_servicename(snum));
8680 if (!W_ERROR_IS_OK(status))
8681 return status;
8683 /* get the list of subkey names */
8685 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8686 data = &printer->info_2->data;
8688 num_keys = get_printer_subkeys( data, key, &keynames );
8690 if ( num_keys == -1 ) {
8691 status = WERR_BADFILE;
8692 goto done;
8695 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8697 r_u->needed = printerkey_len*2;
8699 if ( q_u->size < r_u->needed ) {
8700 status = WERR_MORE_DATA;
8701 goto done;
8704 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8705 status = WERR_NOMEM;
8706 goto done;
8709 status = WERR_OK;
8711 if ( q_u->size < r_u->needed )
8712 status = WERR_MORE_DATA;
8714 done:
8715 free_a_printer( &printer, 2 );
8716 SAFE_FREE( keynames );
8718 return status;
8721 /********************************************************************
8722 * spoolss_deleteprinterkey
8723 ********************************************************************/
8725 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8727 POLICY_HND *handle = &q_u->handle;
8728 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8729 fstring key;
8730 NT_PRINTER_INFO_LEVEL *printer = NULL;
8731 int snum=0;
8732 WERROR status;
8734 DEBUG(5,("spoolss_deleteprinterkey\n"));
8736 if (!Printer) {
8737 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8738 return WERR_BADFID;
8741 /* if keyname == NULL, return error */
8743 if ( !q_u->keyname.buffer )
8744 return WERR_INVALID_PARAM;
8746 if (!get_printer_snum(p, handle, &snum))
8747 return WERR_BADFID;
8749 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8750 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8751 return WERR_ACCESS_DENIED;
8754 status = get_a_printer(&printer, 2, lp_servicename(snum));
8755 if (!W_ERROR_IS_OK(status))
8756 return status;
8758 /* delete the key and all subneys */
8760 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8762 status = delete_all_printer_data( printer->info_2, key );
8764 if ( W_ERROR_IS_OK(status) )
8765 status = mod_a_printer(*printer, 2);
8767 free_a_printer( &printer, 2 );
8769 return status;
8773 /********************************************************************
8774 * spoolss_enumprinterdataex
8775 ********************************************************************/
8777 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8779 POLICY_HND *handle = &q_u->handle;
8780 uint32 in_size = q_u->size;
8781 uint32 num_entries,
8782 needed;
8783 NT_PRINTER_INFO_LEVEL *printer = NULL;
8784 PRINTER_ENUM_VALUES *enum_values = NULL;
8785 NT_PRINTER_DATA *p_data;
8786 fstring key;
8787 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8788 int snum;
8789 WERROR result;
8790 int key_index;
8791 int i;
8792 REGISTRY_VALUE *val;
8793 char *value_name;
8794 int data_len;
8797 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8799 if (!Printer) {
8800 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8801 return WERR_BADFID;
8804 /* first get the printer off of disk */
8806 if (!get_printer_snum(p,handle, &snum))
8807 return WERR_BADFID;
8809 ZERO_STRUCT(printer);
8810 result = get_a_printer(&printer, 2, lp_servicename(snum));
8811 if (!W_ERROR_IS_OK(result))
8812 return result;
8814 /* now look for a match on the key name */
8816 p_data = &printer->info_2->data;
8818 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8819 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8821 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8822 result = WERR_INVALID_PARAM;
8823 goto done;
8826 result = WERR_OK;
8827 needed = 0;
8829 /* allocate the memory for the array of pointers -- if necessary */
8831 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8832 if ( num_entries )
8834 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8836 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8837 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8838 result = WERR_NOMEM;
8839 goto done;
8842 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8846 * loop through all params and build the array to pass
8847 * back to the client
8850 for ( i=0; i<num_entries; i++ )
8852 /* lookup the registry value */
8854 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8855 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8857 /* copy the data */
8859 value_name = regval_name( val );
8860 init_unistr( &enum_values[i].valuename, value_name );
8861 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8862 enum_values[i].type = regval_type( val );
8864 data_len = regval_size( val );
8865 if ( data_len ) {
8866 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8868 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8869 data_len ));
8870 result = WERR_NOMEM;
8871 goto done;
8874 enum_values[i].data_len = data_len;
8876 /* keep track of the size of the array in bytes */
8878 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8881 /* housekeeping information in the reply */
8883 r_u->needed = needed;
8884 r_u->returned = num_entries;
8886 if (needed > in_size) {
8887 result = WERR_MORE_DATA;
8888 goto done;
8891 /* copy data into the reply */
8893 r_u->ctr.size = r_u->needed;
8894 r_u->ctr.size_of_array = r_u->returned;
8895 r_u->ctr.values = enum_values;
8899 done:
8900 free_a_printer(&printer, 2);
8902 return result;
8905 /****************************************************************************
8906 ****************************************************************************/
8908 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8910 init_unistr(&info->name, name);
8913 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8914 UNISTR2 *environment,
8915 NEW_BUFFER *buffer,
8916 uint32 offered,
8917 uint32 *needed)
8919 pstring path;
8920 pstring long_archi;
8921 pstring short_archi;
8922 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8924 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8926 if (get_short_archi(short_archi, long_archi)==False)
8927 return WERR_INVALID_ENVIRONMENT;
8929 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8930 return WERR_NOMEM;
8932 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8934 fill_printprocessordirectory_1(info, path);
8936 *needed += spoolss_size_printprocessordirectory_info_1(info);
8938 if (!alloc_buffer_size(buffer, *needed)) {
8939 safe_free(info);
8940 return WERR_INSUFFICIENT_BUFFER;
8943 smb_io_printprocessordirectory_1("", buffer, info, 0);
8945 safe_free(info);
8947 if (*needed > offered)
8948 return WERR_INSUFFICIENT_BUFFER;
8949 else
8950 return WERR_OK;
8953 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8955 uint32 level = q_u->level;
8956 NEW_BUFFER *buffer = NULL;
8957 uint32 offered = q_u->offered;
8958 uint32 *needed = &r_u->needed;
8959 WERROR result;
8961 /* that's an [in out] buffer */
8962 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8963 buffer = r_u->buffer;
8965 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8967 *needed=0;
8969 switch(level) {
8970 case 1:
8971 result = getprintprocessordirectory_level_1
8972 (&q_u->name, &q_u->environment, buffer, offered, needed);
8973 break;
8974 default:
8975 result = WERR_UNKNOWN_LEVEL;
8978 return result;
8981 #if 0
8983 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
8984 SPOOL_R_REPLYOPENPRINTER *r_u)
8986 DEBUG(5,("_spoolss_replyopenprinter\n"));
8988 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
8990 return WERR_OK;
8993 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
8994 SPOOL_R_REPLYCLOSEPRINTER *r_u)
8996 DEBUG(5,("_spoolss_replycloseprinter\n"));
8997 return WERR_OK;
9000 #endif