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