don't dereference null pointer
[Samba/gebeck_regimport.git] / source4 / rpc_server / srv_spoolss_nt.c
blob0c29962008cb3ac142f3e1bd7e33e2df54d1c3d2
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-2003,
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_"
42 /* Table to map the driver version */
43 /* to OS */
44 static const char * drv_ver_to_os[] = {
45 "WIN9X", /* driver version/cversion 0 */
46 "", /* unused ? */
47 "WINNT", /* driver version/cversion 2 */
48 "WIN2K", /* driver version/cversion 3 */
51 struct table_node {
52 const char *long_archi;
53 const char *short_archi;
54 int version;
57 static Printer_entry *printers_list;
59 typedef struct _counter_printer_0 {
60 ubi_dlNode Next;
61 ubi_dlNode Prev;
63 int snum;
64 uint32 counter;
65 } counter_printer_0;
67 static ubi_dlList counter_list;
69 static struct cli_state notify_cli; /* print notify back-channel */
70 static uint32 smb_connections=0;
73 /* in printing/nt_printing.c */
75 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
77 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
78 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
80 /* translate between internal status numbers and NT status numbers */
81 static int nt_printj_status(int v)
83 switch (v) {
84 case LPQ_QUEUED:
85 return 0;
86 case LPQ_PAUSED:
87 return JOB_STATUS_PAUSED;
88 case LPQ_SPOOLING:
89 return JOB_STATUS_SPOOLING;
90 case LPQ_PRINTING:
91 return JOB_STATUS_PRINTING;
92 case LPQ_ERROR:
93 return JOB_STATUS_ERROR;
94 case LPQ_DELETING:
95 return JOB_STATUS_DELETING;
96 case LPQ_OFFLINE:
97 return JOB_STATUS_OFFLINE;
98 case LPQ_PAPEROUT:
99 return JOB_STATUS_PAPEROUT;
100 case LPQ_PRINTED:
101 return JOB_STATUS_PRINTED;
102 case LPQ_DELETED:
103 return JOB_STATUS_DELETED;
104 case LPQ_BLOCKED:
105 return JOB_STATUS_BLOCKED;
106 case LPQ_USER_INTERVENTION:
107 return JOB_STATUS_USER_INTERVENTION;
109 return 0;
112 static int nt_printq_status(int v)
114 switch (v) {
115 case LPQ_PAUSED:
116 return PRINTER_STATUS_PAUSED;
117 case LPQ_QUEUED:
118 case LPQ_SPOOLING:
119 case LPQ_PRINTING:
120 return 0;
122 return 0;
125 /****************************************************************************
126 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
127 ****************************************************************************/
129 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
131 if (*pp == NULL)
132 return;
134 SAFE_FREE((*pp)->ctr.type);
135 SAFE_FREE(*pp);
138 /***************************************************************************
139 Disconnect from the client
140 ****************************************************************************/
142 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
144 WERROR result;
147 * Tell the specific printing tdb we no longer want messages for this printer
148 * by deregistering our PID.
151 if (!print_notify_deregister_pid(snum))
152 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
154 /* weird if the test succeds !!! */
155 if (smb_connections==0) {
156 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
157 return;
160 result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
162 if (!W_ERROR_IS_OK(result))
163 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
164 dos_errstr(result)));
166 /* if it's the last connection, deconnect the IPC$ share */
167 if (smb_connections==1) {
168 cli_nt_session_close(&notify_cli);
169 cli_ulogoff(&notify_cli);
170 cli_shutdown(&notify_cli);
171 message_deregister(MSG_PRINTER_NOTIFY2);
173 /* Tell the connections db we're no longer interested in
174 * printer notify messages. */
176 register_message_flags( False, FLAG_MSG_PRINTING );
179 smb_connections--;
182 /****************************************************************************
183 Functions to free a printer entry datastruct.
184 ****************************************************************************/
186 static void free_printer_entry(void *ptr)
188 Printer_entry *Printer = (Printer_entry *)ptr;
190 if (Printer->notify.client_connected==True) {
191 int snum = -1;
193 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
194 snum = -1;
195 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
196 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
197 snum = print_queue_snum(Printer->dev.handlename);
198 if (snum != -1)
199 srv_spoolss_replycloseprinter(snum,
200 &Printer->notify.client_hnd);
204 Printer->notify.flags=0;
205 Printer->notify.options=0;
206 Printer->notify.localmachine[0]='\0';
207 Printer->notify.printerlocal=0;
208 free_spool_notify_option(&Printer->notify.option);
209 Printer->notify.option=NULL;
210 Printer->notify.client_connected=False;
212 free_nt_devicemode( &Printer->nt_devmode );
213 free_a_printer( &Printer->printer_info, 2 );
215 talloc_destroy( Printer->ctx );
217 /* Remove from the internal list. */
218 DLIST_REMOVE(printers_list, Printer);
220 SAFE_FREE(Printer);
223 /****************************************************************************
224 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
225 ****************************************************************************/
227 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
229 SPOOL_NOTIFY_OPTION *new_sp = NULL;
231 if (!sp)
232 return NULL;
234 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
235 if (!new_sp)
236 return NULL;
238 *new_sp = *sp;
240 if (sp->ctr.count) {
241 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
243 if (!new_sp->ctr.type) {
244 SAFE_FREE(new_sp);
245 return NULL;
249 return new_sp;
252 /****************************************************************************
253 find printer index by handle
254 ****************************************************************************/
256 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
258 Printer_entry *find_printer = NULL;
260 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
261 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
262 return NULL;
265 return find_printer;
268 /****************************************************************************
269 find printer index by handle
270 ****************************************************************************/
272 void invalidate_printer_hnd_cache( char *printername )
274 Printer_entry *p;
276 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
278 for ( p=printers_list; p; p=p->next )
280 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
281 && StrCaseCmp(p->dev.handlename, printername)==0)
283 DEBUG(10,("invalidating printer_info cache for handl:\n"));
284 free_a_printer( &p->printer_info, 2 );
285 p->printer_info = NULL;
289 return;
291 /****************************************************************************
292 Close printer index by handle.
293 ****************************************************************************/
295 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
297 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
299 if (!Printer) {
300 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
301 return False;
304 close_policy_hnd(p, hnd);
306 return True;
309 /****************************************************************************
310 Delete a printer given a handle.
311 ****************************************************************************/
313 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
315 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
317 if (!Printer) {
318 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
319 return WERR_BADFID;
323 * It turns out that Windows allows delete printer on a handle
324 * opened by an admin user, then used on a pipe handle created
325 * by an anonymous user..... but they're working on security.... riiight !
326 * JRA.
329 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
330 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
331 return WERR_ACCESS_DENIED;
334 #if 0
335 /* Check calling user has permission to delete printer. Note that
336 since we set the snum parameter to -1 only administrators can
337 delete the printer. This stops people with the Full Control
338 permission from deleting the printer. */
340 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
341 DEBUG(3, ("printer delete denied by security descriptor\n"));
342 return WERR_ACCESS_DENIED;
344 #endif
346 if (del_a_printer(Printer->dev.handlename) != 0) {
347 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
348 return WERR_BADFID;
351 if (*lp_deleteprinter_cmd()) {
353 char *cmd = lp_deleteprinter_cmd();
354 pstring command;
355 int ret;
356 int i;
358 /* Printer->dev.handlename equals portname equals sharename */
359 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
360 Printer->dev.handlename);
362 DEBUG(10,("Running [%s]\n", command));
363 ret = smbrun(command, NULL);
364 if (ret != 0) {
365 return WERR_BADFID; /* What to return here? */
367 DEBUGADD(10,("returned [%d]\n", ret));
369 /* Send SIGHUP to process group... is there a better way? */
370 kill(0, SIGHUP);
372 /* go ahead and re-read the services immediately */
373 reload_services( False );
375 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
376 return WERR_ACCESS_DENIED;
379 return WERR_OK;
382 /****************************************************************************
383 Return the snum of a printer corresponding to an handle.
384 ****************************************************************************/
386 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
388 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
390 if (!Printer) {
391 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
392 return False;
395 switch (Printer->printer_type) {
396 case PRINTER_HANDLE_IS_PRINTER:
397 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
398 *number = print_queue_snum(Printer->dev.handlename);
399 return (*number != -1);
400 case PRINTER_HANDLE_IS_PRINTSERVER:
401 return False;
402 default:
403 return False;
407 /****************************************************************************
408 Set printer handle type.
409 Check if it's \\server or \\server\printer
410 ****************************************************************************/
412 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
414 DEBUG(3,("Setting printer type=%s\n", handlename));
416 if ( strlen(handlename) < 3 ) {
417 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
418 return False;
421 /* it's a print server */
422 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
423 DEBUGADD(4,("Printer is a print server\n"));
424 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
426 /* it's a printer */
427 else {
428 DEBUGADD(4,("Printer is a printer\n"));
429 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
432 return True;
435 /****************************************************************************
436 Set printer handle name.
437 ****************************************************************************/
439 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
441 int snum;
442 int n_services=lp_numservices();
443 char *aprinter;
444 fstring sname;
445 BOOL found=False;
447 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
449 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
450 ZERO_STRUCT(Printer->dev.printerservername);
451 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
452 return True;
455 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
456 return False;
458 if (*handlename=='\\') {
459 aprinter=strchr_m(handlename+2, '\\');
460 aprinter++;
462 else {
463 aprinter=handlename;
466 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
469 * The original code allowed smbd to store a printer name that
470 * was different from the share name. This is not possible
471 * anymore, so I've simplified this loop greatly. Here
472 * we are just verifying that the printer name is a valid
473 * printer service defined in smb.conf
474 * --jerry [Fri Feb 15 11:17:46 CST 2002]
477 for (snum=0; snum<n_services; snum++) {
479 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
480 continue;
482 fstrcpy(sname, lp_servicename(snum));
484 DEBUGADD(5,("share:%s\n",sname));
486 if (! StrCaseCmp(sname, aprinter)) {
487 found = True;
488 break;
494 if (!found) {
495 DEBUGADD(4,("Printer not found\n"));
496 return False;
499 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
501 ZERO_STRUCT(Printer->dev.handlename);
502 fstrcpy(Printer->dev.handlename, sname);
504 return True;
507 /****************************************************************************
508 Find first available printer slot. creates a printer handle for you.
509 ****************************************************************************/
511 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
513 Printer_entry *new_printer;
515 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
517 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
518 return False;
520 ZERO_STRUCTP(new_printer);
522 if ( !(new_printer->ctx = talloc_init("Printer Entry [0x%x]", (uint32)hnd)) ) {
523 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
524 return False;
527 new_printer->notify.option=NULL;
529 /* Add to the internal list. */
530 DLIST_ADD(printers_list, new_printer);
532 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
533 SAFE_FREE(new_printer);
534 return False;
537 if (!set_printer_hnd_printertype(new_printer, name)) {
538 close_printer_handle(p, hnd);
539 return False;
542 if (!set_printer_hnd_name(new_printer, name)) {
543 close_printer_handle(p, hnd);
544 return False;
547 new_printer->access_granted = access_granted;
549 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
551 return True;
554 /****************************************************************************
555 Allocate more memory for a BUFFER.
556 ****************************************************************************/
558 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
560 prs_struct *ps;
561 uint32 extra_space;
562 uint32 old_offset;
564 ps= &buffer->prs;
566 /* damn, I'm doing the reverse operation of prs_grow() :) */
567 if (buffer_size < prs_data_size(ps))
568 extra_space=0;
569 else
570 extra_space = buffer_size - prs_data_size(ps);
573 * save the offset and move to the end of the buffer
574 * prs_grow() checks the extra_space against the offset
576 old_offset=prs_offset(ps);
577 prs_set_offset(ps, prs_data_size(ps));
579 if (!prs_grow(ps, extra_space))
580 return False;
582 prs_set_offset(ps, old_offset);
584 buffer->string_at_end=prs_data_size(ps);
586 return True;
589 /***************************************************************************
590 check to see if the client motify handle is monitoring the notification
591 given by (notify_type, notify_field).
592 **************************************************************************/
594 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
595 uint16 notify_field)
597 return True;
600 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
601 uint16 notify_field)
603 SPOOL_NOTIFY_OPTION *option = p->notify.option;
604 uint32 i, j;
607 * Flags should always be zero when the change notify
608 * is registered by the client's spooler. A user Win32 app
609 * might use the flags though instead of the NOTIFY_OPTION_INFO
610 * --jerry
613 if (p->notify.flags)
614 return is_monitoring_event_flags(
615 p->notify.flags, notify_type, notify_field);
617 for (i = 0; i < option->count; i++) {
619 /* Check match for notify_type */
621 if (option->ctr.type[i].type != notify_type)
622 continue;
624 /* Check match for field */
626 for (j = 0; j < option->ctr.type[i].count; j++) {
627 if (option->ctr.type[i].fields[j] == notify_field) {
628 return True;
633 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
634 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
635 p->dev.handlename : p->dev.printerservername,
636 notify_type, notify_field));
638 return False;
641 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
643 static void notify_one_value(struct spoolss_notify_msg *msg,
644 SPOOL_NOTIFY_INFO_DATA *data,
645 TALLOC_CTX *mem_ctx)
647 data->notify_data.value[0] = msg->notify.value[0];
648 data->notify_data.value[1] = 0;
651 static void notify_string(struct spoolss_notify_msg *msg,
652 SPOOL_NOTIFY_INFO_DATA *data,
653 TALLOC_CTX *mem_ctx)
655 UNISTR2 unistr;
657 /* The length of the message includes the trailing \0 */
659 init_unistr2(&unistr, msg->notify.data, msg->len);
661 data->notify_data.data.length = msg->len * 2;
662 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
664 if (!data->notify_data.data.string) {
665 data->notify_data.data.length = 0;
666 return;
669 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
672 static void notify_system_time(struct spoolss_notify_msg *msg,
673 SPOOL_NOTIFY_INFO_DATA *data,
674 TALLOC_CTX *mem_ctx)
676 SYSTEMTIME systime;
677 prs_struct ps;
679 if (msg->len != sizeof(time_t)) {
680 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
681 msg->len));
682 return;
685 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
686 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
687 return;
690 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
691 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
692 return;
695 if (!spoolss_io_system_time("", &ps, 0, &systime))
696 return;
698 data->notify_data.data.length = prs_offset(&ps);
699 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
701 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
703 prs_mem_free(&ps);
706 struct notify2_message_table {
707 const char *name;
708 void (*fn)(struct spoolss_notify_msg *msg,
709 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
712 static struct notify2_message_table printer_notify_table[] = {
713 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
714 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
715 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
716 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
717 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
718 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
719 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
720 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
721 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
722 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
723 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
724 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
725 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
726 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
727 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
728 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
729 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
730 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
731 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
734 static struct notify2_message_table job_notify_table[] = {
735 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
736 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
737 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
738 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
739 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
740 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
741 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
742 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
743 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
744 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
745 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
746 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
747 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
748 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
749 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
750 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
751 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
752 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
753 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
754 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
755 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
756 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
757 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
758 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
762 /***********************************************************************
763 Allocate talloc context for container object
764 **********************************************************************/
766 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
768 if ( !ctr )
769 return;
771 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
773 return;
776 /***********************************************************************
777 release all allocated memory and zero out structure
778 **********************************************************************/
780 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
782 if ( !ctr )
783 return;
785 if ( ctr->ctx )
786 talloc_destroy(ctr->ctx);
788 ZERO_STRUCTP(ctr);
790 return;
793 /***********************************************************************
794 **********************************************************************/
796 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
798 if ( !ctr )
799 return NULL;
801 return ctr->ctx;
804 /***********************************************************************
805 **********************************************************************/
807 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
809 if ( !ctr || !ctr->msg_groups )
810 return NULL;
812 if ( idx >= ctr->num_groups )
813 return NULL;
815 return &ctr->msg_groups[idx];
819 /***********************************************************************
820 How many groups of change messages do we have ?
821 **********************************************************************/
823 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
825 if ( !ctr )
826 return 0;
828 return ctr->num_groups;
831 /***********************************************************************
832 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
833 **********************************************************************/
835 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
837 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
838 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
839 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
840 int i, new_slot;
842 if ( !ctr || !msg )
843 return 0;
845 /* loop over all groups looking for a matching printer name */
847 for ( i=0; i<ctr->num_groups; i++ ) {
848 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
849 break;
852 /* add a new group? */
854 if ( i == ctr->num_groups ) {
855 ctr->num_groups++;
857 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
858 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
859 return 0;
861 ctr->msg_groups = groups;
863 /* clear the new entry and set the printer name */
865 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
866 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
869 /* add the change messages; 'i' is the correct index now regardless */
871 msg_grp = &ctr->msg_groups[i];
873 msg_grp->num_msgs++;
875 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
876 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
877 return 0;
879 msg_grp->msgs = msg_list;
881 new_slot = msg_grp->num_msgs-1;
882 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
884 /* need to allocate own copy of data */
886 if ( msg->len != 0 )
887 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
889 return ctr->num_groups;
892 /***********************************************************************
893 Send a change notication message on all handles which have a call
894 back registered
895 **********************************************************************/
897 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
899 Printer_entry *p;
900 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
901 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
902 SPOOLSS_NOTIFY_MSG *messages;
905 if ( !msg_group ) {
906 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
907 return;
910 messages = msg_group->msgs;
912 if ( !messages ) {
913 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
914 return;
917 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
919 /* loop over all printers */
921 for (p = printers_list; p; p = p->next) {
922 SPOOL_NOTIFY_INFO_DATA *data;
923 uint32 data_len = 0;
924 uint32 id;
925 int i, event_index;
927 /* Is there notification on this handle? */
929 if ( !p->notify.client_connected )
930 continue;
932 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
934 /* For this printer? Print servers always receive
935 notifications. */
937 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
938 ( !strequal(msg_group->printername, p->dev.handlename) ) )
939 continue;
941 DEBUG(10,("Our printer\n"));
943 /* allocate the max entries possible */
945 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
946 ZERO_STRUCTP(data);
948 event_index = 0;
950 /* build the array of change notifications */
952 for ( i=0; i<msg_group->num_msgs; i++ ) {
953 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
955 /* Are we monitoring this event? */
957 if (!is_monitoring_event(p, msg->type, msg->field))
958 continue;
961 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
962 msg->type, msg->field, p->dev.handlename));
965 * if the is a printer notification handle and not a job notification
966 * type, then set the id to 0. Other wise just use what was specified
967 * in the message.
969 * When registering change notification on a print server handle
970 * we always need to send back the id (snum) matching the printer
971 * for which the change took place. For change notify registered
972 * on a printer handle, this does not matter and the id should be 0.
974 * --jerry
977 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
978 id = 0;
979 else
980 id = msg->id;
983 /* Convert unix jobid to smb jobid */
985 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
986 id = sysjob_to_jobid(msg->id);
988 if (id == -1) {
989 DEBUG(3, ("no such unix jobid %d\n", msg->id));
990 goto done;
994 construct_info_data( &data[data_len], msg->type, msg->field, id );
996 switch(msg->type) {
997 case PRINTER_NOTIFY_TYPE:
998 if ( printer_notify_table[msg->field].fn )
999 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1000 break;
1002 case JOB_NOTIFY_TYPE:
1003 if ( job_notify_table[msg->field].fn )
1004 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1005 break;
1007 default:
1008 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1009 goto done;
1012 data_len++;
1015 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1016 data_len, data, p->notify.change, 0 );
1019 done:
1020 DEBUG(8,("send_notify2_changes: Exit...\n"));
1021 return;
1024 /***********************************************************************
1025 **********************************************************************/
1027 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
1030 size_t offset = 0;
1032 /* Unpack message */
1034 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1035 msg->printer);
1037 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
1038 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1040 if (msg->len == 0)
1041 tdb_unpack((char *)buf + offset, len - offset, "dd",
1042 &msg->notify.value[0], &msg->notify.value[1]);
1043 else
1044 tdb_unpack((char *)buf + offset, len - offset, "B",
1045 &msg->len, &msg->notify.data);
1047 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1048 msg->type, msg->field, msg->flags));
1050 if (msg->len == 0)
1051 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1052 msg->notify.value[1]));
1053 else
1054 dump_data(3, msg->notify.data, msg->len);
1056 return True;
1059 /********************************************************************
1060 Receive a notify2 message list
1061 ********************************************************************/
1063 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1065 size_t msg_count, i;
1066 char *buf = (char *)msg;
1067 char *msg_ptr;
1068 size_t msg_len;
1069 SPOOLSS_NOTIFY_MSG notify;
1070 SPOOLSS_NOTIFY_MSG_CTR messages;
1071 int num_groups;
1073 if (len < 4) {
1074 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1075 return;
1078 msg_count = IVAL(buf, 0);
1079 msg_ptr = buf + 4;
1081 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1083 if (msg_count == 0) {
1084 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1085 return;
1088 /* initialize the container */
1090 ZERO_STRUCT( messages );
1091 notify_msg_ctr_init( &messages );
1094 * build message groups for each printer identified
1095 * in a change_notify msg. Remember that a PCN message
1096 * includes the handle returned for the srv_spoolss_replyopenprinter()
1097 * call. Therefore messages are grouped according to printer handle.
1100 for ( i=0; i<msg_count; i++ )
1102 if (msg_ptr + 4 - buf > len) {
1103 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1104 return;
1107 msg_len = IVAL(msg_ptr,0);
1108 msg_ptr += 4;
1110 if (msg_ptr + msg_len - buf > len) {
1111 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1112 return;
1115 /* unpack messages */
1117 ZERO_STRUCT( notify );
1118 notify2_unpack_msg( &notify, msg_ptr, msg_len );
1119 msg_ptr += msg_len;
1121 /* add to correct list in container */
1123 notify_msg_ctr_addmsg( &messages, &notify );
1125 /* free memory that might have been allocated by notify2_unpack_msg() */
1127 if ( notify.len != 0 )
1128 SAFE_FREE( notify.notify.data );
1131 /* process each group of messages */
1133 num_groups = notify_msg_ctr_numgroups( &messages );
1134 for ( i=0; i<num_groups; i++ )
1135 send_notify2_changes( &messages, i );
1138 /* cleanup */
1140 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1142 notify_msg_ctr_destroy( &messages );
1144 return;
1147 /********************************************************************
1148 Send a message to ourself about new driver being installed
1149 so we can upgrade the information for each printer bound to this
1150 driver
1151 ********************************************************************/
1153 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1155 int len = strlen(drivername);
1157 if (!len)
1158 return False;
1160 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1161 drivername));
1163 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1165 return True;
1168 /**********************************************************************
1169 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1170 over all printers, upgrading ones as neessary
1171 **********************************************************************/
1173 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1175 fstring drivername;
1176 int snum;
1177 int n_services = lp_numservices();
1179 len = MIN(len,sizeof(drivername)-1);
1180 strncpy(drivername, buf, len);
1182 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1184 /* Iterate the printer list */
1186 for (snum=0; snum<n_services; snum++)
1188 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1190 WERROR result;
1191 NT_PRINTER_INFO_LEVEL *printer = NULL;
1193 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1194 if (!W_ERROR_IS_OK(result))
1195 continue;
1197 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1199 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1201 /* all we care about currently is the change_id */
1203 result = mod_a_printer(*printer, 2);
1204 if (!W_ERROR_IS_OK(result)) {
1205 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1206 dos_errstr(result)));
1210 free_a_printer(&printer, 2);
1214 /* all done */
1217 /********************************************************************
1218 Update the cahce for all printq's with a registered client
1219 connection
1220 ********************************************************************/
1222 void update_monitored_printq_cache( void )
1224 Printer_entry *printer = printers_list;
1225 int snum;
1227 /* loop through all printers and update the cache where
1228 client_connected == True */
1229 while ( printer )
1231 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1232 && printer->notify.client_connected )
1234 snum = print_queue_snum(printer->dev.handlename);
1235 print_queue_status( snum, NULL, NULL );
1238 printer = printer->next;
1241 return;
1243 /********************************************************************
1244 Send a message to ourself about new driver being installed
1245 so we can upgrade the information for each printer bound to this
1246 driver
1247 ********************************************************************/
1249 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1251 int len = strlen(drivername);
1253 if (!len)
1254 return False;
1256 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1257 drivername));
1259 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1261 return True;
1264 /**********************************************************************
1265 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1266 over all printers, resetting printer data as neessary
1267 **********************************************************************/
1269 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1271 fstring drivername;
1272 int snum;
1273 int n_services = lp_numservices();
1275 len = MIN( len, sizeof(drivername)-1 );
1276 strncpy( drivername, buf, len );
1278 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1280 /* Iterate the printer list */
1282 for ( snum=0; snum<n_services; snum++ )
1284 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1286 WERROR result;
1287 NT_PRINTER_INFO_LEVEL *printer = NULL;
1289 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1290 if ( !W_ERROR_IS_OK(result) )
1291 continue;
1294 * if the printer is bound to the driver,
1295 * then reset to the new driver initdata
1298 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1300 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1302 if ( !set_driver_init(printer, 2) ) {
1303 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1304 printer->info_2->printername, printer->info_2->drivername));
1307 result = mod_a_printer( *printer, 2 );
1308 if ( !W_ERROR_IS_OK(result) ) {
1309 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1310 get_dos_error_msg(result)));
1314 free_a_printer( &printer, 2 );
1318 /* all done */
1320 return;
1323 /********************************************************************
1324 Copy routines used by convert_to_openprinterex()
1325 *******************************************************************/
1327 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1329 DEVICEMODE *d;
1330 int len;
1332 if (!devmode)
1333 return NULL;
1335 DEBUG (8,("dup_devmode\n"));
1337 /* bulk copy first */
1339 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1340 if (!d)
1341 return NULL;
1343 /* dup the pointer members separately */
1345 len = unistrlen(devmode->devicename.buffer);
1346 if (len != -1) {
1347 d->devicename.buffer = talloc(ctx, len*2);
1348 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1349 return NULL;
1353 len = unistrlen(devmode->formname.buffer);
1354 if (len != -1) {
1355 d->devicename.buffer = talloc(ctx, len*2);
1356 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1357 return NULL;
1360 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1362 return d;
1365 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1367 if (!new_ctr || !ctr)
1368 return;
1370 DEBUG(8,("copy_devmode_ctr\n"));
1372 new_ctr->size = ctr->size;
1373 new_ctr->devmode_ptr = ctr->devmode_ptr;
1375 if(ctr->devmode_ptr)
1376 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1379 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1381 if (!new_def || !def)
1382 return;
1384 DEBUG(8,("copy_printer_defaults\n"));
1386 new_def->datatype_ptr = def->datatype_ptr;
1388 if (def->datatype_ptr)
1389 copy_unistr2(&new_def->datatype, &def->datatype);
1391 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1393 new_def->access_required = def->access_required;
1396 /********************************************************************
1397 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1398 * SPOOL_Q_OPEN_PRINTER_EX structure
1399 ********************************************************************/
1401 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1403 if (!q_u_ex || !q_u)
1404 return;
1406 DEBUG(8,("convert_to_openprinterex\n"));
1408 q_u_ex->printername_ptr = q_u->printername_ptr;
1410 if (q_u->printername_ptr)
1411 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1413 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1416 /********************************************************************
1417 * spoolss_open_printer
1419 * called from the spoolss dispatcher
1420 ********************************************************************/
1422 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1424 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1425 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1427 if (!q_u || !r_u)
1428 return WERR_NOMEM;
1430 ZERO_STRUCT(q_u_ex);
1431 ZERO_STRUCT(r_u_ex);
1433 /* convert the OpenPrinter() call to OpenPrinterEx() */
1435 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1437 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1439 /* convert back to OpenPrinter() */
1441 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1443 return r_u->status;
1446 /********************************************************************
1447 * spoolss_open_printer
1449 * If the openprinterex rpc call contains a devmode,
1450 * it's a per-user one. This per-user devmode is derivated
1451 * from the global devmode. Openprinterex() contains a per-user
1452 * devmode for when you do EMF printing and spooling.
1453 * In the EMF case, the NT workstation is only doing half the job
1454 * of rendering the page. The other half is done by running the printer
1455 * driver on the server.
1456 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1457 * The EMF file only contains what is to be printed on the page.
1458 * So in order for the server to know how to print, the NT client sends
1459 * a devicemode attached to the openprinterex call.
1460 * But this devicemode is short lived, it's only valid for the current print job.
1462 * If Samba would have supported EMF spooling, this devicemode would
1463 * have been attached to the handle, to sent it to the driver to correctly
1464 * rasterize the EMF file.
1466 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1467 * we just act as a pass-thru between windows and the printer.
1469 * In order to know that Samba supports only RAW spooling, NT has to call
1470 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1471 * and until NT sends a RAW job, we refuse it.
1473 * But to call getprinter() or startdoc(), you first need a valid handle,
1474 * and to get an handle you have to call openprintex(). Hence why you have
1475 * a devicemode in the openprinterex() call.
1478 * Differences between NT4 and NT 2000.
1479 * NT4:
1480 * ---
1481 * On NT4, you only have a global devicemode. This global devicemode can be changed
1482 * by the administrator (or by a user with enough privs). Everytime a user
1483 * wants to print, the devicemode is resetted to the default. In Word, everytime
1484 * you print, the printer's characteristics are always reset to the global devicemode.
1486 * NT 2000:
1487 * -------
1488 * In W2K, there is the notion of per-user devicemode. The first time you use
1489 * a printer, a per-user devicemode is build from the global devicemode.
1490 * If you change your per-user devicemode, it is saved in the registry, under the
1491 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1492 * printer preferences available.
1494 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1495 * on the General Tab of the printer properties windows.
1497 * To change the global devicemode: it's the "Printing Defaults..." button
1498 * on the Advanced Tab of the printer properties window.
1500 * JFM.
1501 ********************************************************************/
1503 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1505 UNISTR2 *printername = NULL;
1506 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1507 POLICY_HND *handle = &r_u->handle;
1509 fstring name;
1510 int snum;
1511 struct current_user user;
1512 Printer_entry *Printer=NULL;
1514 if (q_u->printername_ptr != 0)
1515 printername = &q_u->printername;
1517 if (printername == NULL)
1518 return WERR_INVALID_PRINTER_NAME;
1520 /* some sanity check because you can open a printer or a print server */
1521 /* aka: \\server\printer or \\server */
1522 unistr2_to_ascii(name, printername, sizeof(name)-1);
1524 DEBUGADD(3,("checking name: %s\n",name));
1526 if (!open_printer_hnd(p, handle, name, 0))
1527 return WERR_INVALID_PRINTER_NAME;
1529 Printer=find_printer_index_by_hnd(p, handle);
1530 if (!Printer) {
1531 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1532 Can't find printer handle we created for printer %s\n", name ));
1533 close_printer_handle(p,handle);
1534 return WERR_INVALID_PRINTER_NAME;
1537 get_current_user(&user, p);
1540 * First case: the user is opening the print server:
1542 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1543 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1545 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1546 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1547 * or if the user is listed in the smb.conf printer admin parameter.
1549 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1550 * client view printer folder, but does not show the MSAPW.
1552 * Note: this test needs code to check access rights here too. Jeremy
1553 * could you look at this?
1555 * Second case: the user is opening a printer:
1556 * NT doesn't let us connect to a printer if the connecting user
1557 * doesn't have print permission.
1560 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1562 /* Printserver handles use global struct... */
1564 snum = -1;
1566 /* Map standard access rights to object specific access rights */
1568 se_map_standard(&printer_default->access_required,
1569 &printserver_std_mapping);
1571 /* Deny any object specific bits that don't apply to print
1572 servers (i.e printer and job specific bits) */
1574 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1576 if (printer_default->access_required &
1577 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1578 DEBUG(3, ("access DENIED for non-printserver bits"));
1579 close_printer_handle(p, handle);
1580 return WERR_ACCESS_DENIED;
1583 /* Allow admin access */
1585 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1587 if (!lp_ms_add_printer_wizard()) {
1588 close_printer_handle(p, handle);
1589 return WERR_ACCESS_DENIED;
1592 /* if the user is not root and not a printer admin, then fail */
1594 if ( user.uid != 0
1595 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1597 close_printer_handle(p, handle);
1598 return WERR_ACCESS_DENIED;
1601 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1603 else
1605 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1608 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1609 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1611 /* We fall through to return WERR_OK */
1614 else
1616 /* NT doesn't let us connect to a printer if the connecting user
1617 doesn't have print permission. */
1619 if (!get_printer_snum(p, handle, &snum))
1620 return WERR_BADFID;
1622 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1624 /* map an empty access mask to the minimum access mask */
1625 if (printer_default->access_required == 0x0)
1626 printer_default->access_required = PRINTER_ACCESS_USE;
1629 * If we are not serving the printer driver for this printer,
1630 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1631 * will keep NT clients happy --jerry
1634 if (lp_use_client_driver(snum)
1635 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1637 printer_default->access_required = PRINTER_ACCESS_USE;
1640 /* check smb.conf parameters and the the sec_desc */
1642 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1643 DEBUG(3, ("access DENIED for printer open\n"));
1644 close_printer_handle(p, handle);
1645 return WERR_ACCESS_DENIED;
1648 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1649 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1650 close_printer_handle(p, handle);
1651 return WERR_ACCESS_DENIED;
1654 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1655 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1656 else
1657 printer_default->access_required = PRINTER_ACCESS_USE;
1659 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1660 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1664 Printer->access_granted = printer_default->access_required;
1667 * If the client sent a devmode in the OpenPrinter() call, then
1668 * save it here in case we get a job submission on this handle
1671 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1672 && q_u->printer_default.devmode_cont.devmode_ptr )
1674 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1675 &Printer->nt_devmode );
1678 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1679 optimization in Windows 2000 clients --jerry */
1681 if ( RA_WIN2K == get_remote_arch() )
1682 usleep( 384000 );
1684 return WERR_OK;
1687 /****************************************************************************
1688 ****************************************************************************/
1690 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1691 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1693 BOOL ret = True;
1695 switch (level) {
1696 case 2:
1697 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1698 break;
1699 default:
1700 break;
1703 return ret;
1706 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1707 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1709 BOOL result = True;
1711 switch (level) {
1712 case 3:
1713 printer->info_3=NULL;
1714 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1715 result = False;
1716 break;
1717 case 6:
1718 printer->info_6=NULL;
1719 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1720 result = False;
1721 break;
1722 default:
1723 break;
1726 return result;
1729 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1730 NT_DEVICEMODE **pp_nt_devmode)
1732 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1735 * Ensure nt_devmode is a valid pointer
1736 * as we will be overwriting it.
1739 if (nt_devmode == NULL) {
1740 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1741 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1742 return False;
1745 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1746 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1748 nt_devmode->specversion=devmode->specversion;
1749 nt_devmode->driverversion=devmode->driverversion;
1750 nt_devmode->size=devmode->size;
1751 nt_devmode->fields=devmode->fields;
1752 nt_devmode->orientation=devmode->orientation;
1753 nt_devmode->papersize=devmode->papersize;
1754 nt_devmode->paperlength=devmode->paperlength;
1755 nt_devmode->paperwidth=devmode->paperwidth;
1756 nt_devmode->scale=devmode->scale;
1757 nt_devmode->copies=devmode->copies;
1758 nt_devmode->defaultsource=devmode->defaultsource;
1759 nt_devmode->printquality=devmode->printquality;
1760 nt_devmode->color=devmode->color;
1761 nt_devmode->duplex=devmode->duplex;
1762 nt_devmode->yresolution=devmode->yresolution;
1763 nt_devmode->ttoption=devmode->ttoption;
1764 nt_devmode->collate=devmode->collate;
1766 nt_devmode->logpixels=devmode->logpixels;
1767 nt_devmode->bitsperpel=devmode->bitsperpel;
1768 nt_devmode->pelswidth=devmode->pelswidth;
1769 nt_devmode->pelsheight=devmode->pelsheight;
1770 nt_devmode->displayflags=devmode->displayflags;
1771 nt_devmode->displayfrequency=devmode->displayfrequency;
1772 nt_devmode->icmmethod=devmode->icmmethod;
1773 nt_devmode->icmintent=devmode->icmintent;
1774 nt_devmode->mediatype=devmode->mediatype;
1775 nt_devmode->dithertype=devmode->dithertype;
1776 nt_devmode->reserved1=devmode->reserved1;
1777 nt_devmode->reserved2=devmode->reserved2;
1778 nt_devmode->panningwidth=devmode->panningwidth;
1779 nt_devmode->panningheight=devmode->panningheight;
1782 * Only change private and driverextra if the incoming devmode
1783 * has a new one. JRA.
1786 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1787 SAFE_FREE(nt_devmode->private);
1788 nt_devmode->driverextra=devmode->driverextra;
1789 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1790 return False;
1791 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1794 *pp_nt_devmode = nt_devmode;
1796 return True;
1799 /********************************************************************
1800 * _spoolss_enddocprinter_internal.
1801 ********************************************************************/
1803 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1805 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1806 int snum;
1808 if (!Printer) {
1809 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1810 return WERR_BADFID;
1813 if (!get_printer_snum(p, handle, &snum))
1814 return WERR_BADFID;
1816 Printer->document_started=False;
1817 print_job_end(snum, Printer->jobid,True);
1818 /* error codes unhandled so far ... */
1820 return WERR_OK;
1823 /********************************************************************
1824 * api_spoolss_closeprinter
1825 ********************************************************************/
1827 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1829 POLICY_HND *handle = &q_u->handle;
1831 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1833 if (Printer && Printer->document_started)
1834 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1836 if (!close_printer_handle(p, handle))
1837 return WERR_BADFID;
1839 /* clear the returned printer handle. Observed behavior
1840 from Win2k server. Don't think this really matters.
1841 Previous code just copied the value of the closed
1842 handle. --jerry */
1844 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1846 return WERR_OK;
1849 /********************************************************************
1850 * api_spoolss_deleteprinter
1852 ********************************************************************/
1854 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1856 POLICY_HND *handle = &q_u->handle;
1857 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1858 WERROR result;
1860 if (Printer && Printer->document_started)
1861 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1863 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1865 result = delete_printer_handle(p, handle);
1867 update_c_setprinter(False);
1869 return result;
1872 /*******************************************************************
1873 * static function to lookup the version id corresponding to an
1874 * long architecture string
1875 ******************************************************************/
1877 static int get_version_id (char * arch)
1879 int i;
1880 struct table_node archi_table[]= {
1882 {"Windows 4.0", "WIN40", 0 },
1883 {"Windows NT x86", "W32X86", 2 },
1884 {"Windows NT R4000", "W32MIPS", 2 },
1885 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1886 {"Windows NT PowerPC", "W32PPC", 2 },
1887 {NULL, "", -1 }
1890 for (i=0; archi_table[i].long_archi != NULL; i++)
1892 if (strcmp(arch, archi_table[i].long_archi) == 0)
1893 return (archi_table[i].version);
1896 return -1;
1899 /********************************************************************
1900 * _spoolss_deleteprinterdriver
1901 ********************************************************************/
1903 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1905 fstring driver;
1906 fstring arch;
1907 NT_PRINTER_DRIVER_INFO_LEVEL info;
1908 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1909 int version;
1910 struct current_user user;
1911 WERROR status;
1912 WERROR status_win2k = WERR_ACCESS_DENIED;
1914 get_current_user(&user, p);
1916 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1917 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1919 /* check that we have a valid driver name first */
1921 if ((version=get_version_id(arch)) == -1)
1922 return WERR_INVALID_ENVIRONMENT;
1924 ZERO_STRUCT(info);
1925 ZERO_STRUCT(info_win2k);
1927 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1929 /* try for Win2k driver if "Windows NT x86" */
1931 if ( version == 2 ) {
1932 version = 3;
1933 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1934 status = WERR_UNKNOWN_PRINTER_DRIVER;
1935 goto done;
1938 /* otherwise it was a failure */
1939 else {
1940 status = WERR_UNKNOWN_PRINTER_DRIVER;
1941 goto done;
1946 if (printer_driver_in_use(info.info_3)) {
1947 status = WERR_PRINTER_DRIVER_IN_USE;
1948 goto done;
1951 if ( version == 2 )
1953 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1955 /* if we get to here, we now have 2 driver info structures to remove */
1956 /* remove the Win2k driver first*/
1958 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1959 free_a_printer_driver( info_win2k, 3 );
1961 /* this should not have failed---if it did, report to client */
1962 if ( !W_ERROR_IS_OK(status_win2k) )
1963 goto done;
1967 status = delete_printer_driver(info.info_3, &user, version, False);
1969 /* if at least one of the deletes succeeded return OK */
1971 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1972 status = WERR_OK;
1974 done:
1975 free_a_printer_driver( info, 3 );
1977 return status;
1980 /********************************************************************
1981 * spoolss_deleteprinterdriverex
1982 ********************************************************************/
1984 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1986 fstring driver;
1987 fstring arch;
1988 NT_PRINTER_DRIVER_INFO_LEVEL info;
1989 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1990 int version;
1991 uint32 flags = q_u->delete_flags;
1992 BOOL delete_files;
1993 struct current_user user;
1994 WERROR status;
1995 WERROR status_win2k = WERR_ACCESS_DENIED;
1997 get_current_user(&user, p);
1999 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2000 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2002 /* check that we have a valid driver name first */
2003 if ((version=get_version_id(arch)) == -1) {
2004 /* this is what NT returns */
2005 return WERR_INVALID_ENVIRONMENT;
2008 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2009 version = q_u->version;
2011 ZERO_STRUCT(info);
2012 ZERO_STRUCT(info_win2k);
2014 status = get_a_printer_driver(&info, 3, driver, arch, version);
2016 if ( !W_ERROR_IS_OK(status) )
2019 * if the client asked for a specific version,
2020 * or this is something other than Windows NT x86,
2021 * then we've failed
2024 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2025 goto done;
2027 /* try for Win2k driver if "Windows NT x86" */
2029 version = 3;
2030 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2031 status = WERR_UNKNOWN_PRINTER_DRIVER;
2032 goto done;
2036 if ( printer_driver_in_use(info.info_3) ) {
2037 status = WERR_PRINTER_DRIVER_IN_USE;
2038 goto done;
2042 * we have a couple of cases to consider.
2043 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2044 * then the delete should fail if **any** files overlap with
2045 * other drivers
2046 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2047 * non-overlapping files
2048 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2049 * is set, the do not delete any files
2050 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2053 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2055 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2057 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2058 /* no idea of the correct error here */
2059 status = WERR_ACCESS_DENIED;
2060 goto done;
2064 /* also check for W32X86/3 if necessary; maybe we already have? */
2066 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2067 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2070 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2071 /* no idea of the correct error here */
2072 free_a_printer_driver( info_win2k, 3 );
2073 status = WERR_ACCESS_DENIED;
2074 goto done;
2077 /* if we get to here, we now have 2 driver info structures to remove */
2078 /* remove the Win2k driver first*/
2080 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2081 free_a_printer_driver( info_win2k, 3 );
2083 /* this should not have failed---if it did, report to client */
2085 if ( !W_ERROR_IS_OK(status_win2k) )
2086 goto done;
2090 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2092 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2093 status = WERR_OK;
2094 done:
2095 free_a_printer_driver( info, 3 );
2097 return status;
2101 /****************************************************************************
2102 Internal routine for retreiving printerdata
2103 ***************************************************************************/
2105 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2106 const char *key, const char *value, uint32 *type, uint8 **data,
2107 uint32 *needed, uint32 in_size )
2109 REGISTRY_VALUE *val;
2110 int size, data_len;
2112 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2113 return WERR_BADFILE;
2115 *type = regval_type( val );
2117 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2119 size = regval_size( val );
2121 /* copy the min(in_size, len) */
2123 if ( in_size ) {
2124 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2126 /* special case for 0 length values */
2127 if ( data_len ) {
2128 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2129 return WERR_NOMEM;
2131 else {
2132 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2133 return WERR_NOMEM;
2136 else
2137 *data = NULL;
2139 *needed = size;
2141 DEBUG(5,("get_printer_dataex: copy done\n"));
2143 return WERR_OK;
2146 /****************************************************************************
2147 Internal routine for removing printerdata
2148 ***************************************************************************/
2150 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2152 return delete_printer_data( printer->info_2, key, value );
2155 /****************************************************************************
2156 Internal routine for storing printerdata
2157 ***************************************************************************/
2159 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2160 uint32 type, uint8 *data, int real_len )
2162 delete_printer_data( printer->info_2, key, value );
2164 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2167 /********************************************************************
2168 GetPrinterData on a printer server Handle.
2169 ********************************************************************/
2171 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2173 int i;
2175 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2177 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2178 *type = 0x4;
2179 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2180 return WERR_NOMEM;
2181 *needed = 0x4;
2182 return WERR_OK;
2185 if (!StrCaseCmp(value, "BeepEnabled")) {
2186 *type = 0x4;
2187 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2188 return WERR_NOMEM;
2189 SIVAL(*data, 0, 0x00);
2190 *needed = 0x4;
2191 return WERR_OK;
2194 if (!StrCaseCmp(value, "EventLog")) {
2195 *type = 0x4;
2196 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2197 return WERR_NOMEM;
2198 /* formally was 0x1b */
2199 SIVAL(*data, 0, 0x0);
2200 *needed = 0x4;
2201 return WERR_OK;
2204 if (!StrCaseCmp(value, "NetPopup")) {
2205 *type = 0x4;
2206 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2207 return WERR_NOMEM;
2208 SIVAL(*data, 0, 0x00);
2209 *needed = 0x4;
2210 return WERR_OK;
2213 if (!StrCaseCmp(value, "MajorVersion")) {
2214 *type = 0x4;
2215 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2216 return WERR_NOMEM;
2217 #ifdef HAVE_ADS
2218 SIVAL(*data, 0, 3);
2219 #else
2220 SIVAL(*data, 0, 2);
2221 #endif
2222 *needed = 0x4;
2223 return WERR_OK;
2226 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2227 fstring string;
2229 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2230 *type = 0x1;
2231 *needed = 2*(strlen(string)+1);
2232 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2233 return WERR_NOMEM;
2234 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2236 /* it's done by hand ready to go on the wire */
2237 for (i=0; i<strlen(string); i++) {
2238 (*data)[2*i]=string[i];
2239 (*data)[2*i+1]='\0';
2241 return WERR_OK;
2244 if (!StrCaseCmp(value, "Architecture")) {
2245 pstring string="Windows NT x86";
2246 *type = 0x1;
2247 *needed = 2*(strlen(string)+1);
2248 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2249 return WERR_NOMEM;
2250 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2251 for (i=0; i<strlen(string); i++) {
2252 (*data)[2*i]=string[i];
2253 (*data)[2*i+1]='\0';
2255 return WERR_OK;
2258 if (!StrCaseCmp(value, "DsPresent")) {
2259 *type = 0x4;
2260 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2261 return WERR_NOMEM;
2262 SIVAL(*data, 0, 0x01);
2263 *needed = 0x4;
2264 return WERR_OK;
2267 if (!StrCaseCmp(value, "DNSMachineName")) {
2268 pstring hostname;
2270 if (!get_myfullname(hostname))
2271 return WERR_BADFILE;
2272 *type = 0x1;
2273 *needed = 2*(strlen(hostname)+1);
2274 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2275 return WERR_NOMEM;
2276 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2277 for (i=0; i<strlen(hostname); i++) {
2278 (*data)[2*i]=hostname[i];
2279 (*data)[2*i+1]='\0';
2281 return WERR_OK;
2285 return WERR_BADFILE;
2288 /********************************************************************
2289 * spoolss_getprinterdata
2290 ********************************************************************/
2292 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2294 POLICY_HND *handle = &q_u->handle;
2295 UNISTR2 *valuename = &q_u->valuename;
2296 uint32 in_size = q_u->size;
2297 uint32 *type = &r_u->type;
2298 uint32 *out_size = &r_u->size;
2299 uint8 **data = &r_u->data;
2300 uint32 *needed = &r_u->needed;
2301 WERROR status;
2302 fstring value;
2303 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2304 NT_PRINTER_INFO_LEVEL *printer = NULL;
2305 int snum = 0;
2308 * Reminder: when it's a string, the length is in BYTES
2309 * even if UNICODE is negociated.
2311 * JFM, 4/19/1999
2314 *out_size = in_size;
2316 /* in case of problem, return some default values */
2318 *needed = 0;
2319 *type = 0;
2321 DEBUG(4,("_spoolss_getprinterdata\n"));
2323 if ( !Printer ) {
2324 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2325 status = WERR_BADFID;
2326 goto done;
2329 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2331 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2332 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2333 else
2335 if ( !get_printer_snum(p,handle, &snum) ) {
2336 status = WERR_BADFID;
2337 goto done;
2340 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2341 if ( !W_ERROR_IS_OK(status) )
2342 goto done;
2344 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2346 if ( strequal(value, "ChangeId") ) {
2347 *type = REG_DWORD;
2348 *needed = sizeof(uint32);
2349 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2350 status = WERR_NOMEM;
2351 goto done;
2353 **data = printer->info_2->changeid;
2354 status = WERR_OK;
2356 else
2357 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2360 if (*needed > *out_size)
2361 status = WERR_MORE_DATA;
2363 done:
2364 if ( !W_ERROR_IS_OK(status) )
2366 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2368 /* reply this param doesn't exist */
2370 if ( *out_size ) {
2371 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2372 if ( printer )
2373 free_a_printer( &printer, 2 );
2374 return WERR_NOMEM;
2377 else {
2378 *data = NULL;
2382 /* cleanup & exit */
2384 if ( printer )
2385 free_a_printer( &printer, 2 );
2387 return status;
2390 /*********************************************************
2391 Connect to the client machine.
2392 **********************************************************/
2394 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, const char *remote_machine)
2396 ZERO_STRUCTP(the_cli);
2397 if(cli_initialise(the_cli) == NULL) {
2398 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2399 return False;
2402 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2403 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2404 cli_shutdown(the_cli);
2405 return False;
2408 if (ismyip(the_cli->dest_ip)) {
2409 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2410 cli_shutdown(the_cli);
2411 return False;
2414 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2415 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2416 cli_shutdown(the_cli);
2417 return False;
2420 if (!attempt_netbios_session_request(the_cli, lp_netbios_name(), remote_machine, &the_cli->dest_ip)) {
2421 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2422 remote_machine));
2423 cli_shutdown(the_cli);
2424 return False;
2427 the_cli->protocol = PROTOCOL_NT1;
2429 if (!cli_negprot(the_cli)) {
2430 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2431 cli_shutdown(the_cli);
2432 return False;
2435 if (the_cli->protocol != PROTOCOL_NT1) {
2436 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2437 cli_shutdown(the_cli);
2438 return False;
2442 * Do an anonymous session setup.
2445 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2446 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2447 cli_shutdown(the_cli);
2448 return False;
2451 if (!(the_cli->sec_mode & 1)) {
2452 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2453 cli_shutdown(the_cli);
2454 return False;
2457 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2458 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2459 cli_shutdown(the_cli);
2460 return False;
2464 * Ok - we have an anonymous connection to the IPC$ share.
2465 * Now start the NT Domain stuff :-).
2468 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2469 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)));
2470 cli_nt_session_close(the_cli);
2471 cli_ulogoff(the_cli);
2472 cli_shutdown(the_cli);
2473 return False;
2476 return True;
2479 /***************************************************************************
2480 Connect to the client.
2481 ****************************************************************************/
2483 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2485 WERROR result;
2488 * If it's the first connection, contact the client
2489 * and connect to the IPC$ share anonumously
2491 if (smb_connections==0) {
2492 fstring unix_printer;
2494 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2496 if(!spoolss_connect_to_client(&notify_cli, unix_printer))
2497 return False;
2499 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2500 /* Tell the connections db we're now interested in printer
2501 * notify messages. */
2502 register_message_flags( True, FLAG_MSG_PRINTING );
2506 * Tell the specific printing tdb we want messages for this printer
2507 * by registering our PID.
2510 if (!print_notify_register_pid(snum))
2511 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2513 smb_connections++;
2515 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2516 type, handle);
2518 if (!W_ERROR_IS_OK(result))
2519 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2520 dos_errstr(result)));
2522 return (W_ERROR_IS_OK(result));
2525 /********************************************************************
2526 * _spoolss_rffpcnex
2527 * ReplyFindFirstPrinterChangeNotifyEx
2529 * before replying OK: status=0 a rpc call is made to the workstation
2530 * asking ReplyOpenPrinter
2532 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2533 * called from api_spoolss_rffpcnex
2534 ********************************************************************/
2536 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2538 POLICY_HND *handle = &q_u->handle;
2539 uint32 flags = q_u->flags;
2540 uint32 options = q_u->options;
2541 UNISTR2 *localmachine = &q_u->localmachine;
2542 uint32 printerlocal = q_u->printerlocal;
2543 int snum = -1;
2544 SPOOL_NOTIFY_OPTION *option = q_u->option;
2546 /* store the notify value in the printer struct */
2548 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2550 if (!Printer) {
2551 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2552 return WERR_BADFID;
2555 Printer->notify.flags=flags;
2556 Printer->notify.options=options;
2557 Printer->notify.printerlocal=printerlocal;
2559 if (Printer->notify.option)
2560 free_spool_notify_option(&Printer->notify.option);
2562 Printer->notify.option=dup_spool_notify_option(option);
2564 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2565 sizeof(Printer->notify.localmachine)-1);
2567 /* Connect to the client machine and send a ReplyOpenPrinter */
2569 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2570 snum = -1;
2571 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2572 !get_printer_snum(p, handle, &snum) )
2573 return WERR_BADFID;
2575 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2576 Printer->notify.printerlocal, 1,
2577 &Printer->notify.client_hnd))
2578 return WERR_SERVER_UNAVAILABLE;
2580 Printer->notify.client_connected=True;
2582 return WERR_OK;
2585 /*******************************************************************
2586 * fill a notify_info_data with the servername
2587 ********************************************************************/
2589 void spoolss_notify_server_name(int snum,
2590 SPOOL_NOTIFY_INFO_DATA *data,
2591 print_queue_struct *queue,
2592 NT_PRINTER_INFO_LEVEL *printer,
2593 TALLOC_CTX *mem_ctx)
2595 pstring temp_name, temp;
2596 uint32 len;
2598 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2600 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2602 data->notify_data.data.length = len;
2603 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2605 if (!data->notify_data.data.string) {
2606 data->notify_data.data.length = 0;
2607 return;
2610 memcpy(data->notify_data.data.string, temp, len);
2613 /*******************************************************************
2614 * fill a notify_info_data with the printername (not including the servername).
2615 ********************************************************************/
2617 void spoolss_notify_printer_name(int snum,
2618 SPOOL_NOTIFY_INFO_DATA *data,
2619 print_queue_struct *queue,
2620 NT_PRINTER_INFO_LEVEL *printer,
2621 TALLOC_CTX *mem_ctx)
2623 pstring temp;
2624 uint32 len;
2626 /* the notify name should not contain the \\server\ part */
2627 char *p = strrchr(printer->info_2->printername, '\\');
2629 if (!p) {
2630 p = printer->info_2->printername;
2631 } else {
2632 p++;
2635 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2637 data->notify_data.data.length = len;
2638 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2640 if (!data->notify_data.data.string) {
2641 data->notify_data.data.length = 0;
2642 return;
2645 memcpy(data->notify_data.data.string, temp, len);
2648 /*******************************************************************
2649 * fill a notify_info_data with the servicename
2650 ********************************************************************/
2652 void spoolss_notify_share_name(int snum,
2653 SPOOL_NOTIFY_INFO_DATA *data,
2654 print_queue_struct *queue,
2655 NT_PRINTER_INFO_LEVEL *printer,
2656 TALLOC_CTX *mem_ctx)
2658 pstring temp;
2659 uint32 len;
2661 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2663 data->notify_data.data.length = len;
2664 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2666 if (!data->notify_data.data.string) {
2667 data->notify_data.data.length = 0;
2668 return;
2671 memcpy(data->notify_data.data.string, temp, len);
2674 /*******************************************************************
2675 * fill a notify_info_data with the port name
2676 ********************************************************************/
2678 void spoolss_notify_port_name(int snum,
2679 SPOOL_NOTIFY_INFO_DATA *data,
2680 print_queue_struct *queue,
2681 NT_PRINTER_INFO_LEVEL *printer,
2682 TALLOC_CTX *mem_ctx)
2684 pstring temp;
2685 uint32 len;
2687 /* even if it's strange, that's consistant in all the code */
2689 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2691 data->notify_data.data.length = len;
2692 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2694 if (!data->notify_data.data.string) {
2695 data->notify_data.data.length = 0;
2696 return;
2699 memcpy(data->notify_data.data.string, temp, len);
2702 /*******************************************************************
2703 * fill a notify_info_data with the printername
2704 * but it doesn't exist, have to see what to do
2705 ********************************************************************/
2707 void spoolss_notify_driver_name(int snum,
2708 SPOOL_NOTIFY_INFO_DATA *data,
2709 print_queue_struct *queue,
2710 NT_PRINTER_INFO_LEVEL *printer,
2711 TALLOC_CTX *mem_ctx)
2713 pstring temp;
2714 uint32 len;
2716 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2718 data->notify_data.data.length = len;
2719 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2721 if (!data->notify_data.data.string) {
2722 data->notify_data.data.length = 0;
2723 return;
2726 memcpy(data->notify_data.data.string, temp, len);
2729 /*******************************************************************
2730 * fill a notify_info_data with the comment
2731 ********************************************************************/
2733 void spoolss_notify_comment(int snum,
2734 SPOOL_NOTIFY_INFO_DATA *data,
2735 print_queue_struct *queue,
2736 NT_PRINTER_INFO_LEVEL *printer,
2737 TALLOC_CTX *mem_ctx)
2739 pstring temp;
2740 uint32 len;
2742 if (*printer->info_2->comment == '\0')
2743 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2744 else
2745 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2747 data->notify_data.data.length = len;
2748 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2750 if (!data->notify_data.data.string) {
2751 data->notify_data.data.length = 0;
2752 return;
2755 memcpy(data->notify_data.data.string, temp, len);
2758 /*******************************************************************
2759 * fill a notify_info_data with the comment
2760 * location = "Room 1, floor 2, building 3"
2761 ********************************************************************/
2763 void spoolss_notify_location(int snum,
2764 SPOOL_NOTIFY_INFO_DATA *data,
2765 print_queue_struct *queue,
2766 NT_PRINTER_INFO_LEVEL *printer,
2767 TALLOC_CTX *mem_ctx)
2769 pstring temp;
2770 uint32 len;
2772 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2774 data->notify_data.data.length = len;
2775 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2777 if (!data->notify_data.data.string) {
2778 data->notify_data.data.length = 0;
2779 return;
2782 memcpy(data->notify_data.data.string, temp, len);
2785 /*******************************************************************
2786 * fill a notify_info_data with the device mode
2787 * jfm:xxxx don't to it for know but that's a real problem !!!
2788 ********************************************************************/
2790 static void spoolss_notify_devmode(int snum,
2791 SPOOL_NOTIFY_INFO_DATA *data,
2792 print_queue_struct *queue,
2793 NT_PRINTER_INFO_LEVEL *printer,
2794 TALLOC_CTX *mem_ctx)
2798 /*******************************************************************
2799 * fill a notify_info_data with the separator file name
2800 ********************************************************************/
2802 void spoolss_notify_sepfile(int snum,
2803 SPOOL_NOTIFY_INFO_DATA *data,
2804 print_queue_struct *queue,
2805 NT_PRINTER_INFO_LEVEL *printer,
2806 TALLOC_CTX *mem_ctx)
2808 pstring temp;
2809 uint32 len;
2811 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2813 data->notify_data.data.length = len;
2814 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2816 if (!data->notify_data.data.string) {
2817 data->notify_data.data.length = 0;
2818 return;
2821 memcpy(data->notify_data.data.string, temp, len);
2824 /*******************************************************************
2825 * fill a notify_info_data with the print processor
2826 * jfm:xxxx return always winprint to indicate we don't do anything to it
2827 ********************************************************************/
2829 void spoolss_notify_print_processor(int snum,
2830 SPOOL_NOTIFY_INFO_DATA *data,
2831 print_queue_struct *queue,
2832 NT_PRINTER_INFO_LEVEL *printer,
2833 TALLOC_CTX *mem_ctx)
2835 pstring temp;
2836 uint32 len;
2838 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2840 data->notify_data.data.length = len;
2841 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2843 if (!data->notify_data.data.string) {
2844 data->notify_data.data.length = 0;
2845 return;
2848 memcpy(data->notify_data.data.string, temp, len);
2851 /*******************************************************************
2852 * fill a notify_info_data with the print processor options
2853 * jfm:xxxx send an empty string
2854 ********************************************************************/
2856 void spoolss_notify_parameters(int snum,
2857 SPOOL_NOTIFY_INFO_DATA *data,
2858 print_queue_struct *queue,
2859 NT_PRINTER_INFO_LEVEL *printer,
2860 TALLOC_CTX *mem_ctx)
2862 pstring temp;
2863 uint32 len;
2865 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2867 data->notify_data.data.length = len;
2868 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2870 if (!data->notify_data.data.string) {
2871 data->notify_data.data.length = 0;
2872 return;
2875 memcpy(data->notify_data.data.string, temp, len);
2878 /*******************************************************************
2879 * fill a notify_info_data with the data type
2880 * jfm:xxxx always send RAW as data type
2881 ********************************************************************/
2883 void spoolss_notify_datatype(int snum,
2884 SPOOL_NOTIFY_INFO_DATA *data,
2885 print_queue_struct *queue,
2886 NT_PRINTER_INFO_LEVEL *printer,
2887 TALLOC_CTX *mem_ctx)
2889 pstring temp;
2890 uint32 len;
2892 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2894 data->notify_data.data.length = len;
2895 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2897 if (!data->notify_data.data.string) {
2898 data->notify_data.data.length = 0;
2899 return;
2902 memcpy(data->notify_data.data.string, temp, len);
2905 /*******************************************************************
2906 * fill a notify_info_data with the security descriptor
2907 * jfm:xxxx send an null pointer to say no security desc
2908 * have to implement security before !
2909 ********************************************************************/
2911 static void spoolss_notify_security_desc(int snum,
2912 SPOOL_NOTIFY_INFO_DATA *data,
2913 print_queue_struct *queue,
2914 NT_PRINTER_INFO_LEVEL *printer,
2915 TALLOC_CTX *mem_ctx)
2917 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2918 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2921 /*******************************************************************
2922 * fill a notify_info_data with the attributes
2923 * jfm:xxxx a samba printer is always shared
2924 ********************************************************************/
2926 void spoolss_notify_attributes(int snum,
2927 SPOOL_NOTIFY_INFO_DATA *data,
2928 print_queue_struct *queue,
2929 NT_PRINTER_INFO_LEVEL *printer,
2930 TALLOC_CTX *mem_ctx)
2932 data->notify_data.value[0] = printer->info_2->attributes;
2933 data->notify_data.value[1] = 0;
2936 /*******************************************************************
2937 * fill a notify_info_data with the priority
2938 ********************************************************************/
2940 static void spoolss_notify_priority(int snum,
2941 SPOOL_NOTIFY_INFO_DATA *data,
2942 print_queue_struct *queue,
2943 NT_PRINTER_INFO_LEVEL *printer,
2944 TALLOC_CTX *mem_ctx)
2946 data->notify_data.value[0] = printer->info_2->priority;
2947 data->notify_data.value[1] = 0;
2950 /*******************************************************************
2951 * fill a notify_info_data with the default priority
2952 ********************************************************************/
2954 static void spoolss_notify_default_priority(int snum,
2955 SPOOL_NOTIFY_INFO_DATA *data,
2956 print_queue_struct *queue,
2957 NT_PRINTER_INFO_LEVEL *printer,
2958 TALLOC_CTX *mem_ctx)
2960 data->notify_data.value[0] = printer->info_2->default_priority;
2961 data->notify_data.value[1] = 0;
2964 /*******************************************************************
2965 * fill a notify_info_data with the start time
2966 ********************************************************************/
2968 static void spoolss_notify_start_time(int snum,
2969 SPOOL_NOTIFY_INFO_DATA *data,
2970 print_queue_struct *queue,
2971 NT_PRINTER_INFO_LEVEL *printer,
2972 TALLOC_CTX *mem_ctx)
2974 data->notify_data.value[0] = printer->info_2->starttime;
2975 data->notify_data.value[1] = 0;
2978 /*******************************************************************
2979 * fill a notify_info_data with the until time
2980 ********************************************************************/
2982 static void spoolss_notify_until_time(int snum,
2983 SPOOL_NOTIFY_INFO_DATA *data,
2984 print_queue_struct *queue,
2985 NT_PRINTER_INFO_LEVEL *printer,
2986 TALLOC_CTX *mem_ctx)
2988 data->notify_data.value[0] = printer->info_2->untiltime;
2989 data->notify_data.value[1] = 0;
2992 /*******************************************************************
2993 * fill a notify_info_data with the status
2994 ********************************************************************/
2996 static void spoolss_notify_status(int snum,
2997 SPOOL_NOTIFY_INFO_DATA *data,
2998 print_queue_struct *queue,
2999 NT_PRINTER_INFO_LEVEL *printer,
3000 TALLOC_CTX *mem_ctx)
3002 print_status_struct status;
3004 print_queue_length(snum, &status);
3005 data->notify_data.value[0]=(uint32) status.status;
3006 data->notify_data.value[1] = 0;
3009 /*******************************************************************
3010 * fill a notify_info_data with the number of jobs queued
3011 ********************************************************************/
3013 void spoolss_notify_cjobs(int snum,
3014 SPOOL_NOTIFY_INFO_DATA *data,
3015 print_queue_struct *queue,
3016 NT_PRINTER_INFO_LEVEL *printer,
3017 TALLOC_CTX *mem_ctx)
3019 data->notify_data.value[0] = print_queue_length(snum, NULL);
3020 data->notify_data.value[1] = 0;
3023 /*******************************************************************
3024 * fill a notify_info_data with the average ppm
3025 ********************************************************************/
3027 static void spoolss_notify_average_ppm(int snum,
3028 SPOOL_NOTIFY_INFO_DATA *data,
3029 print_queue_struct *queue,
3030 NT_PRINTER_INFO_LEVEL *printer,
3031 TALLOC_CTX *mem_ctx)
3033 /* always respond 8 pages per minutes */
3034 /* a little hard ! */
3035 data->notify_data.value[0] = printer->info_2->averageppm;
3036 data->notify_data.value[1] = 0;
3039 /*******************************************************************
3040 * fill a notify_info_data with username
3041 ********************************************************************/
3043 static void spoolss_notify_username(int snum,
3044 SPOOL_NOTIFY_INFO_DATA *data,
3045 print_queue_struct *queue,
3046 NT_PRINTER_INFO_LEVEL *printer,
3047 TALLOC_CTX *mem_ctx)
3049 pstring temp;
3050 uint32 len;
3052 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3054 data->notify_data.data.length = len;
3055 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3057 if (!data->notify_data.data.string) {
3058 data->notify_data.data.length = 0;
3059 return;
3062 memcpy(data->notify_data.data.string, temp, len);
3065 /*******************************************************************
3066 * fill a notify_info_data with job status
3067 ********************************************************************/
3069 static void spoolss_notify_job_status(int snum,
3070 SPOOL_NOTIFY_INFO_DATA *data,
3071 print_queue_struct *queue,
3072 NT_PRINTER_INFO_LEVEL *printer,
3073 TALLOC_CTX *mem_ctx)
3075 data->notify_data.value[0]=nt_printj_status(queue->status);
3076 data->notify_data.value[1] = 0;
3079 /*******************************************************************
3080 * fill a notify_info_data with job name
3081 ********************************************************************/
3083 static void spoolss_notify_job_name(int snum,
3084 SPOOL_NOTIFY_INFO_DATA *data,
3085 print_queue_struct *queue,
3086 NT_PRINTER_INFO_LEVEL *printer,
3087 TALLOC_CTX *mem_ctx)
3089 pstring temp;
3090 uint32 len;
3092 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3094 data->notify_data.data.length = len;
3095 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3097 if (!data->notify_data.data.string) {
3098 data->notify_data.data.length = 0;
3099 return;
3102 memcpy(data->notify_data.data.string, temp, len);
3105 /*******************************************************************
3106 * fill a notify_info_data with job status
3107 ********************************************************************/
3109 static void spoolss_notify_job_status_string(int snum,
3110 SPOOL_NOTIFY_INFO_DATA *data,
3111 print_queue_struct *queue,
3112 NT_PRINTER_INFO_LEVEL *printer,
3113 TALLOC_CTX *mem_ctx)
3116 * Now we're returning job status codes we just return a "" here. JRA.
3119 const char *p = "";
3120 pstring temp;
3121 uint32 len;
3123 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3124 p = "unknown";
3126 switch (queue->status) {
3127 case LPQ_QUEUED:
3128 p = "Queued";
3129 break;
3130 case LPQ_PAUSED:
3131 p = ""; /* NT provides the paused string */
3132 break;
3133 case LPQ_SPOOLING:
3134 p = "Spooling";
3135 break;
3136 case LPQ_PRINTING:
3137 p = "Printing";
3138 break;
3140 #endif /* NO LONGER NEEDED. */
3142 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3144 data->notify_data.data.length = len;
3145 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3147 if (!data->notify_data.data.string) {
3148 data->notify_data.data.length = 0;
3149 return;
3152 memcpy(data->notify_data.data.string, temp, len);
3155 /*******************************************************************
3156 * fill a notify_info_data with job time
3157 ********************************************************************/
3159 static void spoolss_notify_job_time(int snum,
3160 SPOOL_NOTIFY_INFO_DATA *data,
3161 print_queue_struct *queue,
3162 NT_PRINTER_INFO_LEVEL *printer,
3163 TALLOC_CTX *mem_ctx)
3165 data->notify_data.value[0]=0x0;
3166 data->notify_data.value[1]=0;
3169 /*******************************************************************
3170 * fill a notify_info_data with job size
3171 ********************************************************************/
3173 static void spoolss_notify_job_size(int snum,
3174 SPOOL_NOTIFY_INFO_DATA *data,
3175 print_queue_struct *queue,
3176 NT_PRINTER_INFO_LEVEL *printer,
3177 TALLOC_CTX *mem_ctx)
3179 data->notify_data.value[0]=queue->size;
3180 data->notify_data.value[1]=0;
3183 /*******************************************************************
3184 * fill a notify_info_data with page info
3185 ********************************************************************/
3186 static void spoolss_notify_total_pages(int snum,
3187 SPOOL_NOTIFY_INFO_DATA *data,
3188 print_queue_struct *queue,
3189 NT_PRINTER_INFO_LEVEL *printer,
3190 TALLOC_CTX *mem_ctx)
3192 data->notify_data.value[0]=queue->page_count;
3193 data->notify_data.value[1]=0;
3196 /*******************************************************************
3197 * fill a notify_info_data with pages printed info.
3198 ********************************************************************/
3199 static void spoolss_notify_pages_printed(int snum,
3200 SPOOL_NOTIFY_INFO_DATA *data,
3201 print_queue_struct *queue,
3202 NT_PRINTER_INFO_LEVEL *printer,
3203 TALLOC_CTX *mem_ctx)
3205 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3206 data->notify_data.value[1]=0;
3209 /*******************************************************************
3210 Fill a notify_info_data with job position.
3211 ********************************************************************/
3213 static void spoolss_notify_job_position(int snum,
3214 SPOOL_NOTIFY_INFO_DATA *data,
3215 print_queue_struct *queue,
3216 NT_PRINTER_INFO_LEVEL *printer,
3217 TALLOC_CTX *mem_ctx)
3219 data->notify_data.value[0]=queue->job;
3220 data->notify_data.value[1]=0;
3223 /*******************************************************************
3224 Fill a notify_info_data with submitted time.
3225 ********************************************************************/
3227 static void spoolss_notify_submitted_time(int snum,
3228 SPOOL_NOTIFY_INFO_DATA *data,
3229 print_queue_struct *queue,
3230 NT_PRINTER_INFO_LEVEL *printer,
3231 TALLOC_CTX *mem_ctx)
3233 struct tm *t;
3234 uint32 len;
3235 SYSTEMTIME st;
3236 char *p;
3238 t=gmtime(&queue->time);
3240 len = sizeof(SYSTEMTIME);
3242 data->notify_data.data.length = len;
3243 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3245 if (!data->notify_data.data.string) {
3246 data->notify_data.data.length = 0;
3247 return;
3250 make_systemtime(&st, t);
3253 * Systemtime must be linearized as a set of UINT16's.
3254 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3257 p = (char *)data->notify_data.data.string;
3258 SSVAL(p, 0, st.year);
3259 SSVAL(p, 2, st.month);
3260 SSVAL(p, 4, st.dayofweek);
3261 SSVAL(p, 6, st.day);
3262 SSVAL(p, 8, st.hour);
3263 SSVAL(p, 10, st.minute);
3264 SSVAL(p, 12, st.second);
3265 SSVAL(p, 14, st.milliseconds);
3268 struct s_notify_info_data_table
3270 uint16 type;
3271 uint16 field;
3272 const char *name;
3273 uint32 size;
3274 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3275 print_queue_struct *queue,
3276 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3279 /* A table describing the various print notification constants and
3280 whether the notification data is a pointer to a variable sized
3281 buffer, a one value uint32 or a two value uint32. */
3283 static const struct s_notify_info_data_table notify_info_data_table[] =
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3336 /*******************************************************************
3337 Return the size of info_data structure.
3338 ********************************************************************/
3340 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3342 int i=0;
3344 for (i = 0; i < sizeof(notify_info_data_table); i++)
3346 if ( (notify_info_data_table[i].type == type)
3347 && (notify_info_data_table[i].field == field) )
3349 switch(notify_info_data_table[i].size)
3351 case NOTIFY_ONE_VALUE:
3352 case NOTIFY_TWO_VALUE:
3353 return 1;
3354 case NOTIFY_STRING:
3355 return 2;
3357 /* The only pointer notify data I have seen on
3358 the wire is the submitted time and this has
3359 the notify size set to 4. -tpot */
3361 case NOTIFY_POINTER:
3362 return 4;
3364 case NOTIFY_SECDESC:
3365 return 5;
3370 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3372 return 0;
3375 /*******************************************************************
3376 Return the type of notify_info_data.
3377 ********************************************************************/
3379 static int type_of_notify_info_data(uint16 type, uint16 field)
3381 int i=0;
3383 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3384 if (notify_info_data_table[i].type == type &&
3385 notify_info_data_table[i].field == field)
3386 return notify_info_data_table[i].size;
3389 return False;
3392 /****************************************************************************
3393 ****************************************************************************/
3395 static int search_notify(uint16 type, uint16 field, int *value)
3397 int i;
3399 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3400 if (notify_info_data_table[i].type == type &&
3401 notify_info_data_table[i].field == field &&
3402 notify_info_data_table[i].fn != NULL) {
3403 *value = i;
3404 return True;
3408 return False;
3411 /****************************************************************************
3412 ****************************************************************************/
3414 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3416 info_data->type = type;
3417 info_data->field = field;
3418 info_data->reserved = 0;
3420 info_data->size = size_of_notify_info_data(type, field);
3421 info_data->enc_type = type_of_notify_info_data(type, field);
3423 info_data->id = id;
3428 /*******************************************************************
3430 * fill a notify_info struct with info asked
3432 ********************************************************************/
3434 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3435 snum, SPOOL_NOTIFY_OPTION_TYPE
3436 *option_type, uint32 id,
3437 TALLOC_CTX *mem_ctx)
3439 int field_num,j;
3440 uint16 type;
3441 uint16 field;
3443 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3444 NT_PRINTER_INFO_LEVEL *printer = NULL;
3445 print_queue_struct *queue=NULL;
3447 type=option_type->type;
3449 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3450 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3451 option_type->count, lp_servicename(snum)));
3453 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3454 return False;
3456 for(field_num=0; field_num<option_type->count; field_num++) {
3457 field = option_type->fields[field_num];
3459 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3461 if (!search_notify(type, field, &j) )
3462 continue;
3464 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3465 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3466 return False;
3467 } else
3468 info->data = tid;
3470 current_data = &info->data[info->count];
3472 construct_info_data(current_data, type, field, id);
3474 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3475 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3477 notify_info_data_table[j].fn(snum, current_data, queue,
3478 printer, mem_ctx);
3480 info->count++;
3483 free_a_printer(&printer, 2);
3484 return True;
3487 /*******************************************************************
3489 * fill a notify_info struct with info asked
3491 ********************************************************************/
3493 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3494 SPOOL_NOTIFY_INFO *info,
3495 NT_PRINTER_INFO_LEVEL *printer,
3496 int snum, SPOOL_NOTIFY_OPTION_TYPE
3497 *option_type, uint32 id,
3498 TALLOC_CTX *mem_ctx)
3500 int field_num,j;
3501 uint16 type;
3502 uint16 field;
3504 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3506 DEBUG(4,("construct_notify_jobs_info\n"));
3508 type = option_type->type;
3510 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3511 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3512 option_type->count));
3514 for(field_num=0; field_num<option_type->count; field_num++) {
3515 field = option_type->fields[field_num];
3517 if (!search_notify(type, field, &j) )
3518 continue;
3520 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3521 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3522 return False;
3524 else info->data = tid;
3526 current_data=&(info->data[info->count]);
3528 construct_info_data(current_data, type, field, id);
3529 notify_info_data_table[j].fn(snum, current_data, queue,
3530 printer, mem_ctx);
3531 info->count++;
3534 return True;
3538 * JFM: The enumeration is not that simple, it's even non obvious.
3540 * let's take an example: I want to monitor the PRINTER SERVER for
3541 * the printer's name and the number of jobs currently queued.
3542 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3543 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3545 * I have 3 printers on the back of my server.
3547 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3548 * structures.
3549 * Number Data Id
3550 * 1 printer 1 name 1
3551 * 2 printer 1 cjob 1
3552 * 3 printer 2 name 2
3553 * 4 printer 2 cjob 2
3554 * 5 printer 3 name 3
3555 * 6 printer 3 name 3
3557 * that's the print server case, the printer case is even worse.
3560 /*******************************************************************
3562 * enumerate all printers on the printserver
3563 * fill a notify_info struct with info asked
3565 ********************************************************************/
3567 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3568 SPOOL_NOTIFY_INFO *info,
3569 TALLOC_CTX *mem_ctx)
3571 int snum;
3572 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3573 int n_services=lp_numservices();
3574 int i;
3575 uint32 id;
3576 SPOOL_NOTIFY_OPTION *option;
3577 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3579 DEBUG(4,("printserver_notify_info\n"));
3581 if (!Printer)
3582 return WERR_BADFID;
3584 option=Printer->notify.option;
3585 id=1;
3586 info->version=2;
3587 info->data=NULL;
3588 info->count=0;
3590 for (i=0; i<option->count; i++) {
3591 option_type=&(option->ctr.type[i]);
3593 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3594 continue;
3596 for (snum=0; snum<n_services; snum++)
3598 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3599 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3603 #if 0
3605 * Debugging information, don't delete.
3608 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3609 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3610 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3612 for (i=0; i<info->count; i++) {
3613 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3614 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3615 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3617 #endif
3619 return WERR_OK;
3622 /*******************************************************************
3624 * fill a notify_info struct with info asked
3626 ********************************************************************/
3628 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3629 TALLOC_CTX *mem_ctx)
3631 int snum;
3632 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3633 int i;
3634 uint32 id;
3635 SPOOL_NOTIFY_OPTION *option;
3636 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3637 int count,j;
3638 print_queue_struct *queue=NULL;
3639 print_status_struct status;
3641 DEBUG(4,("printer_notify_info\n"));
3643 if (!Printer)
3644 return WERR_BADFID;
3646 option=Printer->notify.option;
3647 id = 0x0;
3648 info->version=2;
3649 info->data=NULL;
3650 info->count=0;
3652 get_printer_snum(p, hnd, &snum);
3654 for (i=0; i<option->count; i++) {
3655 option_type=&option->ctr.type[i];
3657 switch ( option_type->type ) {
3658 case PRINTER_NOTIFY_TYPE:
3659 if(construct_notify_printer_info(Printer, info, snum,
3660 option_type, id,
3661 mem_ctx))
3662 id--;
3663 break;
3665 case JOB_NOTIFY_TYPE: {
3666 NT_PRINTER_INFO_LEVEL *printer = NULL;
3668 count = print_queue_status(snum, &queue, &status);
3670 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3671 goto done;
3673 for (j=0; j<count; j++) {
3674 construct_notify_jobs_info(&queue[j], info,
3675 printer, snum,
3676 option_type,
3677 queue[j].job,
3678 mem_ctx);
3681 free_a_printer(&printer, 2);
3683 done:
3684 SAFE_FREE(queue);
3685 break;
3691 * Debugging information, don't delete.
3694 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3695 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3696 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3698 for (i=0; i<info->count; i++) {
3699 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3700 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3701 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3704 return WERR_OK;
3707 /********************************************************************
3708 * spoolss_rfnpcnex
3709 ********************************************************************/
3711 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3713 POLICY_HND *handle = &q_u->handle;
3714 SPOOL_NOTIFY_INFO *info = &r_u->info;
3716 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3717 WERROR result = WERR_BADFID;
3719 /* we always have a NOTIFY_INFO struct */
3720 r_u->info_ptr=0x1;
3722 if (!Printer) {
3723 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3724 OUR_HANDLE(handle)));
3725 goto done;
3728 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3731 * We are now using the change value, and
3732 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3733 * I don't have a global notification system, I'm sending back all the
3734 * informations even when _NOTHING_ has changed.
3737 /* We need to keep track of the change value to send back in
3738 RRPCN replies otherwise our updates are ignored. */
3740 Printer->notify.fnpcn = True;
3742 if (Printer->notify.client_connected) {
3743 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3744 Printer->notify.change = q_u->change;
3747 /* just ignore the SPOOL_NOTIFY_OPTION */
3749 switch (Printer->printer_type) {
3750 case PRINTER_HANDLE_IS_PRINTSERVER:
3751 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3752 break;
3754 case PRINTER_HANDLE_IS_PRINTER:
3755 result = printer_notify_info(p, handle, info, p->mem_ctx);
3756 break;
3759 Printer->notify.fnpcn = False;
3761 done:
3762 return result;
3765 /********************************************************************
3766 * construct_printer_info_0
3767 * fill a printer_info_0 struct
3768 ********************************************************************/
3770 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3772 pstring chaine;
3773 int count;
3774 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3775 counter_printer_0 *session_counter;
3776 uint32 global_counter;
3777 struct tm *t;
3778 time_t setuptime;
3779 print_status_struct status;
3781 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3782 return False;
3784 count = print_queue_length(snum, &status);
3786 /* check if we already have a counter for this printer */
3787 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3789 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3790 if (session_counter->snum == snum)
3791 break;
3794 /* it's the first time, add it to the list */
3795 if (session_counter==NULL) {
3796 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3797 free_a_printer(&ntprinter, 2);
3798 return False;
3800 ZERO_STRUCTP(session_counter);
3801 session_counter->snum=snum;
3802 session_counter->counter=0;
3803 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3806 /* increment it */
3807 session_counter->counter++;
3809 /* JFM:
3810 * the global_counter should be stored in a TDB as it's common to all the clients
3811 * and should be zeroed on samba startup
3813 global_counter=session_counter->counter;
3815 pstrcpy(chaine,ntprinter->info_2->printername);
3817 init_unistr(&printer->printername, chaine);
3819 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3820 init_unistr(&printer->servername, chaine);
3822 printer->cjobs = count;
3823 printer->total_jobs = 0;
3824 printer->total_bytes = 0;
3826 setuptime = (time_t)ntprinter->info_2->setuptime;
3827 t=gmtime(&setuptime);
3829 printer->year = t->tm_year+1900;
3830 printer->month = t->tm_mon+1;
3831 printer->dayofweek = t->tm_wday;
3832 printer->day = t->tm_mday;
3833 printer->hour = t->tm_hour;
3834 printer->minute = t->tm_min;
3835 printer->second = t->tm_sec;
3836 printer->milliseconds = 0;
3838 printer->global_counter = global_counter;
3839 printer->total_pages = 0;
3840 #ifdef HAVE_ADS
3841 printer->major_version = 0x0005; /* NT 5 */
3842 printer->build_version = 0x0893; /* build 2195 */
3843 #else
3844 printer->major_version = 0x0004; /* NT 4 */
3845 printer->build_version = 0x0565; /* build 1381 */
3846 #endif
3847 printer->unknown7 = 0x1;
3848 printer->unknown8 = 0x0;
3849 printer->unknown9 = 0x0;
3850 printer->session_counter = session_counter->counter;
3851 printer->unknown11 = 0x0;
3852 printer->printer_errors = 0x0; /* number of print failure */
3853 printer->unknown13 = 0x0;
3854 printer->unknown14 = 0x1;
3855 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3856 printer->unknown16 = 0x0;
3857 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3858 printer->unknown18 = 0x0;
3859 printer->status = nt_printq_status(status.status);
3860 printer->unknown20 = 0x0;
3861 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3862 printer->unknown22 = 0x0;
3863 printer->unknown23 = 0x6; /* 6 ???*/
3864 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3865 printer->unknown25 = 0;
3866 printer->unknown26 = 0;
3867 printer->unknown27 = 0;
3868 printer->unknown28 = 0;
3869 printer->unknown29 = 0;
3871 free_a_printer(&ntprinter,2);
3872 return (True);
3875 /********************************************************************
3876 * construct_printer_info_1
3877 * fill a printer_info_1 struct
3878 ********************************************************************/
3879 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3881 pstring chaine;
3882 pstring chaine2;
3883 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3885 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3886 return False;
3888 printer->flags=flags;
3890 if (*ntprinter->info_2->comment == '\0') {
3891 init_unistr(&printer->comment, lp_comment(snum));
3892 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3893 ntprinter->info_2->drivername, lp_comment(snum));
3895 else {
3896 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3897 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3898 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3901 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3903 init_unistr(&printer->description, chaine);
3904 init_unistr(&printer->name, chaine2);
3906 free_a_printer(&ntprinter,2);
3908 return True;
3911 /****************************************************************************
3912 Free a DEVMODE struct.
3913 ****************************************************************************/
3915 static void free_dev_mode(DEVICEMODE *dev)
3917 if (dev == NULL)
3918 return;
3920 SAFE_FREE(dev->private);
3921 SAFE_FREE(dev);
3925 /****************************************************************************
3926 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3927 should be valid upon entry
3928 ****************************************************************************/
3930 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
3932 if ( !devmode || !ntdevmode )
3933 return False;
3935 init_unistr(&devmode->devicename, ntdevmode->devicename);
3937 init_unistr(&devmode->formname, ntdevmode->formname);
3939 devmode->specversion = ntdevmode->specversion;
3940 devmode->driverversion = ntdevmode->driverversion;
3941 devmode->size = ntdevmode->size;
3942 devmode->driverextra = ntdevmode->driverextra;
3943 devmode->fields = ntdevmode->fields;
3945 devmode->orientation = ntdevmode->orientation;
3946 devmode->papersize = ntdevmode->papersize;
3947 devmode->paperlength = ntdevmode->paperlength;
3948 devmode->paperwidth = ntdevmode->paperwidth;
3949 devmode->scale = ntdevmode->scale;
3950 devmode->copies = ntdevmode->copies;
3951 devmode->defaultsource = ntdevmode->defaultsource;
3952 devmode->printquality = ntdevmode->printquality;
3953 devmode->color = ntdevmode->color;
3954 devmode->duplex = ntdevmode->duplex;
3955 devmode->yresolution = ntdevmode->yresolution;
3956 devmode->ttoption = ntdevmode->ttoption;
3957 devmode->collate = ntdevmode->collate;
3958 devmode->icmmethod = ntdevmode->icmmethod;
3959 devmode->icmintent = ntdevmode->icmintent;
3960 devmode->mediatype = ntdevmode->mediatype;
3961 devmode->dithertype = ntdevmode->dithertype;
3963 if (ntdevmode->private != NULL) {
3964 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3965 return False;
3968 return True;
3971 /****************************************************************************
3972 Create a DEVMODE struct. Returns malloced memory.
3973 ****************************************************************************/
3975 DEVICEMODE *construct_dev_mode(int snum)
3977 NT_PRINTER_INFO_LEVEL *printer = NULL;
3978 DEVICEMODE *devmode = NULL;
3980 DEBUG(7,("construct_dev_mode\n"));
3982 DEBUGADD(8,("getting printer characteristics\n"));
3984 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
3985 return NULL;
3987 if ( !printer->info_2->devmode ) {
3988 DEBUG(5, ("BONG! There was no device mode!\n"));
3989 goto done;
3992 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3993 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3994 goto done;
3997 ZERO_STRUCTP(devmode);
3999 DEBUGADD(8,("loading DEVICEMODE\n"));
4001 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4002 free_dev_mode( devmode );
4003 devmode = NULL;
4006 done:
4007 free_a_printer(&printer,2);
4009 return devmode;
4012 /********************************************************************
4013 * construct_printer_info_2
4014 * fill a printer_info_2 struct
4015 ********************************************************************/
4017 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4019 int count;
4020 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4022 print_status_struct status;
4024 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4025 return False;
4027 count = print_queue_length(snum, &status);
4029 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4030 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4031 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4032 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4033 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4035 if (*ntprinter->info_2->comment == '\0')
4036 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4037 else
4038 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4040 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4041 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4042 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4043 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4044 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4046 printer->attributes = ntprinter->info_2->attributes;
4048 printer->priority = ntprinter->info_2->priority; /* priority */
4049 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4050 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4051 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4052 printer->status = nt_printq_status(status.status); /* status */
4053 printer->cjobs = count; /* jobs */
4054 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4056 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4057 DEBUG(8, ("Returning NULL Devicemode!\n"));
4060 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4061 /* steal the printer info sec_desc structure. [badly done]. */
4062 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4063 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4064 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4065 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4067 else {
4068 printer->secdesc = NULL;
4071 free_a_printer(&ntprinter, 2);
4072 return True;
4075 /********************************************************************
4076 * construct_printer_info_3
4077 * fill a printer_info_3 struct
4078 ********************************************************************/
4080 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4082 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4083 PRINTER_INFO_3 *printer = NULL;
4085 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4086 return False;
4088 *pp_printer = NULL;
4089 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4090 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4091 return False;
4094 ZERO_STRUCTP(printer);
4096 printer->flags = 4; /* These are the components of the SD we are returning. */
4097 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4098 /* steal the printer info sec_desc structure. [badly done]. */
4099 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4101 #if 0
4103 * Set the flags for the components we are returning.
4106 if (printer->secdesc->owner_sid)
4107 printer->flags |= OWNER_SECURITY_INFORMATION;
4109 if (printer->secdesc->grp_sid)
4110 printer->flags |= GROUP_SECURITY_INFORMATION;
4112 if (printer->secdesc->dacl)
4113 printer->flags |= DACL_SECURITY_INFORMATION;
4115 if (printer->secdesc->sacl)
4116 printer->flags |= SACL_SECURITY_INFORMATION;
4117 #endif
4119 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4120 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4121 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4124 free_a_printer(&ntprinter, 2);
4126 *pp_printer = printer;
4127 return True;
4130 /********************************************************************
4131 * construct_printer_info_4
4132 * fill a printer_info_4 struct
4133 ********************************************************************/
4135 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4137 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4139 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4140 return False;
4142 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4143 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4144 printer->attributes = ntprinter->info_2->attributes;
4146 free_a_printer(&ntprinter, 2);
4147 return True;
4150 /********************************************************************
4151 * construct_printer_info_5
4152 * fill a printer_info_5 struct
4153 ********************************************************************/
4155 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4157 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4159 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4160 return False;
4162 init_unistr(&printer->printername, ntprinter->info_2->printername);
4163 init_unistr(&printer->portname, ntprinter->info_2->portname);
4164 printer->attributes = ntprinter->info_2->attributes;
4166 /* these two are not used by NT+ according to MSDN */
4168 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4169 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4171 free_a_printer(&ntprinter, 2);
4173 return True;
4176 /********************************************************************
4177 * construct_printer_info_7
4178 * fill a printer_info_7 struct
4179 ********************************************************************/
4181 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4183 char *guid_str = NULL;
4184 GUID guid;
4185 TALLOC_CTX *mem_ctx;
4187 mem_ctx = talloc_init("dump_guid");
4188 if (!mem_ctx) return;
4190 if (is_printer_published(print_hnd, snum, &guid)) {
4191 asprintf(&guid_str, "{%s}", uuid_string(mem_ctx, guid));
4192 strupper(guid_str);
4193 init_unistr(&printer->guid, guid_str);
4194 printer->action = SPOOL_DS_PUBLISH;
4195 } else {
4196 init_unistr(&printer->guid, "");
4197 printer->action = SPOOL_DS_UNPUBLISH;
4199 talloc_destroy(mem_ctx);
4201 return True;
4204 /********************************************************************
4205 Spoolss_enumprinters.
4206 ********************************************************************/
4208 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4210 int snum;
4211 int i;
4212 int n_services=lp_numservices();
4213 PRINTER_INFO_1 *tp, *printers=NULL;
4214 PRINTER_INFO_1 current_prt;
4216 DEBUG(4,("enum_all_printers_info_1\n"));
4218 for (snum=0; snum<n_services; snum++) {
4219 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4220 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4222 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4223 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4224 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4225 SAFE_FREE(printers);
4226 *returned=0;
4227 return WERR_NOMEM;
4229 else printers = tp;
4230 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4232 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4233 (*returned)++;
4238 /* check the required size. */
4239 for (i=0; i<*returned; i++)
4240 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4242 if (!alloc_buffer_size(buffer, *needed))
4243 return WERR_INSUFFICIENT_BUFFER;
4245 /* fill the buffer with the structures */
4246 for (i=0; i<*returned; i++)
4247 smb_io_printer_info_1("", buffer, &printers[i], 0);
4249 /* clear memory */
4250 SAFE_FREE(printers);
4252 if (*needed > offered) {
4253 *returned=0;
4254 return WERR_INSUFFICIENT_BUFFER;
4256 else
4257 return WERR_OK;
4260 /********************************************************************
4261 enum_all_printers_info_1_local.
4262 *********************************************************************/
4264 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4266 DEBUG(4,("enum_all_printers_info_1_local\n"));
4268 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4271 /********************************************************************
4272 enum_all_printers_info_1_name.
4273 *********************************************************************/
4275 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4277 char *s = name;
4279 DEBUG(4,("enum_all_printers_info_1_name\n"));
4281 if ((name[0] == '\\') && (name[1] == '\\'))
4282 s = name + 2;
4284 if (is_myname_or_ipaddr(s)) {
4285 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4287 else
4288 return WERR_INVALID_NAME;
4291 /********************************************************************
4292 enum_all_printers_info_1_remote.
4293 *********************************************************************/
4295 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4297 PRINTER_INFO_1 *printer;
4298 fstring printername;
4299 fstring desc;
4300 fstring comment;
4301 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4303 /* JFM: currently it's more a place holder than anything else.
4304 * In the spooler world there is a notion of server registration.
4305 * the print servers are registring (sp ?) on the PDC (in the same domain)
4307 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4310 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4311 return WERR_NOMEM;
4313 *returned=1;
4315 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4316 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4317 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4319 init_unistr(&printer->description, desc);
4320 init_unistr(&printer->name, printername);
4321 init_unistr(&printer->comment, comment);
4322 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4324 /* check the required size. */
4325 *needed += spoolss_size_printer_info_1(printer);
4327 if (!alloc_buffer_size(buffer, *needed)) {
4328 SAFE_FREE(printer);
4329 return WERR_INSUFFICIENT_BUFFER;
4332 /* fill the buffer with the structures */
4333 smb_io_printer_info_1("", buffer, printer, 0);
4335 /* clear memory */
4336 SAFE_FREE(printer);
4338 if (*needed > offered) {
4339 *returned=0;
4340 return WERR_INSUFFICIENT_BUFFER;
4342 else
4343 return WERR_OK;
4346 /********************************************************************
4347 enum_all_printers_info_1_network.
4348 *********************************************************************/
4350 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4352 char *s = name;
4354 DEBUG(4,("enum_all_printers_info_1_network\n"));
4356 /* If we respond to a enum_printers level 1 on our name with flags
4357 set to PRINTER_ENUM_REMOTE with a list of printers then these
4358 printers incorrectly appear in the APW browse list.
4359 Specifically the printers for the server appear at the workgroup
4360 level where all the other servers in the domain are
4361 listed. Windows responds to this call with a
4362 WERR_CAN_NOT_COMPLETE so we should do the same. */
4364 if (name[0] == '\\' && name[1] == '\\')
4365 s = name + 2;
4367 if (is_myname_or_ipaddr(s))
4368 return WERR_CAN_NOT_COMPLETE;
4370 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4373 /********************************************************************
4374 * api_spoolss_enumprinters
4376 * called from api_spoolss_enumprinters (see this to understand)
4377 ********************************************************************/
4379 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4381 int snum;
4382 int i;
4383 int n_services=lp_numservices();
4384 PRINTER_INFO_2 *tp, *printers=NULL;
4385 PRINTER_INFO_2 current_prt;
4387 for (snum=0; snum<n_services; snum++) {
4388 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4389 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4391 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4392 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4393 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4394 SAFE_FREE(printers);
4395 *returned = 0;
4396 return WERR_NOMEM;
4398 else printers = tp;
4399 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4400 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4401 (*returned)++;
4406 /* check the required size. */
4407 for (i=0; i<*returned; i++)
4408 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4410 if (!alloc_buffer_size(buffer, *needed)) {
4411 for (i=0; i<*returned; i++) {
4412 free_devmode(printers[i].devmode);
4414 SAFE_FREE(printers);
4415 return WERR_INSUFFICIENT_BUFFER;
4418 /* fill the buffer with the structures */
4419 for (i=0; i<*returned; i++)
4420 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4422 /* clear memory */
4423 for (i=0; i<*returned; i++) {
4424 free_devmode(printers[i].devmode);
4426 SAFE_FREE(printers);
4428 if (*needed > offered) {
4429 *returned=0;
4430 return WERR_INSUFFICIENT_BUFFER;
4432 else
4433 return WERR_OK;
4436 /********************************************************************
4437 * handle enumeration of printers at level 1
4438 ********************************************************************/
4440 static WERROR enumprinters_level1( uint32 flags, fstring name,
4441 NEW_BUFFER *buffer, uint32 offered,
4442 uint32 *needed, uint32 *returned)
4444 /* Not all the flags are equals */
4446 if (flags & PRINTER_ENUM_LOCAL)
4447 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4449 if (flags & PRINTER_ENUM_NAME)
4450 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4452 if (flags & PRINTER_ENUM_REMOTE)
4453 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4455 if (flags & PRINTER_ENUM_NETWORK)
4456 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4458 return WERR_OK; /* NT4sp5 does that */
4461 /********************************************************************
4462 * handle enumeration of printers at level 2
4463 ********************************************************************/
4465 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4466 NEW_BUFFER *buffer, uint32 offered,
4467 uint32 *needed, uint32 *returned)
4469 char *s = servername;
4471 if (flags & PRINTER_ENUM_LOCAL) {
4472 return enum_all_printers_info_2(buffer, offered, needed, returned);
4475 if (flags & PRINTER_ENUM_NAME) {
4476 if ((servername[0] == '\\') && (servername[1] == '\\'))
4477 s = servername + 2;
4478 if (is_myname_or_ipaddr(s))
4479 return enum_all_printers_info_2(buffer, offered, needed, returned);
4480 else
4481 return WERR_INVALID_NAME;
4484 if (flags & PRINTER_ENUM_REMOTE)
4485 return WERR_UNKNOWN_LEVEL;
4487 return WERR_OK;
4490 /********************************************************************
4491 * handle enumeration of printers at level 5
4492 ********************************************************************/
4494 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4495 NEW_BUFFER *buffer, uint32 offered,
4496 uint32 *needed, uint32 *returned)
4498 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4499 return WERR_OK;
4502 /********************************************************************
4503 * api_spoolss_enumprinters
4505 * called from api_spoolss_enumprinters (see this to understand)
4506 ********************************************************************/
4508 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4510 uint32 flags = q_u->flags;
4511 UNISTR2 *servername = &q_u->servername;
4512 uint32 level = q_u->level;
4513 NEW_BUFFER *buffer = NULL;
4514 uint32 offered = q_u->offered;
4515 uint32 *needed = &r_u->needed;
4516 uint32 *returned = &r_u->returned;
4518 fstring name;
4520 /* that's an [in out] buffer */
4521 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4522 buffer = r_u->buffer;
4524 DEBUG(4,("_spoolss_enumprinters\n"));
4526 *needed=0;
4527 *returned=0;
4530 * Level 1:
4531 * flags==PRINTER_ENUM_NAME
4532 * if name=="" then enumerates all printers
4533 * if name!="" then enumerate the printer
4534 * flags==PRINTER_ENUM_REMOTE
4535 * name is NULL, enumerate printers
4536 * Level 2: name!="" enumerates printers, name can't be NULL
4537 * Level 3: doesn't exist
4538 * Level 4: does a local registry lookup
4539 * Level 5: same as Level 2
4542 unistr2_to_ascii(name, servername, sizeof(name)-1);
4543 strupper(name);
4545 switch (level) {
4546 case 1:
4547 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4548 case 2:
4549 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4550 case 5:
4551 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4552 case 3:
4553 case 4:
4554 break;
4556 return WERR_UNKNOWN_LEVEL;
4559 /****************************************************************************
4560 ****************************************************************************/
4562 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4564 PRINTER_INFO_0 *printer=NULL;
4566 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4567 return WERR_NOMEM;
4569 construct_printer_info_0(print_hnd, printer, snum);
4571 /* check the required size. */
4572 *needed += spoolss_size_printer_info_0(printer);
4574 if (!alloc_buffer_size(buffer, *needed)) {
4575 SAFE_FREE(printer);
4576 return WERR_INSUFFICIENT_BUFFER;
4579 /* fill the buffer with the structures */
4580 smb_io_printer_info_0("", buffer, printer, 0);
4582 /* clear memory */
4583 SAFE_FREE(printer);
4585 if (*needed > offered) {
4586 return WERR_INSUFFICIENT_BUFFER;
4589 return WERR_OK;
4592 /****************************************************************************
4593 ****************************************************************************/
4595 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4597 PRINTER_INFO_1 *printer=NULL;
4599 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4600 return WERR_NOMEM;
4602 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4604 /* check the required size. */
4605 *needed += spoolss_size_printer_info_1(printer);
4607 if (!alloc_buffer_size(buffer, *needed)) {
4608 SAFE_FREE(printer);
4609 return WERR_INSUFFICIENT_BUFFER;
4612 /* fill the buffer with the structures */
4613 smb_io_printer_info_1("", buffer, printer, 0);
4615 /* clear memory */
4616 SAFE_FREE(printer);
4618 if (*needed > offered) {
4619 return WERR_INSUFFICIENT_BUFFER;
4622 return WERR_OK;
4625 /****************************************************************************
4626 ****************************************************************************/
4628 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4630 PRINTER_INFO_2 *printer=NULL;
4632 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4633 return WERR_NOMEM;
4635 construct_printer_info_2(print_hnd, printer, snum);
4637 /* check the required size. */
4638 *needed += spoolss_size_printer_info_2(printer);
4640 if (!alloc_buffer_size(buffer, *needed)) {
4641 free_printer_info_2(printer);
4642 return WERR_INSUFFICIENT_BUFFER;
4645 /* fill the buffer with the structures */
4646 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4647 free_printer_info_2(printer);
4648 return WERR_NOMEM;
4651 /* clear memory */
4652 free_printer_info_2(printer);
4654 if (*needed > offered) {
4655 return WERR_INSUFFICIENT_BUFFER;
4658 return WERR_OK;
4661 /****************************************************************************
4662 ****************************************************************************/
4664 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4666 PRINTER_INFO_3 *printer=NULL;
4668 if (!construct_printer_info_3(print_hnd, &printer, snum))
4669 return WERR_NOMEM;
4671 /* check the required size. */
4672 *needed += spoolss_size_printer_info_3(printer);
4674 if (!alloc_buffer_size(buffer, *needed)) {
4675 free_printer_info_3(printer);
4676 return WERR_INSUFFICIENT_BUFFER;
4679 /* fill the buffer with the structures */
4680 smb_io_printer_info_3("", buffer, printer, 0);
4682 /* clear memory */
4683 free_printer_info_3(printer);
4685 if (*needed > offered) {
4686 return WERR_INSUFFICIENT_BUFFER;
4689 return WERR_OK;
4692 /****************************************************************************
4693 ****************************************************************************/
4695 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4697 PRINTER_INFO_4 *printer=NULL;
4699 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4700 return WERR_NOMEM;
4702 if (!construct_printer_info_4(print_hnd, printer, snum))
4703 return WERR_NOMEM;
4705 /* check the required size. */
4706 *needed += spoolss_size_printer_info_4(printer);
4708 if (!alloc_buffer_size(buffer, *needed)) {
4709 free_printer_info_4(printer);
4710 return WERR_INSUFFICIENT_BUFFER;
4713 /* fill the buffer with the structures */
4714 smb_io_printer_info_4("", buffer, printer, 0);
4716 /* clear memory */
4717 free_printer_info_4(printer);
4719 if (*needed > offered) {
4720 return WERR_INSUFFICIENT_BUFFER;
4723 return WERR_OK;
4726 /****************************************************************************
4727 ****************************************************************************/
4729 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4731 PRINTER_INFO_5 *printer=NULL;
4733 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4734 return WERR_NOMEM;
4736 if (!construct_printer_info_5(print_hnd, printer, snum))
4737 return WERR_NOMEM;
4739 /* check the required size. */
4740 *needed += spoolss_size_printer_info_5(printer);
4742 if (!alloc_buffer_size(buffer, *needed)) {
4743 free_printer_info_5(printer);
4744 return WERR_INSUFFICIENT_BUFFER;
4747 /* fill the buffer with the structures */
4748 smb_io_printer_info_5("", buffer, printer, 0);
4750 /* clear memory */
4751 free_printer_info_5(printer);
4753 if (*needed > offered) {
4754 return WERR_INSUFFICIENT_BUFFER;
4757 return WERR_OK;
4760 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4762 PRINTER_INFO_7 *printer=NULL;
4764 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4765 return WERR_NOMEM;
4767 if (!construct_printer_info_7(print_hnd, printer, snum))
4768 return WERR_NOMEM;
4770 /* check the required size. */
4771 *needed += spoolss_size_printer_info_7(printer);
4773 if (!alloc_buffer_size(buffer, *needed)) {
4774 free_printer_info_7(printer);
4775 return WERR_INSUFFICIENT_BUFFER;
4778 /* fill the buffer with the structures */
4779 smb_io_printer_info_7("", buffer, printer, 0);
4781 /* clear memory */
4782 free_printer_info_7(printer);
4784 if (*needed > offered) {
4785 return WERR_INSUFFICIENT_BUFFER;
4788 return WERR_OK;
4791 /****************************************************************************
4792 ****************************************************************************/
4794 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4796 POLICY_HND *handle = &q_u->handle;
4797 uint32 level = q_u->level;
4798 NEW_BUFFER *buffer = NULL;
4799 uint32 offered = q_u->offered;
4800 uint32 *needed = &r_u->needed;
4801 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4803 int snum;
4805 /* that's an [in out] buffer */
4806 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4807 buffer = r_u->buffer;
4809 *needed=0;
4811 if (!get_printer_snum(p, handle, &snum))
4812 return WERR_BADFID;
4814 switch (level) {
4815 case 0:
4816 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4817 case 1:
4818 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4819 case 2:
4820 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4821 case 3:
4822 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4823 case 4:
4824 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4825 case 5:
4826 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4827 case 7:
4828 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4830 return WERR_UNKNOWN_LEVEL;
4833 /********************************************************************
4834 * fill a DRIVER_INFO_1 struct
4835 ********************************************************************/
4837 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4839 init_unistr( &info->name, driver.info_3->name);
4842 /********************************************************************
4843 * construct_printer_driver_info_1
4844 ********************************************************************/
4846 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4848 NT_PRINTER_INFO_LEVEL *printer = NULL;
4849 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4851 ZERO_STRUCT(driver);
4853 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4854 return WERR_INVALID_PRINTER_NAME;
4856 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4857 return WERR_UNKNOWN_PRINTER_DRIVER;
4859 fill_printer_driver_info_1(info, driver, servername, architecture);
4861 free_a_printer(&printer,2);
4863 return WERR_OK;
4866 /********************************************************************
4867 * construct_printer_driver_info_2
4868 * fill a printer_info_2 struct
4869 ********************************************************************/
4871 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4873 pstring temp;
4875 info->version=driver.info_3->cversion;
4877 init_unistr( &info->name, driver.info_3->name );
4878 init_unistr( &info->architecture, driver.info_3->environment );
4881 if (strlen(driver.info_3->driverpath)) {
4882 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4883 init_unistr( &info->driverpath, temp );
4884 } else
4885 init_unistr( &info->driverpath, "" );
4887 if (strlen(driver.info_3->datafile)) {
4888 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4889 init_unistr( &info->datafile, temp );
4890 } else
4891 init_unistr( &info->datafile, "" );
4893 if (strlen(driver.info_3->configfile)) {
4894 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4895 init_unistr( &info->configfile, temp );
4896 } else
4897 init_unistr( &info->configfile, "" );
4900 /********************************************************************
4901 * construct_printer_driver_info_2
4902 * fill a printer_info_2 struct
4903 ********************************************************************/
4905 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4907 NT_PRINTER_INFO_LEVEL *printer = NULL;
4908 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4910 ZERO_STRUCT(printer);
4911 ZERO_STRUCT(driver);
4913 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4914 return WERR_INVALID_PRINTER_NAME;
4916 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4917 return WERR_UNKNOWN_PRINTER_DRIVER;
4919 fill_printer_driver_info_2(info, driver, servername);
4921 free_a_printer(&printer,2);
4923 return WERR_OK;
4926 /********************************************************************
4927 * copy a strings array and convert to UNICODE
4929 * convert an array of ascii string to a UNICODE string
4930 ********************************************************************/
4932 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
4934 int i=0;
4935 int j=0;
4936 const char *v;
4937 pstring line;
4938 uint16 *tuary;
4940 DEBUG(6,("init_unistr_array\n"));
4941 *uni_array=NULL;
4943 while (True)
4945 if ( !char_array )
4946 v = "";
4947 else
4949 v = char_array[i];
4950 if (!v)
4951 v = ""; /* hack to handle null lists */
4954 /* hack to allow this to be used in places other than when generating
4955 the list of dependent files */
4957 if ( servername )
4958 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4959 else
4960 pstrcpy( line, v );
4962 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4964 /* add one extra unit16 for the second terminating NULL */
4966 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4967 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4968 return 0;
4969 } else
4970 *uni_array = tuary;
4972 if ( !strlen(v) )
4973 break;
4975 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4976 i++;
4979 if (*uni_array) {
4980 /* special case for ""; we need to add both NULL's here */
4981 if (!j)
4982 (*uni_array)[j++]=0x0000;
4983 (*uni_array)[j]=0x0000;
4986 DEBUGADD(6,("last one:done\n"));
4988 /* return size of array in uint16's */
4990 return j+1;
4993 /********************************************************************
4994 * construct_printer_info_3
4995 * fill a printer_info_3 struct
4996 ********************************************************************/
4998 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5000 pstring temp;
5002 ZERO_STRUCTP(info);
5004 info->version=driver.info_3->cversion;
5006 init_unistr( &info->name, driver.info_3->name );
5007 init_unistr( &info->architecture, driver.info_3->environment );
5009 if (strlen(driver.info_3->driverpath)) {
5010 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5011 init_unistr( &info->driverpath, temp );
5012 } else
5013 init_unistr( &info->driverpath, "" );
5015 if (strlen(driver.info_3->datafile)) {
5016 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5017 init_unistr( &info->datafile, temp );
5018 } else
5019 init_unistr( &info->datafile, "" );
5021 if (strlen(driver.info_3->configfile)) {
5022 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5023 init_unistr( &info->configfile, temp );
5024 } else
5025 init_unistr( &info->configfile, "" );
5027 if (strlen(driver.info_3->helpfile)) {
5028 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5029 init_unistr( &info->helpfile, temp );
5030 } else
5031 init_unistr( &info->helpfile, "" );
5033 init_unistr( &info->monitorname, driver.info_3->monitorname );
5034 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5036 info->dependentfiles=NULL;
5037 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5040 /********************************************************************
5041 * construct_printer_info_3
5042 * fill a printer_info_3 struct
5043 ********************************************************************/
5045 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5047 NT_PRINTER_INFO_LEVEL *printer = NULL;
5048 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5049 WERROR status;
5050 ZERO_STRUCT(driver);
5052 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5053 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5054 if (!W_ERROR_IS_OK(status))
5055 return WERR_INVALID_PRINTER_NAME;
5057 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5058 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5060 #if 0 /* JERRY */
5063 * I put this code in during testing. Helpful when commenting out the
5064 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5065 * as win2k always queries the driver using an infor level of 6.
5066 * I've left it in (but ifdef'd out) because I'll probably
5067 * use it in experimentation again in the future. --jerry 22/01/2002
5070 if (!W_ERROR_IS_OK(status)) {
5072 * Is this a W2k client ?
5074 if (version == 3) {
5075 /* Yes - try again with a WinNT driver. */
5076 version = 2;
5077 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5078 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5080 #endif
5082 if (!W_ERROR_IS_OK(status)) {
5083 free_a_printer(&printer,2);
5084 return WERR_UNKNOWN_PRINTER_DRIVER;
5087 #if 0 /* JERRY */
5089 #endif
5092 fill_printer_driver_info_3(info, driver, servername);
5094 free_a_printer(&printer,2);
5096 return WERR_OK;
5099 /********************************************************************
5100 * construct_printer_info_6
5101 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5102 ********************************************************************/
5104 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5106 pstring temp;
5107 fstring nullstr;
5109 ZERO_STRUCTP(info);
5110 memset(&nullstr, '\0', sizeof(fstring));
5112 info->version=driver.info_3->cversion;
5114 init_unistr( &info->name, driver.info_3->name );
5115 init_unistr( &info->architecture, driver.info_3->environment );
5117 if (strlen(driver.info_3->driverpath)) {
5118 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5119 init_unistr( &info->driverpath, temp );
5120 } else
5121 init_unistr( &info->driverpath, "" );
5123 if (strlen(driver.info_3->datafile)) {
5124 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5125 init_unistr( &info->datafile, temp );
5126 } else
5127 init_unistr( &info->datafile, "" );
5129 if (strlen(driver.info_3->configfile)) {
5130 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5131 init_unistr( &info->configfile, temp );
5132 } else
5133 init_unistr( &info->configfile, "" );
5135 if (strlen(driver.info_3->helpfile)) {
5136 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5137 init_unistr( &info->helpfile, temp );
5138 } else
5139 init_unistr( &info->helpfile, "" );
5141 init_unistr( &info->monitorname, driver.info_3->monitorname );
5142 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5144 info->dependentfiles = NULL;
5145 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5147 info->previousdrivernames=NULL;
5148 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5150 info->driver_date.low=0;
5151 info->driver_date.high=0;
5153 info->padding=0;
5154 info->driver_version_low=0;
5155 info->driver_version_high=0;
5157 init_unistr( &info->mfgname, "");
5158 init_unistr( &info->oem_url, "");
5159 init_unistr( &info->hardware_id, "");
5160 init_unistr( &info->provider, "");
5163 /********************************************************************
5164 * construct_printer_info_6
5165 * fill a printer_info_6 struct
5166 ********************************************************************/
5168 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5169 fstring servername, fstring architecture, uint32 version)
5171 NT_PRINTER_INFO_LEVEL *printer = NULL;
5172 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5173 WERROR status;
5175 ZERO_STRUCT(driver);
5177 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5179 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5181 if (!W_ERROR_IS_OK(status))
5182 return WERR_INVALID_PRINTER_NAME;
5184 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5186 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5188 if (!W_ERROR_IS_OK(status))
5191 * Is this a W2k client ?
5194 if (version < 3) {
5195 free_a_printer(&printer,2);
5196 return WERR_UNKNOWN_PRINTER_DRIVER;
5199 /* Yes - try again with a WinNT driver. */
5200 version = 2;
5201 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5202 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5203 if (!W_ERROR_IS_OK(status)) {
5204 free_a_printer(&printer,2);
5205 return WERR_UNKNOWN_PRINTER_DRIVER;
5209 fill_printer_driver_info_6(info, driver, servername);
5211 free_a_printer(&printer,2);
5212 free_a_printer_driver(driver, 3);
5214 return WERR_OK;
5217 /****************************************************************************
5218 ****************************************************************************/
5220 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5222 SAFE_FREE(info->dependentfiles);
5225 /****************************************************************************
5226 ****************************************************************************/
5228 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5230 SAFE_FREE(info->dependentfiles);
5234 /****************************************************************************
5235 ****************************************************************************/
5237 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5239 DRIVER_INFO_1 *info=NULL;
5240 WERROR status;
5242 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5243 return WERR_NOMEM;
5245 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5246 if (!W_ERROR_IS_OK(status)) {
5247 SAFE_FREE(info);
5248 return status;
5251 /* check the required size. */
5252 *needed += spoolss_size_printer_driver_info_1(info);
5254 if (!alloc_buffer_size(buffer, *needed)) {
5255 SAFE_FREE(info);
5256 return WERR_INSUFFICIENT_BUFFER;
5259 /* fill the buffer with the structures */
5260 smb_io_printer_driver_info_1("", buffer, info, 0);
5262 /* clear memory */
5263 SAFE_FREE(info);
5265 if (*needed > offered)
5266 return WERR_INSUFFICIENT_BUFFER;
5268 return WERR_OK;
5271 /****************************************************************************
5272 ****************************************************************************/
5274 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5276 DRIVER_INFO_2 *info=NULL;
5277 WERROR status;
5279 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5280 return WERR_NOMEM;
5282 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5283 if (!W_ERROR_IS_OK(status)) {
5284 SAFE_FREE(info);
5285 return status;
5288 /* check the required size. */
5289 *needed += spoolss_size_printer_driver_info_2(info);
5291 if (!alloc_buffer_size(buffer, *needed)) {
5292 SAFE_FREE(info);
5293 return WERR_INSUFFICIENT_BUFFER;
5296 /* fill the buffer with the structures */
5297 smb_io_printer_driver_info_2("", buffer, info, 0);
5299 /* clear memory */
5300 SAFE_FREE(info);
5302 if (*needed > offered)
5303 return WERR_INSUFFICIENT_BUFFER;
5305 return WERR_OK;
5308 /****************************************************************************
5309 ****************************************************************************/
5311 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5313 DRIVER_INFO_3 info;
5314 WERROR status;
5316 ZERO_STRUCT(info);
5318 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5319 if (!W_ERROR_IS_OK(status)) {
5320 return status;
5323 /* check the required size. */
5324 *needed += spoolss_size_printer_driver_info_3(&info);
5326 if (!alloc_buffer_size(buffer, *needed)) {
5327 free_printer_driver_info_3(&info);
5328 return WERR_INSUFFICIENT_BUFFER;
5331 /* fill the buffer with the structures */
5332 smb_io_printer_driver_info_3("", buffer, &info, 0);
5334 free_printer_driver_info_3(&info);
5336 if (*needed > offered)
5337 return WERR_INSUFFICIENT_BUFFER;
5339 return WERR_OK;
5342 /****************************************************************************
5343 ****************************************************************************/
5345 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5347 DRIVER_INFO_6 info;
5348 WERROR status;
5350 ZERO_STRUCT(info);
5352 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5353 if (!W_ERROR_IS_OK(status)) {
5354 return status;
5357 /* check the required size. */
5358 *needed += spoolss_size_printer_driver_info_6(&info);
5360 if (!alloc_buffer_size(buffer, *needed)) {
5361 free_printer_driver_info_6(&info);
5362 return WERR_INSUFFICIENT_BUFFER;
5365 /* fill the buffer with the structures */
5366 smb_io_printer_driver_info_6("", buffer, &info, 0);
5368 free_printer_driver_info_6(&info);
5370 if (*needed > offered)
5371 return WERR_INSUFFICIENT_BUFFER;
5373 return WERR_OK;
5376 /****************************************************************************
5377 ****************************************************************************/
5379 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5381 POLICY_HND *handle = &q_u->handle;
5382 UNISTR2 *uni_arch = &q_u->architecture;
5383 uint32 level = q_u->level;
5384 uint32 clientmajorversion = q_u->clientmajorversion;
5385 NEW_BUFFER *buffer = NULL;
5386 uint32 offered = q_u->offered;
5387 uint32 *needed = &r_u->needed;
5388 uint32 *servermajorversion = &r_u->servermajorversion;
5389 uint32 *serverminorversion = &r_u->serverminorversion;
5391 fstring servername;
5392 fstring architecture;
5393 int snum;
5395 /* that's an [in out] buffer */
5396 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5397 buffer = r_u->buffer;
5399 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5401 *needed = 0;
5402 *servermajorversion = 0;
5403 *serverminorversion = 0;
5405 fstrcpy(servername, get_called_name());
5406 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5408 if (!get_printer_snum(p, handle, &snum))
5409 return WERR_BADFID;
5411 switch (level) {
5412 case 1:
5413 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5414 case 2:
5415 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5416 case 3:
5417 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5418 case 6:
5419 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5422 return WERR_UNKNOWN_LEVEL;
5425 /****************************************************************************
5426 ****************************************************************************/
5428 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5430 POLICY_HND *handle = &q_u->handle;
5432 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5434 if (!Printer) {
5435 DEBUG(3,("Error in startpageprinter printer handle\n"));
5436 return WERR_BADFID;
5439 Printer->page_started=True;
5440 return WERR_OK;
5443 /****************************************************************************
5444 ****************************************************************************/
5446 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5448 POLICY_HND *handle = &q_u->handle;
5449 int snum;
5451 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5453 if (!Printer) {
5454 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5455 return WERR_BADFID;
5458 if (!get_printer_snum(p, handle, &snum))
5459 return WERR_BADFID;
5461 Printer->page_started=False;
5462 print_job_endpage(snum, Printer->jobid);
5464 return WERR_OK;
5467 /********************************************************************
5468 * api_spoolss_getprinter
5469 * called from the spoolss dispatcher
5471 ********************************************************************/
5473 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5475 POLICY_HND *handle = &q_u->handle;
5476 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5477 uint32 *jobid = &r_u->jobid;
5479 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5480 int snum;
5481 pstring jobname;
5482 fstring datatype;
5483 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5484 struct current_user user;
5486 if (!Printer) {
5487 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5488 return WERR_BADFID;
5491 get_current_user(&user, p);
5494 * a nice thing with NT is it doesn't listen to what you tell it.
5495 * when asked to send _only_ RAW datas, it tries to send datas
5496 * in EMF format.
5498 * So I add checks like in NT Server ...
5501 if (info_1->p_datatype != 0) {
5502 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5503 if (strcmp(datatype, "RAW") != 0) {
5504 (*jobid)=0;
5505 return WERR_INVALID_DATATYPE;
5509 /* get the share number of the printer */
5510 if (!get_printer_snum(p, handle, &snum)) {
5511 return WERR_BADFID;
5514 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5516 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5518 /* An error occured in print_job_start() so return an appropriate
5519 NT error code. */
5521 if (Printer->jobid == -1) {
5522 return map_werror_from_unix(errno);
5525 Printer->document_started=True;
5526 (*jobid) = Printer->jobid;
5528 return WERR_OK;
5531 /********************************************************************
5532 * api_spoolss_getprinter
5533 * called from the spoolss dispatcher
5535 ********************************************************************/
5537 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5539 POLICY_HND *handle = &q_u->handle;
5541 return _spoolss_enddocprinter_internal(p, handle);
5544 /****************************************************************************
5545 ****************************************************************************/
5547 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5549 POLICY_HND *handle = &q_u->handle;
5550 uint32 buffer_size = q_u->buffer_size;
5551 uint8 *buffer = q_u->buffer;
5552 uint32 *buffer_written = &q_u->buffer_size2;
5553 int snum;
5554 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5556 if (!Printer) {
5557 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5558 r_u->buffer_written = q_u->buffer_size2;
5559 return WERR_BADFID;
5562 if (!get_printer_snum(p, handle, &snum))
5563 return WERR_BADFID;
5565 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5566 if (*buffer_written == -1) {
5567 r_u->buffer_written = 0;
5568 if (errno == ENOSPC)
5569 return WERR_NO_SPOOL_SPACE;
5570 else
5571 return WERR_ACCESS_DENIED;
5574 r_u->buffer_written = q_u->buffer_size2;
5576 return WERR_OK;
5579 /********************************************************************
5580 * api_spoolss_getprinter
5581 * called from the spoolss dispatcher
5583 ********************************************************************/
5585 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5586 pipes_struct *p)
5588 struct current_user user;
5589 int snum;
5590 WERROR errcode = WERR_BADFUNC;
5591 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5593 get_current_user(&user, p);
5595 if (!Printer) {
5596 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5597 return WERR_BADFID;
5600 if (!get_printer_snum(p, handle, &snum))
5601 return WERR_BADFID;
5603 switch (command) {
5604 case PRINTER_CONTROL_PAUSE:
5605 if (print_queue_pause(&user, snum, &errcode)) {
5606 errcode = WERR_OK;
5608 break;
5609 case PRINTER_CONTROL_RESUME:
5610 case PRINTER_CONTROL_UNPAUSE:
5611 if (print_queue_resume(&user, snum, &errcode)) {
5612 errcode = WERR_OK;
5614 break;
5615 case PRINTER_CONTROL_PURGE:
5616 if (print_queue_purge(&user, snum, &errcode)) {
5617 errcode = WERR_OK;
5619 break;
5620 default:
5621 return WERR_UNKNOWN_LEVEL;
5624 return errcode;
5627 /********************************************************************
5628 * api_spoolss_abortprinter
5629 * From MSDN: "Deletes printer's spool file if printer is configured
5630 * for spooling"
5631 ********************************************************************/
5633 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5635 POLICY_HND *handle = &q_u->handle;
5636 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5637 int snum;
5638 struct current_user user;
5639 WERROR errcode = WERR_OK;
5641 if (!Printer) {
5642 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5643 return WERR_BADFID;
5646 if (!get_printer_snum(p, handle, &snum))
5647 return WERR_BADFID;
5649 get_current_user( &user, p );
5651 print_job_delete( &user, snum, Printer->jobid, &errcode );
5653 return errcode;
5656 /********************************************************************
5657 * called by spoolss_api_setprinter
5658 * when updating a printer description
5659 ********************************************************************/
5661 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5662 const SPOOL_PRINTER_INFO_LEVEL *info,
5663 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5665 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5666 struct current_user user;
5667 WERROR result;
5668 int snum;
5670 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5672 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5673 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5674 OUR_HANDLE(handle)));
5676 result = WERR_BADFID;
5677 goto done;
5680 /* NT seems to like setting the security descriptor even though
5681 nothing may have actually changed. This causes annoying
5682 dialog boxes when the user doesn't have permission to change
5683 the security descriptor. */
5685 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5687 if (DEBUGLEVEL >= 10) {
5688 SEC_ACL *the_acl;
5689 int i;
5691 the_acl = old_secdesc_ctr->sec->dacl;
5692 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5693 PRINTERNAME(snum), the_acl->num_aces));
5695 for (i = 0; i < the_acl->num_aces; i++) {
5696 fstring sid_str;
5698 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5700 DEBUG(10, ("%s 0x%08x\n", sid_str,
5701 the_acl->ace[i].info.mask));
5704 the_acl = secdesc_ctr->sec->dacl;
5706 if (the_acl) {
5707 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5708 PRINTERNAME(snum), the_acl->num_aces));
5710 for (i = 0; i < the_acl->num_aces; i++) {
5711 fstring sid_str;
5713 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5715 DEBUG(10, ("%s 0x%08x\n", sid_str,
5716 the_acl->ace[i].info.mask));
5718 } else {
5719 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5723 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5725 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5726 result = WERR_OK;
5727 goto done;
5730 /* Work out which user is performing the operation */
5732 get_current_user(&user, p);
5734 /* Check the user has permissions to change the security
5735 descriptor. By experimentation with two NT machines, the user
5736 requires Full Access to the printer to change security
5737 information. */
5739 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5740 result = WERR_ACCESS_DENIED;
5741 goto done;
5744 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5746 done:
5748 return result;
5751 /********************************************************************
5752 Do Samba sanity checks on a printer info struct.
5753 this has changed purpose: it now "canonicalises" printer
5754 info from a client rather than just checking it is correct
5755 ********************************************************************/
5757 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5759 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5760 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5762 /* we force some elements to "correct" values */
5763 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5764 fstrcpy(info->sharename, lp_servicename(snum));
5765 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5766 get_called_name(), info->sharename);
5767 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5770 return True;
5773 /****************************************************************************
5774 ****************************************************************************/
5776 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5778 extern userdom_struct current_user_info;
5779 char *cmd = lp_addprinter_cmd();
5780 char **qlines;
5781 pstring command;
5782 int numlines;
5783 int ret;
5784 int fd;
5785 fstring remote_machine = "%m";
5787 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5789 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5790 cmd, printer->info_2->printername, printer->info_2->sharename,
5791 printer->info_2->portname, printer->info_2->drivername,
5792 printer->info_2->location, printer->info_2->comment, remote_machine);
5794 DEBUG(10,("Running [%s]\n", command));
5795 ret = smbrun(command, &fd);
5796 DEBUGADD(10,("returned [%d]\n", ret));
5798 if ( ret != 0 ) {
5799 if (fd != -1)
5800 close(fd);
5801 return False;
5804 numlines = 0;
5805 /* Get lines and convert them back to dos-codepage */
5806 qlines = fd_lines_load(fd, &numlines);
5807 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5808 close(fd);
5810 if(numlines) {
5811 /* Set the portname to what the script says the portname should be. */
5812 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5813 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5815 /* Send SIGHUP to process group... is there a better way? */
5816 kill(0, SIGHUP);
5818 /* reload our services immediately */
5819 reload_services( False );
5822 file_lines_free(qlines);
5823 return True;
5826 /********************************************************************
5827 * Called by spoolss_api_setprinter
5828 * when updating a printer description.
5829 ********************************************************************/
5831 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5832 const SPOOL_PRINTER_INFO_LEVEL *info,
5833 DEVICEMODE *devmode)
5835 int snum;
5836 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5837 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5838 WERROR result;
5839 UNISTR2 buffer;
5840 fstring asc_buffer;
5842 DEBUG(8,("update_printer\n"));
5844 result = WERR_OK;
5846 if (!Printer) {
5847 result = WERR_BADFID;
5848 goto done;
5851 if (!get_printer_snum(p, handle, &snum)) {
5852 result = WERR_BADFID;
5853 goto done;
5856 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5857 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5858 result = WERR_BADFID;
5859 goto done;
5862 DEBUGADD(8,("Converting info_2 struct\n"));
5865 * convert_printer_info converts the incoming
5866 * info from the client and overwrites the info
5867 * just read from the tdb in the pointer 'printer'.
5870 if (!convert_printer_info(info, printer, level)) {
5871 result = WERR_NOMEM;
5872 goto done;
5875 if (devmode) {
5876 /* we have a valid devmode
5877 convert it and link it*/
5879 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5880 if (!convert_devicemode(printer->info_2->printername, devmode,
5881 &printer->info_2->devmode)) {
5882 result = WERR_NOMEM;
5883 goto done;
5887 /* Do sanity check on the requested changes for Samba */
5889 if (!check_printer_ok(printer->info_2, snum)) {
5890 result = WERR_INVALID_PARAM;
5891 goto done;
5894 /* Check calling user has permission to update printer description */
5896 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5897 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5898 result = WERR_ACCESS_DENIED;
5899 goto done;
5902 /* Call addprinter hook */
5903 /* Check changes to see if this is really needed */
5905 if ( *lp_addprinter_cmd()
5906 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5907 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5908 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5909 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5911 if ( !add_printer_hook(printer) ) {
5912 result = WERR_ACCESS_DENIED;
5913 goto done;
5917 * make sure we actually reload the services after
5918 * this as smb.conf could have a new section in it
5919 * .... shouldn't .... but could
5921 reload_services(False);
5925 * When a *new* driver is bound to a printer, the drivername is used to
5926 * lookup previously saved driver initialization info, which is then
5927 * bound to the printer, simulating what happens in the Windows arch.
5929 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5931 if (!set_driver_init(printer, 2))
5933 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5934 printer->info_2->drivername));
5937 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5938 printer->info_2->drivername));
5940 notify_printer_driver(snum, printer->info_2->drivername);
5944 * flag which changes actually occured. This is a small subset of
5945 * all the possible changes. We also have to update things in the
5946 * DsSpooler key.
5949 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5950 init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 );
5951 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5952 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5954 notify_printer_comment(snum, printer->info_2->comment);
5957 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5958 init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 );
5959 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5960 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5961 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5962 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5964 notify_printer_sharename(snum, printer->info_2->sharename);
5967 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5968 init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 );
5969 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5970 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5972 notify_printer_port(snum, printer->info_2->portname);
5975 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5976 init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 );
5977 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5978 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5980 notify_printer_location(snum, printer->info_2->location);
5983 /* here we need to update some more DsSpooler keys */
5984 /* uNCName, serverName, shortServerName */
5986 init_unistr2( &buffer, lp_netbios_name(), strlen(lp_netbios_name())+1 );
5987 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5988 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5989 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5990 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5992 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5993 lp_netbios_name(), printer->info_2->sharename );
5994 init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 );
5995 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5996 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5998 /* Update printer info */
5999 result = mod_a_printer(*printer, 2);
6001 done:
6002 free_a_printer(&printer, 2);
6003 free_a_printer(&old_printer, 2);
6006 return result;
6009 /****************************************************************************
6010 ****************************************************************************/
6011 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6012 const SPOOL_PRINTER_INFO_LEVEL *info)
6014 #ifdef HAVE_ADS
6015 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6016 int snum;
6017 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6018 WERROR result;
6020 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6022 result = WERR_OK;
6024 if (!Printer)
6025 return WERR_BADFID;
6027 if (!get_printer_snum(p, handle, &snum))
6028 return WERR_BADFID;
6030 nt_printer_publish(Printer, snum, info7->action);
6032 return WERR_OK;
6033 #else
6034 return WERR_UNKNOWN_LEVEL;
6035 #endif
6037 /****************************************************************************
6038 ****************************************************************************/
6040 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6042 POLICY_HND *handle = &q_u->handle;
6043 uint32 level = q_u->level;
6044 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6045 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6046 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6047 uint32 command = q_u->command;
6049 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6051 if (!Printer) {
6052 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6053 return WERR_BADFID;
6056 /* check the level */
6057 switch (level) {
6058 case 0:
6059 return control_printer(handle, command, p);
6060 case 2:
6061 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6062 case 3:
6063 return update_printer_sec(handle, level, info, p,
6064 secdesc_ctr);
6065 case 7:
6066 return publish_or_unpublish_printer(p, handle, info);
6067 default:
6068 return WERR_UNKNOWN_LEVEL;
6072 /****************************************************************************
6073 ****************************************************************************/
6075 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6077 POLICY_HND *handle = &q_u->handle;
6078 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6080 if (!Printer) {
6081 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6082 return WERR_BADFID;
6085 if (Printer->notify.client_connected==True) {
6086 int snum = -1;
6088 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6089 snum = -1;
6090 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6091 !get_printer_snum(p, handle, &snum) )
6092 return WERR_BADFID;
6094 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6097 Printer->notify.flags=0;
6098 Printer->notify.options=0;
6099 Printer->notify.localmachine[0]='\0';
6100 Printer->notify.printerlocal=0;
6101 if (Printer->notify.option)
6102 free_spool_notify_option(&Printer->notify.option);
6103 Printer->notify.client_connected=False;
6105 return WERR_OK;
6108 /****************************************************************************
6109 ****************************************************************************/
6111 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6113 /* that's an [in out] buffer (despite appearences to the contrary) */
6114 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6116 r_u->needed = 0;
6117 return WERR_INVALID_PARAM; /* this is what a NT server
6118 returns for AddJob. AddJob
6119 must fail on non-local
6120 printers */
6123 /****************************************************************************
6124 ****************************************************************************/
6126 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6127 int position, int snum)
6129 pstring temp_name;
6131 struct tm *t;
6133 t=gmtime(&queue->time);
6134 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6136 job_info->jobid=queue->job;
6137 init_unistr(&job_info->printername, lp_servicename(snum));
6138 init_unistr(&job_info->machinename, temp_name);
6139 init_unistr(&job_info->username, queue->fs_user);
6140 init_unistr(&job_info->document, queue->fs_file);
6141 init_unistr(&job_info->datatype, "RAW");
6142 init_unistr(&job_info->text_status, "");
6143 job_info->status=nt_printj_status(queue->status);
6144 job_info->priority=queue->priority;
6145 job_info->position=position;
6146 job_info->totalpages=queue->page_count;
6147 job_info->pagesprinted=0;
6149 make_systemtime(&job_info->submitted, t);
6152 /****************************************************************************
6153 ****************************************************************************/
6155 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6156 int position, int snum,
6157 NT_PRINTER_INFO_LEVEL *ntprinter,
6158 DEVICEMODE *devmode)
6160 pstring temp_name;
6161 struct tm *t;
6163 t=gmtime(&queue->time);
6164 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6166 job_info->jobid=queue->job;
6168 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6170 init_unistr(&job_info->machinename, temp_name);
6171 init_unistr(&job_info->username, queue->fs_user);
6172 init_unistr(&job_info->document, queue->fs_file);
6173 init_unistr(&job_info->notifyname, queue->fs_user);
6174 init_unistr(&job_info->datatype, "RAW");
6175 init_unistr(&job_info->printprocessor, "winprint");
6176 init_unistr(&job_info->parameters, "");
6177 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6178 init_unistr(&job_info->text_status, "");
6180 /* and here the security descriptor */
6182 job_info->status=nt_printj_status(queue->status);
6183 job_info->priority=queue->priority;
6184 job_info->position=position;
6185 job_info->starttime=0;
6186 job_info->untiltime=0;
6187 job_info->totalpages=queue->page_count;
6188 job_info->size=queue->size;
6189 make_systemtime(&(job_info->submitted), t);
6190 job_info->timeelapsed=0;
6191 job_info->pagesprinted=0;
6193 job_info->devmode = devmode;
6195 return (True);
6198 /****************************************************************************
6199 Enumjobs at level 1.
6200 ****************************************************************************/
6202 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6203 NEW_BUFFER *buffer, uint32 offered,
6204 uint32 *needed, uint32 *returned)
6206 JOB_INFO_1 *info;
6207 int i;
6209 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6210 if (info==NULL) {
6211 SAFE_FREE(queue);
6212 *returned=0;
6213 return WERR_NOMEM;
6216 for (i=0; i<*returned; i++)
6217 fill_job_info_1(&info[i], &queue[i], i, snum);
6219 SAFE_FREE(queue);
6221 /* check the required size. */
6222 for (i=0; i<*returned; i++)
6223 (*needed) += spoolss_size_job_info_1(&info[i]);
6225 if (!alloc_buffer_size(buffer, *needed)) {
6226 SAFE_FREE(info);
6227 return WERR_INSUFFICIENT_BUFFER;
6230 /* fill the buffer with the structures */
6231 for (i=0; i<*returned; i++)
6232 smb_io_job_info_1("", buffer, &info[i], 0);
6234 /* clear memory */
6235 SAFE_FREE(info);
6237 if (*needed > offered) {
6238 *returned=0;
6239 return WERR_INSUFFICIENT_BUFFER;
6242 return WERR_OK;
6245 /****************************************************************************
6246 Enumjobs at level 2.
6247 ****************************************************************************/
6249 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6250 NEW_BUFFER *buffer, uint32 offered,
6251 uint32 *needed, uint32 *returned)
6253 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6254 JOB_INFO_2 *info = NULL;
6255 int i;
6256 WERROR result;
6257 DEVICEMODE *devmode = NULL;
6259 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6260 if (info==NULL) {
6261 *returned=0;
6262 result = WERR_NOMEM;
6263 goto done;
6266 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6267 if (!W_ERROR_IS_OK(result)) {
6268 *returned = 0;
6269 goto done;
6272 /* this should not be a failure condition if the devmode is NULL */
6274 devmode = construct_dev_mode(snum);
6276 for (i=0; i<*returned; i++)
6277 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6278 devmode);
6280 free_a_printer(&ntprinter, 2);
6281 SAFE_FREE(queue);
6283 /* check the required size. */
6284 for (i=0; i<*returned; i++)
6285 (*needed) += spoolss_size_job_info_2(&info[i]);
6287 if (*needed > offered) {
6288 *returned=0;
6289 result = WERR_INSUFFICIENT_BUFFER;
6290 goto done;
6293 if (!alloc_buffer_size(buffer, *needed)) {
6294 SAFE_FREE(info);
6295 result = WERR_INSUFFICIENT_BUFFER;
6296 goto done;
6299 /* fill the buffer with the structures */
6300 for (i=0; i<*returned; i++)
6301 smb_io_job_info_2("", buffer, &info[i], 0);
6303 result = WERR_OK;
6305 done:
6306 free_a_printer(&ntprinter, 2);
6307 free_devmode(devmode);
6308 SAFE_FREE(queue);
6309 SAFE_FREE(info);
6311 return result;
6315 /****************************************************************************
6316 Enumjobs.
6317 ****************************************************************************/
6319 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6321 POLICY_HND *handle = &q_u->handle;
6322 uint32 level = q_u->level;
6323 NEW_BUFFER *buffer = NULL;
6324 uint32 offered = q_u->offered;
6325 uint32 *needed = &r_u->needed;
6326 uint32 *returned = &r_u->returned;
6328 int snum;
6329 print_status_struct prt_status;
6330 print_queue_struct *queue=NULL;
6331 int max_rep_jobs;
6333 /* that's an [in out] buffer */
6334 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6335 buffer = r_u->buffer;
6337 DEBUG(4,("_spoolss_enumjobs\n"));
6339 *needed=0;
6340 *returned=0;
6342 if (!get_printer_snum(p, handle, &snum))
6343 return WERR_BADFID;
6345 max_rep_jobs = lp_max_reported_jobs(snum);
6347 *returned = print_queue_status(snum, &queue, &prt_status);
6348 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6350 if (*returned == 0) {
6351 SAFE_FREE(queue);
6352 return WERR_OK;
6355 if (max_rep_jobs && (*returned > max_rep_jobs))
6356 *returned = max_rep_jobs;
6358 switch (level) {
6359 case 1:
6360 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6361 case 2:
6362 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6363 default:
6364 SAFE_FREE(queue);
6365 *returned=0;
6366 return WERR_UNKNOWN_LEVEL;
6370 /****************************************************************************
6371 ****************************************************************************/
6373 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6375 return WERR_OK;
6378 /****************************************************************************
6379 ****************************************************************************/
6381 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6383 POLICY_HND *handle = &q_u->handle;
6384 uint32 jobid = q_u->jobid;
6385 uint32 command = q_u->command;
6387 struct current_user user;
6388 int snum;
6389 WERROR errcode = WERR_BADFUNC;
6391 if (!get_printer_snum(p, handle, &snum)) {
6392 return WERR_BADFID;
6395 if (!print_job_exists(snum, jobid)) {
6396 return WERR_INVALID_PRINTER_NAME;
6399 get_current_user(&user, p);
6401 switch (command) {
6402 case JOB_CONTROL_CANCEL:
6403 case JOB_CONTROL_DELETE:
6404 if (print_job_delete(&user, snum, jobid, &errcode)) {
6405 errcode = WERR_OK;
6407 break;
6408 case JOB_CONTROL_PAUSE:
6409 if (print_job_pause(&user, snum, jobid, &errcode)) {
6410 errcode = WERR_OK;
6412 break;
6413 case JOB_CONTROL_RESTART:
6414 case JOB_CONTROL_RESUME:
6415 if (print_job_resume(&user, snum, jobid, &errcode)) {
6416 errcode = WERR_OK;
6418 break;
6419 default:
6420 return WERR_UNKNOWN_LEVEL;
6423 return errcode;
6426 /****************************************************************************
6427 Enumerates all printer drivers at level 1.
6428 ****************************************************************************/
6430 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6432 int i;
6433 int ndrivers;
6434 uint32 version;
6435 fstring *list = NULL;
6437 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6438 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6440 *returned=0;
6442 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6443 list=NULL;
6444 ndrivers=get_ntdrivers(&list, architecture, version);
6445 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6447 if(ndrivers == -1)
6448 return WERR_NOMEM;
6450 if(ndrivers != 0) {
6451 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6452 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6453 SAFE_FREE(driver_info_1);
6454 SAFE_FREE(list);
6455 return WERR_NOMEM;
6457 else driver_info_1 = tdi1;
6460 for (i=0; i<ndrivers; i++) {
6461 WERROR status;
6462 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6463 ZERO_STRUCT(driver);
6464 status = get_a_printer_driver(&driver, 3, list[i],
6465 architecture, version);
6466 if (!W_ERROR_IS_OK(status)) {
6467 SAFE_FREE(list);
6468 return status;
6470 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6471 free_a_printer_driver(driver, 3);
6474 *returned+=ndrivers;
6475 SAFE_FREE(list);
6478 /* check the required size. */
6479 for (i=0; i<*returned; i++) {
6480 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6481 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6484 if (!alloc_buffer_size(buffer, *needed)) {
6485 SAFE_FREE(driver_info_1);
6486 return WERR_INSUFFICIENT_BUFFER;
6489 /* fill the buffer with the driver structures */
6490 for (i=0; i<*returned; i++) {
6491 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6492 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6495 SAFE_FREE(driver_info_1);
6497 if (*needed > offered) {
6498 *returned=0;
6499 return WERR_INSUFFICIENT_BUFFER;
6502 return WERR_OK;
6505 /****************************************************************************
6506 Enumerates all printer drivers at level 2.
6507 ****************************************************************************/
6509 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6511 int i;
6512 int ndrivers;
6513 uint32 version;
6514 fstring *list = NULL;
6516 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6517 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6519 *returned=0;
6521 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6522 list=NULL;
6523 ndrivers=get_ntdrivers(&list, architecture, version);
6524 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6526 if(ndrivers == -1)
6527 return WERR_NOMEM;
6529 if(ndrivers != 0) {
6530 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6531 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6532 SAFE_FREE(driver_info_2);
6533 SAFE_FREE(list);
6534 return WERR_NOMEM;
6536 else driver_info_2 = tdi2;
6539 for (i=0; i<ndrivers; i++) {
6540 WERROR status;
6542 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6543 ZERO_STRUCT(driver);
6544 status = get_a_printer_driver(&driver, 3, list[i],
6545 architecture, version);
6546 if (!W_ERROR_IS_OK(status)) {
6547 SAFE_FREE(list);
6548 return status;
6550 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6551 free_a_printer_driver(driver, 3);
6554 *returned+=ndrivers;
6555 SAFE_FREE(list);
6558 /* check the required size. */
6559 for (i=0; i<*returned; i++) {
6560 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6561 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6564 if (!alloc_buffer_size(buffer, *needed)) {
6565 SAFE_FREE(driver_info_2);
6566 return WERR_INSUFFICIENT_BUFFER;
6569 /* fill the buffer with the form structures */
6570 for (i=0; i<*returned; i++) {
6571 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6572 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6575 SAFE_FREE(driver_info_2);
6577 if (*needed > offered) {
6578 *returned=0;
6579 return WERR_INSUFFICIENT_BUFFER;
6582 return WERR_OK;
6585 /****************************************************************************
6586 Enumerates all printer drivers at level 3.
6587 ****************************************************************************/
6589 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6591 int i;
6592 int ndrivers;
6593 uint32 version;
6594 fstring *list = NULL;
6596 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6597 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6599 *returned=0;
6601 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6602 list=NULL;
6603 ndrivers=get_ntdrivers(&list, architecture, version);
6604 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6606 if(ndrivers == -1)
6607 return WERR_NOMEM;
6609 if(ndrivers != 0) {
6610 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6611 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6612 SAFE_FREE(driver_info_3);
6613 SAFE_FREE(list);
6614 return WERR_NOMEM;
6616 else driver_info_3 = tdi3;
6619 for (i=0; i<ndrivers; i++) {
6620 WERROR status;
6622 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6623 ZERO_STRUCT(driver);
6624 status = get_a_printer_driver(&driver, 3, list[i],
6625 architecture, version);
6626 if (!W_ERROR_IS_OK(status)) {
6627 SAFE_FREE(list);
6628 return status;
6630 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6631 free_a_printer_driver(driver, 3);
6634 *returned+=ndrivers;
6635 SAFE_FREE(list);
6638 /* check the required size. */
6639 for (i=0; i<*returned; i++) {
6640 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6641 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6644 if (!alloc_buffer_size(buffer, *needed)) {
6645 SAFE_FREE(driver_info_3);
6646 return WERR_INSUFFICIENT_BUFFER;
6649 /* fill the buffer with the driver structures */
6650 for (i=0; i<*returned; i++) {
6651 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6652 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6655 for (i=0; i<*returned; i++)
6656 SAFE_FREE(driver_info_3[i].dependentfiles);
6658 SAFE_FREE(driver_info_3);
6660 if (*needed > offered) {
6661 *returned=0;
6662 return WERR_INSUFFICIENT_BUFFER;
6665 return WERR_OK;
6668 /****************************************************************************
6669 Enumerates all printer drivers.
6670 ****************************************************************************/
6672 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6674 UNISTR2 *environment = &q_u->environment;
6675 uint32 level = q_u->level;
6676 NEW_BUFFER *buffer = NULL;
6677 uint32 offered = q_u->offered;
6678 uint32 *needed = &r_u->needed;
6679 uint32 *returned = &r_u->returned;
6681 fstring *list = NULL;
6682 fstring servername;
6683 fstring architecture;
6685 /* that's an [in out] buffer */
6686 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6687 buffer = r_u->buffer;
6689 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6690 fstrcpy(servername, get_called_name());
6691 *needed=0;
6692 *returned=0;
6694 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6696 switch (level) {
6697 case 1:
6698 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6699 case 2:
6700 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6701 case 3:
6702 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6703 default:
6704 *returned=0;
6705 SAFE_FREE(list);
6706 return WERR_UNKNOWN_LEVEL;
6710 /****************************************************************************
6711 ****************************************************************************/
6713 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6715 form->flag=list->flag;
6716 init_unistr(&form->name, list->name);
6717 form->width=list->width;
6718 form->length=list->length;
6719 form->left=list->left;
6720 form->top=list->top;
6721 form->right=list->right;
6722 form->bottom=list->bottom;
6725 /****************************************************************************
6726 ****************************************************************************/
6728 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6730 uint32 level = q_u->level;
6731 NEW_BUFFER *buffer = NULL;
6732 uint32 offered = q_u->offered;
6733 uint32 *needed = &r_u->needed;
6734 uint32 *numofforms = &r_u->numofforms;
6735 uint32 numbuiltinforms;
6737 nt_forms_struct *list=NULL;
6738 nt_forms_struct *builtinlist=NULL;
6739 FORM_1 *forms_1;
6740 int buffer_size=0;
6741 int i;
6743 /* that's an [in out] buffer */
6744 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6745 buffer = r_u->buffer;
6747 DEBUG(4,("_spoolss_enumforms\n"));
6748 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6749 DEBUGADD(5,("Info level [%d]\n", level));
6751 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6752 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6753 *numofforms = get_ntforms(&list);
6754 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6755 *numofforms += numbuiltinforms;
6757 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6759 switch (level) {
6760 case 1:
6761 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6762 *numofforms=0;
6763 return WERR_NOMEM;
6766 /* construct the list of form structures */
6767 for (i=0; i<numbuiltinforms; i++) {
6768 DEBUGADD(6,("Filling form number [%d]\n",i));
6769 fill_form_1(&forms_1[i], &builtinlist[i]);
6772 SAFE_FREE(builtinlist);
6774 for (; i<*numofforms; i++) {
6775 DEBUGADD(6,("Filling form number [%d]\n",i));
6776 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6779 SAFE_FREE(list);
6781 /* check the required size. */
6782 for (i=0; i<numbuiltinforms; i++) {
6783 DEBUGADD(6,("adding form [%d]'s size\n",i));
6784 buffer_size += spoolss_size_form_1(&forms_1[i]);
6786 for (; i<*numofforms; i++) {
6787 DEBUGADD(6,("adding form [%d]'s size\n",i));
6788 buffer_size += spoolss_size_form_1(&forms_1[i]);
6791 *needed=buffer_size;
6793 if (!alloc_buffer_size(buffer, buffer_size)){
6794 SAFE_FREE(forms_1);
6795 return WERR_INSUFFICIENT_BUFFER;
6798 /* fill the buffer with the form structures */
6799 for (i=0; i<numbuiltinforms; i++) {
6800 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6801 smb_io_form_1("", buffer, &forms_1[i], 0);
6803 for (; i<*numofforms; i++) {
6804 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6805 smb_io_form_1("", buffer, &forms_1[i], 0);
6808 SAFE_FREE(forms_1);
6810 if (*needed > offered) {
6811 *numofforms=0;
6812 return WERR_INSUFFICIENT_BUFFER;
6814 else
6815 return WERR_OK;
6817 default:
6818 SAFE_FREE(list);
6819 SAFE_FREE(builtinlist);
6820 return WERR_UNKNOWN_LEVEL;
6825 /****************************************************************************
6826 ****************************************************************************/
6828 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6830 uint32 level = q_u->level;
6831 UNISTR2 *uni_formname = &q_u->formname;
6832 NEW_BUFFER *buffer = NULL;
6833 uint32 offered = q_u->offered;
6834 uint32 *needed = &r_u->needed;
6836 nt_forms_struct *list=NULL;
6837 nt_forms_struct builtin_form;
6838 BOOL foundBuiltin;
6839 FORM_1 form_1;
6840 fstring form_name;
6841 int buffer_size=0;
6842 int numofforms=0, i=0;
6844 /* that's an [in out] buffer */
6845 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6846 buffer = r_u->buffer;
6848 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6850 DEBUG(4,("_spoolss_getform\n"));
6851 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6852 DEBUGADD(5,("Info level [%d]\n", level));
6854 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6855 if (!foundBuiltin) {
6856 numofforms = get_ntforms(&list);
6857 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6859 if (numofforms == 0)
6860 return WERR_BADFID;
6863 switch (level) {
6864 case 1:
6865 if (foundBuiltin) {
6866 fill_form_1(&form_1, &builtin_form);
6867 } else {
6869 /* Check if the requested name is in the list of form structures */
6870 for (i=0; i<numofforms; i++) {
6872 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6874 if (strequal(form_name, list[i].name)) {
6875 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6876 fill_form_1(&form_1, &list[i]);
6877 break;
6881 SAFE_FREE(list);
6882 if (i == numofforms) {
6883 return WERR_BADFID;
6886 /* check the required size. */
6888 *needed=spoolss_size_form_1(&form_1);
6890 if (!alloc_buffer_size(buffer, buffer_size)){
6891 return WERR_INSUFFICIENT_BUFFER;
6894 if (*needed > offered) {
6895 return WERR_INSUFFICIENT_BUFFER;
6898 /* fill the buffer with the form structures */
6899 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6900 smb_io_form_1("", buffer, &form_1, 0);
6902 return WERR_OK;
6904 default:
6905 SAFE_FREE(list);
6906 return WERR_UNKNOWN_LEVEL;
6910 /****************************************************************************
6911 ****************************************************************************/
6913 static void fill_port_1(PORT_INFO_1 *port, const char *name)
6915 init_unistr(&port->port_name, name);
6918 /****************************************************************************
6919 ****************************************************************************/
6921 static void fill_port_2(PORT_INFO_2 *port, const char *name)
6923 init_unistr(&port->port_name, name);
6924 init_unistr(&port->monitor_name, "Local Monitor");
6925 init_unistr(&port->description, "Local Port");
6926 #define PORT_TYPE_WRITE 1
6927 port->port_type=PORT_TYPE_WRITE;
6928 port->reserved=0x0;
6931 /****************************************************************************
6932 enumports level 1.
6933 ****************************************************************************/
6935 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6937 PORT_INFO_1 *ports=NULL;
6938 int i=0;
6940 if (*lp_enumports_cmd()) {
6941 char *cmd = lp_enumports_cmd();
6942 char **qlines;
6943 pstring command;
6944 int numlines;
6945 int ret;
6946 int fd;
6948 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6950 DEBUG(10,("Running [%s]\n", command));
6951 ret = smbrun(command, &fd);
6952 DEBUG(10,("Returned [%d]\n", ret));
6953 if (ret != 0) {
6954 if (fd != -1)
6955 close(fd);
6956 /* Is this the best error to return here? */
6957 return WERR_ACCESS_DENIED;
6960 numlines = 0;
6961 qlines = fd_lines_load(fd, &numlines);
6962 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6963 close(fd);
6965 if(numlines) {
6966 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6967 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6968 dos_errstr(WERR_NOMEM)));
6969 file_lines_free(qlines);
6970 return WERR_NOMEM;
6973 for (i=0; i<numlines; i++) {
6974 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6975 fill_port_1(&ports[i], qlines[i]);
6978 file_lines_free(qlines);
6981 *returned = numlines;
6983 } else {
6984 *returned = 1; /* Sole Samba port returned. */
6986 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6987 return WERR_NOMEM;
6989 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6991 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6994 /* check the required size. */
6995 for (i=0; i<*returned; i++) {
6996 DEBUGADD(6,("adding port [%d]'s size\n", i));
6997 *needed += spoolss_size_port_info_1(&ports[i]);
7000 if (!alloc_buffer_size(buffer, *needed)) {
7001 SAFE_FREE(ports);
7002 return WERR_INSUFFICIENT_BUFFER;
7005 /* fill the buffer with the ports structures */
7006 for (i=0; i<*returned; i++) {
7007 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7008 smb_io_port_1("", buffer, &ports[i], 0);
7011 SAFE_FREE(ports);
7013 if (*needed > offered) {
7014 *returned=0;
7015 return WERR_INSUFFICIENT_BUFFER;
7018 return WERR_OK;
7021 /****************************************************************************
7022 enumports level 2.
7023 ****************************************************************************/
7025 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7027 PORT_INFO_2 *ports=NULL;
7028 int i=0;
7030 if (*lp_enumports_cmd()) {
7031 char *cmd = lp_enumports_cmd();
7032 char *path;
7033 char **qlines;
7034 pstring tmp_file;
7035 pstring command;
7036 int numlines;
7037 int ret;
7038 int fd;
7040 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7041 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7042 else
7043 path = lp_lockdir();
7045 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7046 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7048 unlink(tmp_file);
7049 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7050 ret = smbrun(command, &fd);
7051 DEBUGADD(10,("returned [%d]\n", ret));
7052 if (ret != 0) {
7053 if (fd != -1)
7054 close(fd);
7055 /* Is this the best error to return here? */
7056 return WERR_ACCESS_DENIED;
7059 numlines = 0;
7060 qlines = fd_lines_load(fd, &numlines);
7061 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7062 close(fd);
7064 if(numlines) {
7065 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7066 file_lines_free(qlines);
7067 return WERR_NOMEM;
7070 for (i=0; i<numlines; i++) {
7071 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7072 fill_port_2(&(ports[i]), qlines[i]);
7075 file_lines_free(qlines);
7078 *returned = numlines;
7080 } else {
7082 *returned = 1;
7084 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7085 return WERR_NOMEM;
7087 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7089 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7092 /* check the required size. */
7093 for (i=0; i<*returned; i++) {
7094 DEBUGADD(6,("adding port [%d]'s size\n", i));
7095 *needed += spoolss_size_port_info_2(&ports[i]);
7098 if (!alloc_buffer_size(buffer, *needed)) {
7099 SAFE_FREE(ports);
7100 return WERR_INSUFFICIENT_BUFFER;
7103 /* fill the buffer with the ports structures */
7104 for (i=0; i<*returned; i++) {
7105 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7106 smb_io_port_2("", buffer, &ports[i], 0);
7109 SAFE_FREE(ports);
7111 if (*needed > offered) {
7112 *returned=0;
7113 return WERR_INSUFFICIENT_BUFFER;
7116 return WERR_OK;
7119 /****************************************************************************
7120 enumports.
7121 ****************************************************************************/
7123 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7125 uint32 level = q_u->level;
7126 NEW_BUFFER *buffer = NULL;
7127 uint32 offered = q_u->offered;
7128 uint32 *needed = &r_u->needed;
7129 uint32 *returned = &r_u->returned;
7131 /* that's an [in out] buffer */
7132 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7133 buffer = r_u->buffer;
7135 DEBUG(4,("_spoolss_enumports\n"));
7137 *returned=0;
7138 *needed=0;
7140 switch (level) {
7141 case 1:
7142 return enumports_level_1(buffer, offered, needed, returned);
7143 case 2:
7144 return enumports_level_2(buffer, offered, needed, returned);
7145 default:
7146 return WERR_UNKNOWN_LEVEL;
7150 /****************************************************************************
7151 ****************************************************************************/
7153 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7154 const SPOOL_PRINTER_INFO_LEVEL *info,
7155 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7156 uint32 user_switch, const SPOOL_USER_CTR *user,
7157 POLICY_HND *handle)
7159 NT_PRINTER_INFO_LEVEL *printer = NULL;
7160 fstring name;
7161 int snum;
7162 WERROR err = WERR_OK;
7164 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7165 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7166 return WERR_NOMEM;
7169 ZERO_STRUCTP(printer);
7171 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7172 if (!convert_printer_info(info, printer, 2)) {
7173 free_a_printer(&printer, 2);
7174 return WERR_NOMEM;
7177 /* check to see if the printer already exists */
7179 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7180 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7181 printer->info_2->sharename));
7182 free_a_printer(&printer, 2);
7183 return WERR_PRINTER_ALREADY_EXISTS;
7186 if (*lp_addprinter_cmd() ) {
7187 if ( !add_printer_hook(printer) ) {
7188 free_a_printer(&printer,2);
7189 return WERR_ACCESS_DENIED;
7193 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7194 printer->info_2->sharename);
7197 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7198 free_a_printer(&printer,2);
7199 return WERR_ACCESS_DENIED;
7202 /* you must be a printer admin to add a new printer */
7203 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7204 free_a_printer(&printer,2);
7205 return WERR_ACCESS_DENIED;
7209 * Do sanity check on the requested changes for Samba.
7212 if (!check_printer_ok(printer->info_2, snum)) {
7213 free_a_printer(&printer,2);
7214 return WERR_INVALID_PARAM;
7218 * When a printer is created, the drivername bound to the printer is used
7219 * to lookup previously saved driver initialization info, which is then
7220 * bound to the new printer, simulating what happens in the Windows arch.
7223 if (!devmode)
7225 set_driver_init(printer, 2);
7227 else
7229 /* A valid devmode was included, convert and link it
7231 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7233 if (!convert_devicemode(printer->info_2->printername, devmode,
7234 &printer->info_2->devmode))
7235 return WERR_NOMEM;
7238 /* write the ASCII on disk */
7239 err = mod_a_printer(*printer, 2);
7240 if (!W_ERROR_IS_OK(err)) {
7241 free_a_printer(&printer,2);
7242 return err;
7245 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7246 /* Handle open failed - remove addition. */
7247 del_a_printer(printer->info_2->sharename);
7248 free_a_printer(&printer,2);
7249 return WERR_ACCESS_DENIED;
7252 update_c_setprinter(False);
7253 free_a_printer(&printer,2);
7255 return WERR_OK;
7258 /****************************************************************************
7259 ****************************************************************************/
7261 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7263 UNISTR2 *uni_srv_name = &q_u->server_name;
7264 uint32 level = q_u->level;
7265 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7266 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7267 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7268 uint32 user_switch = q_u->user_switch;
7269 SPOOL_USER_CTR *user = &q_u->user_ctr;
7270 POLICY_HND *handle = &r_u->handle;
7272 switch (level) {
7273 case 1:
7274 /* we don't handle yet */
7275 /* but I know what to do ... */
7276 return WERR_UNKNOWN_LEVEL;
7277 case 2:
7278 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7279 devmode, sdb,
7280 user_switch, user, handle);
7281 default:
7282 return WERR_UNKNOWN_LEVEL;
7286 /****************************************************************************
7287 ****************************************************************************/
7289 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7291 uint32 level = q_u->level;
7292 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7293 WERROR err = WERR_OK;
7294 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7295 struct current_user user;
7296 fstring driver_name;
7297 uint32 version;
7299 ZERO_STRUCT(driver);
7301 get_current_user(&user, p);
7303 if (!convert_printer_driver_info(info, &driver, level)) {
7304 err = WERR_NOMEM;
7305 goto done;
7308 DEBUG(5,("Cleaning driver's information\n"));
7309 err = clean_up_driver_struct(driver, level, &user);
7310 if (!W_ERROR_IS_OK(err))
7311 goto done;
7313 DEBUG(5,("Moving driver to final destination\n"));
7314 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7315 if (W_ERROR_IS_OK(err))
7316 err = WERR_ACCESS_DENIED;
7317 goto done;
7320 if (add_a_printer_driver(driver, level)!=0) {
7321 err = WERR_ACCESS_DENIED;
7322 goto done;
7325 /* BEGIN_ADMIN_LOG */
7326 switch(level) {
7327 case 3:
7328 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7329 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7330 fstrcpy(driver_name, driver.info_3->name);
7331 break;
7332 case 6:
7333 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7334 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7335 fstrcpy(driver_name, driver.info_6->name);
7336 break;
7338 /* END_ADMIN_LOG */
7341 * I think this is where he DrvUpgradePrinter() hook would be
7342 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7343 * server. Right now, we just need to send ourselves a message
7344 * to update each printer bound to this driver. --jerry
7347 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7348 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7349 driver_name));
7353 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7354 * decide if the driver init data should be deleted. The rules are:
7355 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7356 * 2) delete init data only if there is no 2k/Xp driver
7357 * 3) always delete init data
7358 * The generalized rule is always use init data from the highest order driver.
7359 * It is necessary to follow the driver install by an initialization step to
7360 * finish off this process.
7362 if (level == 3)
7363 version = driver.info_3->cversion;
7364 else if (level == 6)
7365 version = driver.info_6->version;
7366 else
7367 version = -1;
7368 switch (version) {
7370 * 9x printer driver - never delete init data
7372 case 0:
7373 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7374 driver_name));
7375 break;
7378 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7379 * there is no 2k/Xp driver init data for this driver name.
7381 case 2:
7383 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7385 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7387 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7389 if (!del_driver_init(driver_name))
7390 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7391 } else {
7393 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7395 free_a_printer_driver(driver1,3);
7396 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7397 driver_name));
7400 break;
7403 * 2k or Xp printer driver - always delete init data
7405 case 3:
7406 if (!del_driver_init(driver_name))
7407 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7408 break;
7410 default:
7411 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7412 break;
7416 done:
7417 free_a_printer_driver(driver, level);
7418 return err;
7421 /********************************************************************
7422 * spoolss_addprinterdriverex
7423 ********************************************************************/
7425 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7427 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7428 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7431 * we only support the semantics of AddPrinterDriver()
7432 * i.e. only copy files that are newer than existing ones
7435 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7436 return WERR_ACCESS_DENIED;
7438 ZERO_STRUCT(q_u_local);
7439 ZERO_STRUCT(r_u_local);
7441 /* just pass the information off to _spoolss_addprinterdriver() */
7442 q_u_local.server_name_ptr = q_u->server_name_ptr;
7443 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7444 q_u_local.level = q_u->level;
7445 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7447 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7450 /****************************************************************************
7451 ****************************************************************************/
7453 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7455 init_unistr(&info->name, name);
7458 /****************************************************************************
7459 ****************************************************************************/
7461 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7463 pstring path;
7464 pstring long_archi;
7465 pstring short_archi;
7466 DRIVER_DIRECTORY_1 *info=NULL;
7468 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7470 if (get_short_archi(short_archi, long_archi)==False)
7471 return WERR_INVALID_ENVIRONMENT;
7473 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7474 return WERR_NOMEM;
7476 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7478 DEBUG(4,("printer driver directory: [%s]\n", path));
7480 fill_driverdir_1(info, path);
7482 *needed += spoolss_size_driverdir_info_1(info);
7484 if (!alloc_buffer_size(buffer, *needed)) {
7485 SAFE_FREE(info);
7486 return WERR_INSUFFICIENT_BUFFER;
7489 smb_io_driverdir_1("", buffer, info, 0);
7491 SAFE_FREE(info);
7493 if (*needed > offered)
7494 return WERR_INSUFFICIENT_BUFFER;
7496 return WERR_OK;
7499 /****************************************************************************
7500 ****************************************************************************/
7502 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7504 UNISTR2 *name = &q_u->name;
7505 UNISTR2 *uni_environment = &q_u->environment;
7506 uint32 level = q_u->level;
7507 NEW_BUFFER *buffer = NULL;
7508 uint32 offered = q_u->offered;
7509 uint32 *needed = &r_u->needed;
7511 /* that's an [in out] buffer */
7512 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7513 buffer = r_u->buffer;
7515 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7517 *needed=0;
7519 switch(level) {
7520 case 1:
7521 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7522 default:
7523 return WERR_UNKNOWN_LEVEL;
7527 /****************************************************************************
7528 ****************************************************************************/
7530 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7532 POLICY_HND *handle = &q_u->handle;
7533 uint32 idx = q_u->index;
7534 uint32 in_value_len = q_u->valuesize;
7535 uint32 in_data_len = q_u->datasize;
7536 uint32 *out_max_value_len = &r_u->valuesize;
7537 uint16 **out_value = &r_u->value;
7538 uint32 *out_value_len = &r_u->realvaluesize;
7539 uint32 *out_type = &r_u->type;
7540 uint32 *out_max_data_len = &r_u->datasize;
7541 uint8 **data_out = &r_u->data;
7542 uint32 *out_data_len = &r_u->realdatasize;
7544 NT_PRINTER_INFO_LEVEL *printer = NULL;
7546 uint32 param_index;
7547 uint32 biggest_valuesize;
7548 uint32 biggest_datasize;
7549 uint32 data_len;
7550 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7551 int snum;
7552 WERROR result;
7553 REGISTRY_VALUE *val;
7554 NT_PRINTER_DATA *p_data;
7555 int i, key_index, num_values;
7556 int name_length;
7558 ZERO_STRUCT( printer );
7560 *out_type = 0;
7562 *out_max_data_len = 0;
7563 *data_out = NULL;
7564 *out_data_len = 0;
7566 DEBUG(5,("spoolss_enumprinterdata\n"));
7568 if (!Printer) {
7569 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7570 return WERR_BADFID;
7573 if (!get_printer_snum(p,handle, &snum))
7574 return WERR_BADFID;
7576 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7577 if (!W_ERROR_IS_OK(result))
7578 return result;
7580 p_data = &printer->info_2->data;
7581 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7583 result = WERR_OK;
7586 * The NT machine wants to know the biggest size of value and data
7588 * cf: MSDN EnumPrinterData remark section
7591 if ( !in_value_len && !in_data_len )
7593 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7595 param_index = 0;
7596 biggest_valuesize = 0;
7597 biggest_datasize = 0;
7599 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7601 for ( i=0; i<num_values; i++ )
7603 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7605 name_length = strlen(val->valuename);
7606 if ( strlen(val->valuename) > biggest_valuesize )
7607 biggest_valuesize = name_length;
7609 if ( val->size > biggest_datasize )
7610 biggest_datasize = val->size;
7612 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7613 biggest_datasize));
7616 /* the value is an UNICODE string but real_value_size is the length
7617 in bytes including the trailing 0 */
7619 *out_value_len = 2 * (1+biggest_valuesize);
7620 *out_data_len = biggest_datasize;
7622 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7624 goto done;
7628 * the value len is wrong in NT sp3
7629 * that's the number of bytes not the number of unicode chars
7632 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7634 if ( !val )
7637 /* out_value should default to "" or else NT4 has
7638 problems unmarshalling the response */
7640 *out_max_value_len=(in_value_len/sizeof(uint16));
7642 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7644 result = WERR_NOMEM;
7645 goto done;
7648 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7650 /* the data is counted in bytes */
7652 *out_max_data_len = in_data_len;
7653 *out_data_len = in_data_len;
7655 /* only allocate when given a non-zero data_len */
7657 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7659 result = WERR_NOMEM;
7660 goto done;
7663 result = WERR_NO_MORE_ITEMS;
7665 else
7668 * the value is:
7669 * - counted in bytes in the request
7670 * - counted in UNICODE chars in the max reply
7671 * - counted in bytes in the real size
7673 * take a pause *before* coding not *during* coding
7676 /* name */
7677 *out_max_value_len=(in_value_len/sizeof(uint16));
7678 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7680 result = WERR_NOMEM;
7681 goto done;
7684 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7686 /* type */
7688 *out_type = regval_type( val );
7690 /* data - counted in bytes */
7692 *out_max_data_len = in_data_len;
7693 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7695 result = WERR_NOMEM;
7696 goto done;
7698 data_len = (size_t)regval_size(val);
7699 memcpy( *data_out, regval_data_p(val), data_len );
7700 *out_data_len = data_len;
7703 done:
7704 free_a_printer(&printer, 2);
7705 return result;
7708 /****************************************************************************
7709 ****************************************************************************/
7711 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7713 POLICY_HND *handle = &q_u->handle;
7714 UNISTR2 *value = &q_u->value;
7715 uint32 type = q_u->type;
7716 uint8 *data = q_u->data;
7717 uint32 real_len = q_u->real_len;
7719 NT_PRINTER_INFO_LEVEL *printer = NULL;
7720 int snum=0;
7721 WERROR status = WERR_OK;
7722 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7723 fstring valuename;
7725 DEBUG(5,("spoolss_setprinterdata\n"));
7727 if (!Printer) {
7728 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7729 return WERR_BADFID;
7732 if (!get_printer_snum(p,handle, &snum))
7733 return WERR_BADFID;
7736 * Access check : NT returns "access denied" if you make a
7737 * SetPrinterData call without the necessary privildge.
7738 * we were originally returning OK if nothing changed
7739 * which made Win2k issue **a lot** of SetPrinterData
7740 * when connecting to a printer --jerry
7743 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7745 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7746 status = WERR_ACCESS_DENIED;
7747 goto done;
7750 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7751 if (!W_ERROR_IS_OK(status))
7752 return status;
7754 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7757 * When client side code sets a magic printer data key, detect it and save
7758 * the current printer data and the magic key's data (its the DEVMODE) for
7759 * future printer/driver initializations.
7761 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7763 /* Set devmode and printer initialization info */
7764 status = save_driver_init( printer, 2, data, real_len );
7766 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7768 else
7770 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7771 type, data, real_len );
7772 if ( W_ERROR_IS_OK(status) )
7773 status = mod_a_printer(*printer, 2);
7776 done:
7777 free_a_printer(&printer, 2);
7779 return status;
7782 /****************************************************************************
7783 ****************************************************************************/
7785 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7787 POLICY_HND *handle = &q_u->handle;
7788 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7789 int snum;
7791 DEBUG(5,("_spoolss_resetprinter\n"));
7794 * All we do is to check to see if the handle and queue is valid.
7795 * This call really doesn't mean anything to us because we only
7796 * support RAW printing. --jerry
7799 if (!Printer) {
7800 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7801 return WERR_BADFID;
7804 if (!get_printer_snum(p,handle, &snum))
7805 return WERR_BADFID;
7808 /* blindly return success */
7809 return WERR_OK;
7813 /****************************************************************************
7814 ****************************************************************************/
7816 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7818 POLICY_HND *handle = &q_u->handle;
7819 UNISTR2 *value = &q_u->valuename;
7821 NT_PRINTER_INFO_LEVEL *printer = NULL;
7822 int snum=0;
7823 WERROR status = WERR_OK;
7824 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7825 pstring valuename;
7827 DEBUG(5,("spoolss_deleteprinterdata\n"));
7829 if (!Printer) {
7830 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7831 return WERR_BADFID;
7834 if (!get_printer_snum(p, handle, &snum))
7835 return WERR_BADFID;
7837 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7838 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7839 return WERR_ACCESS_DENIED;
7842 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7843 if (!W_ERROR_IS_OK(status))
7844 return status;
7846 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7848 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7850 free_a_printer(&printer, 2);
7852 return status;
7855 /****************************************************************************
7856 ****************************************************************************/
7858 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7860 POLICY_HND *handle = &q_u->handle;
7861 FORM *form = &q_u->form;
7862 nt_forms_struct tmpForm;
7863 int snum;
7864 WERROR status = WERR_OK;
7865 NT_PRINTER_INFO_LEVEL *printer = NULL;
7867 int count=0;
7868 nt_forms_struct *list=NULL;
7869 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7871 DEBUG(5,("spoolss_addform\n"));
7873 if (!Printer) {
7874 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7875 return WERR_BADFID;
7879 /* forms can be added on printer of on the print server handle */
7881 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7883 if (!get_printer_snum(p,handle, &snum))
7884 return WERR_BADFID;
7886 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7887 if (!W_ERROR_IS_OK(status))
7888 goto done;
7891 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7892 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7893 status = WERR_ACCESS_DENIED;
7894 goto done;
7897 /* can't add if builtin */
7899 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7900 status = WERR_ALREADY_EXISTS;
7901 goto done;
7904 count = get_ntforms(&list);
7906 if(!add_a_form(&list, form, &count)) {
7907 status = WERR_NOMEM;
7908 goto done;
7911 write_ntforms(&list, count);
7914 * ChangeID must always be set if this is a printer
7917 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7918 status = mod_a_printer(*printer, 2);
7920 done:
7921 if ( printer )
7922 free_a_printer(&printer, 2);
7923 SAFE_FREE(list);
7925 return status;
7928 /****************************************************************************
7929 ****************************************************************************/
7931 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7933 POLICY_HND *handle = &q_u->handle;
7934 UNISTR2 *form_name = &q_u->name;
7935 nt_forms_struct tmpForm;
7936 int count=0;
7937 nt_forms_struct *list=NULL;
7938 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7939 int snum;
7940 WERROR status = WERR_OK;
7941 NT_PRINTER_INFO_LEVEL *printer = NULL;
7943 DEBUG(5,("spoolss_deleteform\n"));
7945 if (!Printer) {
7946 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7947 return WERR_BADFID;
7950 /* forms can be deleted on printer of on the print server handle */
7952 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7954 if (!get_printer_snum(p,handle, &snum))
7955 return WERR_BADFID;
7957 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7958 if (!W_ERROR_IS_OK(status))
7959 goto done;
7962 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7963 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7964 status = WERR_ACCESS_DENIED;
7965 goto done;
7968 /* can't delete if builtin */
7970 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7971 status = WERR_INVALID_PARAM;
7972 goto done;
7975 count = get_ntforms(&list);
7977 if ( !delete_a_form(&list, form_name, &count, &status ))
7978 goto done;
7981 * ChangeID must always be set if this is a printer
7984 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7985 status = mod_a_printer(*printer, 2);
7987 done:
7988 if ( printer )
7989 free_a_printer(&printer, 2);
7990 SAFE_FREE(list);
7992 return status;
7995 /****************************************************************************
7996 ****************************************************************************/
7998 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8000 POLICY_HND *handle = &q_u->handle;
8001 FORM *form = &q_u->form;
8002 nt_forms_struct tmpForm;
8003 int snum;
8004 WERROR status = WERR_OK;
8005 NT_PRINTER_INFO_LEVEL *printer = NULL;
8007 int count=0;
8008 nt_forms_struct *list=NULL;
8009 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8011 DEBUG(5,("spoolss_setform\n"));
8013 if (!Printer) {
8014 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8015 return WERR_BADFID;
8018 /* forms can be modified on printer of on the print server handle */
8020 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8022 if (!get_printer_snum(p,handle, &snum))
8023 return WERR_BADFID;
8025 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8026 if (!W_ERROR_IS_OK(status))
8027 goto done;
8030 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8031 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8032 status = WERR_ACCESS_DENIED;
8033 goto done;
8036 /* can't set if builtin */
8037 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8038 status = WERR_INVALID_PARAM;
8039 goto done;
8042 count = get_ntforms(&list);
8043 update_a_form(&list, form, count);
8044 write_ntforms(&list, count);
8047 * ChangeID must always be set if this is a printer
8050 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8051 status = mod_a_printer(*printer, 2);
8054 done:
8055 if ( printer )
8056 free_a_printer(&printer, 2);
8057 SAFE_FREE(list);
8059 return status;
8062 /****************************************************************************
8063 enumprintprocessors level 1.
8064 ****************************************************************************/
8066 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8068 PRINTPROCESSOR_1 *info_1=NULL;
8070 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8071 return WERR_NOMEM;
8073 (*returned) = 0x1;
8075 init_unistr(&info_1->name, "winprint");
8077 *needed += spoolss_size_printprocessor_info_1(info_1);
8079 if (!alloc_buffer_size(buffer, *needed))
8080 return WERR_INSUFFICIENT_BUFFER;
8082 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8084 SAFE_FREE(info_1);
8086 if (*needed > offered) {
8087 *returned=0;
8088 return WERR_INSUFFICIENT_BUFFER;
8091 return WERR_OK;
8094 /****************************************************************************
8095 ****************************************************************************/
8097 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8099 uint32 level = q_u->level;
8100 NEW_BUFFER *buffer = NULL;
8101 uint32 offered = q_u->offered;
8102 uint32 *needed = &r_u->needed;
8103 uint32 *returned = &r_u->returned;
8105 /* that's an [in out] buffer */
8106 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8107 buffer = r_u->buffer;
8109 DEBUG(5,("spoolss_enumprintprocessors\n"));
8112 * Enumerate the print processors ...
8114 * Just reply with "winprint", to keep NT happy
8115 * and I can use my nice printer checker.
8118 *returned=0;
8119 *needed=0;
8121 switch (level) {
8122 case 1:
8123 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8124 default:
8125 return WERR_UNKNOWN_LEVEL;
8129 /****************************************************************************
8130 enumprintprocdatatypes level 1.
8131 ****************************************************************************/
8133 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8135 PRINTPROCDATATYPE_1 *info_1=NULL;
8137 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8138 return WERR_NOMEM;
8140 (*returned) = 0x1;
8142 init_unistr(&info_1->name, "RAW");
8144 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8146 if (!alloc_buffer_size(buffer, *needed))
8147 return WERR_INSUFFICIENT_BUFFER;
8149 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8151 SAFE_FREE(info_1);
8153 if (*needed > offered) {
8154 *returned=0;
8155 return WERR_INSUFFICIENT_BUFFER;
8158 return WERR_OK;
8161 /****************************************************************************
8162 ****************************************************************************/
8164 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8166 uint32 level = q_u->level;
8167 NEW_BUFFER *buffer = NULL;
8168 uint32 offered = q_u->offered;
8169 uint32 *needed = &r_u->needed;
8170 uint32 *returned = &r_u->returned;
8172 /* that's an [in out] buffer */
8173 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8174 buffer = r_u->buffer;
8176 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8178 *returned=0;
8179 *needed=0;
8181 switch (level) {
8182 case 1:
8183 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8184 default:
8185 return WERR_UNKNOWN_LEVEL;
8189 /****************************************************************************
8190 enumprintmonitors level 1.
8191 ****************************************************************************/
8193 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8195 PRINTMONITOR_1 *info_1=NULL;
8197 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8198 return WERR_NOMEM;
8200 (*returned) = 0x1;
8202 init_unistr(&info_1->name, "Local Port");
8204 *needed += spoolss_size_printmonitor_info_1(info_1);
8206 if (!alloc_buffer_size(buffer, *needed))
8207 return WERR_INSUFFICIENT_BUFFER;
8209 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8211 SAFE_FREE(info_1);
8213 if (*needed > offered) {
8214 *returned=0;
8215 return WERR_INSUFFICIENT_BUFFER;
8218 return WERR_OK;
8221 /****************************************************************************
8222 enumprintmonitors level 2.
8223 ****************************************************************************/
8225 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8227 PRINTMONITOR_2 *info_2=NULL;
8229 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8230 return WERR_NOMEM;
8232 (*returned) = 0x1;
8234 init_unistr(&info_2->name, "Local Port");
8235 init_unistr(&info_2->environment, "Windows NT X86");
8236 init_unistr(&info_2->dll_name, "localmon.dll");
8238 *needed += spoolss_size_printmonitor_info_2(info_2);
8240 if (!alloc_buffer_size(buffer, *needed))
8241 return WERR_INSUFFICIENT_BUFFER;
8243 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8245 SAFE_FREE(info_2);
8247 if (*needed > offered) {
8248 *returned=0;
8249 return WERR_INSUFFICIENT_BUFFER;
8252 return WERR_OK;
8255 /****************************************************************************
8256 ****************************************************************************/
8258 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8260 uint32 level = q_u->level;
8261 NEW_BUFFER *buffer = NULL;
8262 uint32 offered = q_u->offered;
8263 uint32 *needed = &r_u->needed;
8264 uint32 *returned = &r_u->returned;
8266 /* that's an [in out] buffer */
8267 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8268 buffer = r_u->buffer;
8270 DEBUG(5,("spoolss_enumprintmonitors\n"));
8273 * Enumerate the print monitors ...
8275 * Just reply with "Local Port", to keep NT happy
8276 * and I can use my nice printer checker.
8279 *returned=0;
8280 *needed=0;
8282 switch (level) {
8283 case 1:
8284 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8285 case 2:
8286 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8287 default:
8288 return WERR_UNKNOWN_LEVEL;
8292 /****************************************************************************
8293 ****************************************************************************/
8295 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8297 int i=0;
8298 BOOL found=False;
8299 JOB_INFO_1 *info_1=NULL;
8301 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8303 if (info_1 == NULL) {
8304 SAFE_FREE(queue);
8305 return WERR_NOMEM;
8308 for (i=0; i<count && found==False; i++) {
8309 if (queue[i].job==(int)jobid)
8310 found=True;
8313 if (found==False) {
8314 SAFE_FREE(queue);
8315 SAFE_FREE(info_1);
8316 /* NT treats not found as bad param... yet another bad choice */
8317 return WERR_INVALID_PARAM;
8320 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8322 *needed += spoolss_size_job_info_1(info_1);
8324 if (!alloc_buffer_size(buffer, *needed)) {
8325 SAFE_FREE(info_1);
8326 return WERR_INSUFFICIENT_BUFFER;
8329 smb_io_job_info_1("", buffer, info_1, 0);
8331 SAFE_FREE(info_1);
8333 if (*needed > offered)
8334 return WERR_INSUFFICIENT_BUFFER;
8336 return WERR_OK;
8339 /****************************************************************************
8340 ****************************************************************************/
8342 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8344 int i = 0;
8345 BOOL found = False;
8346 JOB_INFO_2 *info_2;
8347 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8348 WERROR ret;
8349 DEVICEMODE *devmode = NULL;
8350 NT_DEVICEMODE *nt_devmode = NULL;
8352 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8354 ZERO_STRUCTP(info_2);
8356 if (info_2 == NULL) {
8357 ret = WERR_NOMEM;
8358 goto done;
8361 for ( i=0; i<count && found==False; i++ )
8363 if (queue[i].job == (int)jobid)
8364 found = True;
8367 if ( !found )
8369 /* NT treats not found as bad param... yet another bad
8370 choice */
8371 ret = WERR_INVALID_PARAM;
8372 goto done;
8375 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8376 if (!W_ERROR_IS_OK(ret))
8377 goto done;
8380 * if the print job does not have a DEVMODE associated with it,
8381 * just use the one for the printer. A NULL devicemode is not
8382 * a failure condition
8385 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8386 devmode = construct_dev_mode(snum);
8387 else {
8388 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8389 ZERO_STRUCTP( devmode );
8390 convert_nt_devicemode( devmode, nt_devmode );
8394 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8396 *needed += spoolss_size_job_info_2(info_2);
8398 if (!alloc_buffer_size(buffer, *needed)) {
8399 ret = WERR_INSUFFICIENT_BUFFER;
8400 goto done;
8403 smb_io_job_info_2("", buffer, info_2, 0);
8405 if (*needed > offered) {
8406 ret = WERR_INSUFFICIENT_BUFFER;
8407 goto done;
8410 ret = WERR_OK;
8412 done:
8413 /* Cleanup allocated memory */
8415 free_job_info_2(info_2); /* Also frees devmode */
8416 SAFE_FREE(info_2);
8417 free_a_printer(&ntprinter, 2);
8419 return ret;
8422 /****************************************************************************
8423 ****************************************************************************/
8425 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8427 POLICY_HND *handle = &q_u->handle;
8428 uint32 jobid = q_u->jobid;
8429 uint32 level = q_u->level;
8430 NEW_BUFFER *buffer = NULL;
8431 uint32 offered = q_u->offered;
8432 uint32 *needed = &r_u->needed;
8433 WERROR wstatus = WERR_OK;
8435 int snum;
8436 int count;
8437 print_queue_struct *queue = NULL;
8438 print_status_struct prt_status;
8440 /* that's an [in out] buffer */
8441 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8442 buffer = r_u->buffer;
8444 DEBUG(5,("spoolss_getjob\n"));
8446 *needed = 0;
8448 if (!get_printer_snum(p, handle, &snum))
8449 return WERR_BADFID;
8451 count = print_queue_status(snum, &queue, &prt_status);
8453 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8454 count, prt_status.status, prt_status.message));
8456 switch ( level ) {
8457 case 1:
8458 wstatus = getjob_level_1(queue, count, snum, jobid,
8459 buffer, offered, needed);
8460 break;
8461 case 2:
8462 wstatus = getjob_level_2(queue, count, snum, jobid,
8463 buffer, offered, needed);
8464 break;
8465 default:
8466 wstatus = WERR_UNKNOWN_LEVEL;
8467 break;
8470 SAFE_FREE(queue);
8471 return wstatus;
8474 /********************************************************************
8475 spoolss_getprinterdataex
8477 From MSDN documentation of GetPrinterDataEx: pass request
8478 to GetPrinterData if key is "PrinterDriverData".
8479 ********************************************************************/
8481 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8483 POLICY_HND *handle = &q_u->handle;
8484 uint32 in_size = q_u->size;
8485 uint32 *type = &r_u->type;
8486 uint32 *out_size = &r_u->size;
8487 uint8 **data = &r_u->data;
8488 uint32 *needed = &r_u->needed;
8489 fstring keyname, valuename;
8491 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8493 NT_PRINTER_INFO_LEVEL *printer = NULL;
8494 int snum = 0;
8495 WERROR status = WERR_OK;
8497 DEBUG(4,("_spoolss_getprinterdataex\n"));
8499 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8500 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8502 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8503 keyname, valuename));
8505 /* in case of problem, return some default values */
8507 *needed = 0;
8508 *type = 0;
8509 *out_size = in_size;
8511 if (!Printer) {
8512 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8513 status = WERR_BADFID;
8514 goto done;
8517 /* Is the handle to a printer or to the server? */
8519 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8520 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8521 status = WERR_INVALID_PARAM;
8522 goto done;
8525 if ( !get_printer_snum(p,handle, &snum) )
8526 return WERR_BADFID;
8528 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8529 if ( !W_ERROR_IS_OK(status) )
8530 goto done;
8532 /* check to see if the keyname is valid */
8533 if ( !strlen(keyname) ) {
8534 status = WERR_INVALID_PARAM;
8535 goto done;
8538 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8539 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8540 free_a_printer( &printer, 2 );
8541 status = WERR_BADFILE;
8542 goto done;
8545 /* When given a new keyname, we should just create it */
8547 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8549 if (*needed > *out_size)
8550 status = WERR_MORE_DATA;
8552 done:
8553 if ( !W_ERROR_IS_OK(status) )
8555 DEBUG(5, ("error: allocating %d\n", *out_size));
8557 /* reply this param doesn't exist */
8559 if ( *out_size )
8561 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8562 status = WERR_NOMEM;
8563 goto done;
8566 else {
8567 *data = NULL;
8571 if ( printer )
8572 free_a_printer( &printer, 2 );
8574 return status;
8577 /********************************************************************
8578 * spoolss_setprinterdataex
8579 ********************************************************************/
8581 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8583 POLICY_HND *handle = &q_u->handle;
8584 uint32 type = q_u->type;
8585 uint8 *data = q_u->data;
8586 uint32 real_len = q_u->real_len;
8588 NT_PRINTER_INFO_LEVEL *printer = NULL;
8589 int snum = 0;
8590 WERROR status = WERR_OK;
8591 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8592 fstring valuename;
8593 fstring keyname;
8594 char *oid_string;
8596 DEBUG(4,("_spoolss_setprinterdataex\n"));
8598 /* From MSDN documentation of SetPrinterDataEx: pass request to
8599 SetPrinterData if key is "PrinterDriverData" */
8601 if (!Printer) {
8602 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8603 return WERR_BADFID;
8606 if ( !get_printer_snum(p,handle, &snum) )
8607 return WERR_BADFID;
8610 * Access check : NT returns "access denied" if you make a
8611 * SetPrinterData call without the necessary privildge.
8612 * we were originally returning OK if nothing changed
8613 * which made Win2k issue **a lot** of SetPrinterData
8614 * when connecting to a printer --jerry
8617 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8619 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8620 return WERR_ACCESS_DENIED;
8623 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8624 if (!W_ERROR_IS_OK(status))
8625 return status;
8627 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8628 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8630 /* check for OID in valuename */
8632 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8634 *oid_string = '\0';
8635 oid_string++;
8638 /* save the registry data */
8640 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8642 if ( W_ERROR_IS_OK(status) )
8644 /* save the OID if one was specified */
8645 if ( oid_string ) {
8646 fstrcat( keyname, "\\" );
8647 fstrcat( keyname, SPOOL_OID_KEY );
8650 * I'm not checking the status here on purpose. Don't know
8651 * if this is right, but I'm returning the status from the
8652 * previous set_printer_dataex() call. I have no idea if
8653 * this is right. --jerry
8656 set_printer_dataex( printer, keyname, valuename,
8657 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8660 status = mod_a_printer(*printer, 2);
8663 free_a_printer(&printer, 2);
8665 return status;
8669 /********************************************************************
8670 * spoolss_deleteprinterdataex
8671 ********************************************************************/
8673 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8675 POLICY_HND *handle = &q_u->handle;
8676 UNISTR2 *value = &q_u->valuename;
8677 UNISTR2 *key = &q_u->keyname;
8679 NT_PRINTER_INFO_LEVEL *printer = NULL;
8680 int snum=0;
8681 WERROR status = WERR_OK;
8682 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8683 pstring valuename, keyname;
8685 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8687 if (!Printer) {
8688 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8689 return WERR_BADFID;
8692 if (!get_printer_snum(p, handle, &snum))
8693 return WERR_BADFID;
8695 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8696 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8697 return WERR_ACCESS_DENIED;
8700 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8701 if (!W_ERROR_IS_OK(status))
8702 return status;
8704 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8705 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8707 status = delete_printer_dataex( printer, keyname, valuename );
8709 free_a_printer(&printer, 2);
8711 return status;
8714 /********************************************************************
8715 * spoolss_enumprinterkey
8716 ********************************************************************/
8719 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8721 fstring key;
8722 fstring *keynames = NULL;
8723 uint16 *enumkeys = NULL;
8724 int num_keys;
8725 int printerkey_len;
8726 POLICY_HND *handle = &q_u->handle;
8727 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8728 NT_PRINTER_DATA *data;
8729 NT_PRINTER_INFO_LEVEL *printer = NULL;
8730 int snum = 0;
8731 WERROR status = WERR_BADFILE;
8734 DEBUG(4,("_spoolss_enumprinterkey\n"));
8736 if (!Printer) {
8737 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8738 return WERR_BADFID;
8741 if ( !get_printer_snum(p,handle, &snum) )
8742 return WERR_BADFID;
8744 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8745 if (!W_ERROR_IS_OK(status))
8746 return status;
8748 /* get the list of subkey names */
8750 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8751 data = &printer->info_2->data;
8753 num_keys = get_printer_subkeys( data, key, &keynames );
8755 if ( num_keys == -1 ) {
8756 status = WERR_BADFILE;
8757 goto done;
8760 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8762 r_u->needed = printerkey_len*2;
8764 if ( q_u->size < r_u->needed ) {
8765 status = WERR_MORE_DATA;
8766 goto done;
8769 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8770 status = WERR_NOMEM;
8771 goto done;
8774 status = WERR_OK;
8776 if ( q_u->size < r_u->needed )
8777 status = WERR_MORE_DATA;
8779 done:
8780 free_a_printer( &printer, 2 );
8781 SAFE_FREE( keynames );
8783 return status;
8786 /********************************************************************
8787 * spoolss_deleteprinterkey
8788 ********************************************************************/
8790 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8792 POLICY_HND *handle = &q_u->handle;
8793 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8794 fstring key;
8795 NT_PRINTER_INFO_LEVEL *printer = NULL;
8796 int snum=0;
8797 WERROR status;
8799 DEBUG(5,("spoolss_deleteprinterkey\n"));
8801 if (!Printer) {
8802 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8803 return WERR_BADFID;
8806 /* if keyname == NULL, return error */
8808 if ( !q_u->keyname.buffer )
8809 return WERR_INVALID_PARAM;
8811 if (!get_printer_snum(p, handle, &snum))
8812 return WERR_BADFID;
8814 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8815 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8816 return WERR_ACCESS_DENIED;
8819 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8820 if (!W_ERROR_IS_OK(status))
8821 return status;
8823 /* delete the key and all subneys */
8825 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8827 status = delete_all_printer_data( printer->info_2, key );
8829 if ( W_ERROR_IS_OK(status) )
8830 status = mod_a_printer(*printer, 2);
8832 free_a_printer( &printer, 2 );
8834 return status;
8838 /********************************************************************
8839 * spoolss_enumprinterdataex
8840 ********************************************************************/
8842 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8844 POLICY_HND *handle = &q_u->handle;
8845 uint32 in_size = q_u->size;
8846 uint32 num_entries,
8847 needed;
8848 NT_PRINTER_INFO_LEVEL *printer = NULL;
8849 PRINTER_ENUM_VALUES *enum_values = NULL;
8850 NT_PRINTER_DATA *p_data;
8851 fstring key;
8852 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8853 int snum;
8854 WERROR result;
8855 int key_index;
8856 int i;
8857 REGISTRY_VALUE *val;
8858 char *value_name;
8859 int data_len;
8862 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8864 if (!Printer) {
8865 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8866 return WERR_BADFID;
8870 * first check for a keyname of NULL or "". Win2k seems to send
8871 * this a lot and we should send back WERR_INVALID_PARAM
8872 * no need to spend time looking up the printer in this case.
8873 * --jerry
8876 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8877 if ( !strlen(key) ) {
8878 result = WERR_INVALID_PARAM;
8879 goto done;
8882 /* get the printer off of disk */
8884 if (!get_printer_snum(p,handle, &snum))
8885 return WERR_BADFID;
8887 ZERO_STRUCT(printer);
8888 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8889 if (!W_ERROR_IS_OK(result))
8890 return result;
8892 /* now look for a match on the key name */
8894 p_data = &printer->info_2->data;
8896 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8897 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8899 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8900 result = WERR_INVALID_PARAM;
8901 goto done;
8904 result = WERR_OK;
8905 needed = 0;
8907 /* allocate the memory for the array of pointers -- if necessary */
8909 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8910 if ( num_entries )
8912 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8914 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8915 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8916 result = WERR_NOMEM;
8917 goto done;
8920 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8924 * loop through all params and build the array to pass
8925 * back to the client
8928 for ( i=0; i<num_entries; i++ )
8930 /* lookup the registry value */
8932 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8933 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8935 /* copy the data */
8937 value_name = regval_name( val );
8938 init_unistr( &enum_values[i].valuename, value_name );
8939 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8940 enum_values[i].type = regval_type( val );
8942 data_len = regval_size( val );
8943 if ( data_len ) {
8944 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8946 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8947 data_len ));
8948 result = WERR_NOMEM;
8949 goto done;
8952 enum_values[i].data_len = data_len;
8954 /* keep track of the size of the array in bytes */
8956 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8959 /* housekeeping information in the reply */
8961 r_u->needed = needed;
8962 r_u->returned = num_entries;
8964 if (needed > in_size) {
8965 result = WERR_MORE_DATA;
8966 goto done;
8969 /* copy data into the reply */
8971 r_u->ctr.size = r_u->needed;
8972 r_u->ctr.size_of_array = r_u->returned;
8973 r_u->ctr.values = enum_values;
8977 done:
8978 if ( printer )
8979 free_a_printer(&printer, 2);
8981 return result;
8984 /****************************************************************************
8985 ****************************************************************************/
8987 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8989 init_unistr(&info->name, name);
8992 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8993 UNISTR2 *environment,
8994 NEW_BUFFER *buffer,
8995 uint32 offered,
8996 uint32 *needed)
8998 pstring path;
8999 pstring long_archi;
9000 pstring short_archi;
9001 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9003 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9005 if (get_short_archi(short_archi, long_archi)==False)
9006 return WERR_INVALID_ENVIRONMENT;
9008 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9009 return WERR_NOMEM;
9011 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9013 fill_printprocessordirectory_1(info, path);
9015 *needed += spoolss_size_printprocessordirectory_info_1(info);
9017 if (!alloc_buffer_size(buffer, *needed)) {
9018 safe_free(info);
9019 return WERR_INSUFFICIENT_BUFFER;
9022 smb_io_printprocessordirectory_1("", buffer, info, 0);
9024 safe_free(info);
9026 if (*needed > offered)
9027 return WERR_INSUFFICIENT_BUFFER;
9028 else
9029 return WERR_OK;
9032 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9034 uint32 level = q_u->level;
9035 NEW_BUFFER *buffer = NULL;
9036 uint32 offered = q_u->offered;
9037 uint32 *needed = &r_u->needed;
9038 WERROR result;
9040 /* that's an [in out] buffer */
9041 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9042 buffer = r_u->buffer;
9044 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9046 *needed=0;
9048 switch(level) {
9049 case 1:
9050 result = getprintprocessordirectory_level_1
9051 (&q_u->name, &q_u->environment, buffer, offered, needed);
9052 break;
9053 default:
9054 result = WERR_UNKNOWN_LEVEL;
9057 return result;
9060 #if 0
9062 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9063 SPOOL_R_REPLYOPENPRINTER *r_u)
9065 DEBUG(5,("_spoolss_replyopenprinter\n"));
9067 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9069 return WERR_OK;
9072 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9073 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9075 DEBUG(5,("_spoolss_replycloseprinter\n"));
9076 return WERR_OK;
9079 #endif