More code to store ACEs and SIDs. I have almost enough to start testing
[Samba/gebeck_regimport.git] / source3 / rpc_server / srv_spoolss_nt.c
blob026484d96d36d3e998cf631baf74bf8c207e2149
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 (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
523 SAFE_FREE(new_printer);
524 return False;
527 /* Add to the internal list. */
528 DLIST_ADD(printers_list, new_printer);
530 new_printer->notify.option=NULL;
532 if ( !(new_printer->ctx = talloc_init("Printer Entry [0x%x]", (uint32)hnd)) ) {
533 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
534 close_printer_handle(p, hnd);
535 return False;
538 if (!set_printer_hnd_printertype(new_printer, name)) {
539 close_printer_handle(p, hnd);
540 return False;
543 if (!set_printer_hnd_name(new_printer, name)) {
544 close_printer_handle(p, hnd);
545 return False;
548 new_printer->access_granted = access_granted;
550 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
552 return True;
555 /****************************************************************************
556 Allocate more memory for a BUFFER.
557 ****************************************************************************/
559 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
561 prs_struct *ps;
562 uint32 extra_space;
563 uint32 old_offset;
565 ps= &buffer->prs;
567 /* damn, I'm doing the reverse operation of prs_grow() :) */
568 if (buffer_size < prs_data_size(ps))
569 extra_space=0;
570 else
571 extra_space = buffer_size - prs_data_size(ps);
574 * save the offset and move to the end of the buffer
575 * prs_grow() checks the extra_space against the offset
577 old_offset=prs_offset(ps);
578 prs_set_offset(ps, prs_data_size(ps));
580 if (!prs_grow(ps, extra_space))
581 return False;
583 prs_set_offset(ps, old_offset);
585 buffer->string_at_end=prs_data_size(ps);
587 return True;
590 /***************************************************************************
591 check to see if the client motify handle is monitoring the notification
592 given by (notify_type, notify_field).
593 **************************************************************************/
595 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
596 uint16 notify_field)
598 return True;
601 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
602 uint16 notify_field)
604 SPOOL_NOTIFY_OPTION *option = p->notify.option;
605 uint32 i, j;
608 * Flags should always be zero when the change notify
609 * is registered by the client's spooler. A user Win32 app
610 * might use the flags though instead of the NOTIFY_OPTION_INFO
611 * --jerry
614 if (p->notify.flags)
615 return is_monitoring_event_flags(
616 p->notify.flags, notify_type, notify_field);
618 for (i = 0; i < option->count; i++) {
620 /* Check match for notify_type */
622 if (option->ctr.type[i].type != notify_type)
623 continue;
625 /* Check match for field */
627 for (j = 0; j < option->ctr.type[i].count; j++) {
628 if (option->ctr.type[i].fields[j] == notify_field) {
629 return True;
634 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
635 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
636 p->dev.handlename : p->dev.printerservername,
637 notify_type, notify_field));
639 return False;
642 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
644 static void notify_one_value(struct spoolss_notify_msg *msg,
645 SPOOL_NOTIFY_INFO_DATA *data,
646 TALLOC_CTX *mem_ctx)
648 data->notify_data.value[0] = msg->notify.value[0];
649 data->notify_data.value[1] = 0;
652 static void notify_string(struct spoolss_notify_msg *msg,
653 SPOOL_NOTIFY_INFO_DATA *data,
654 TALLOC_CTX *mem_ctx)
656 UNISTR2 unistr;
658 /* The length of the message includes the trailing \0 */
660 init_unistr2(&unistr, msg->notify.data, msg->len);
662 data->notify_data.data.length = msg->len * 2;
663 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
665 if (!data->notify_data.data.string) {
666 data->notify_data.data.length = 0;
667 return;
670 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
673 static void notify_system_time(struct spoolss_notify_msg *msg,
674 SPOOL_NOTIFY_INFO_DATA *data,
675 TALLOC_CTX *mem_ctx)
677 SYSTEMTIME systime;
678 prs_struct ps;
680 if (msg->len != sizeof(time_t)) {
681 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
682 msg->len));
683 return;
686 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
687 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
688 return;
691 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
692 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
693 return;
696 if (!spoolss_io_system_time("", &ps, 0, &systime))
697 return;
699 data->notify_data.data.length = prs_offset(&ps);
700 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
702 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
704 prs_mem_free(&ps);
707 struct notify2_message_table {
708 const char *name;
709 void (*fn)(struct spoolss_notify_msg *msg,
710 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
713 static struct notify2_message_table printer_notify_table[] = {
714 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
715 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
716 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
717 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
718 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
719 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
720 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
721 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
722 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
723 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
724 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
725 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
726 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
727 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
728 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
729 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
730 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
731 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
732 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
735 static struct notify2_message_table job_notify_table[] = {
736 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
737 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
738 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
739 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
740 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
741 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
742 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
743 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
744 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
745 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
746 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
747 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
748 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
749 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
750 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
751 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
752 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
753 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
754 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
755 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
756 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
757 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
758 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
759 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
763 /***********************************************************************
764 Allocate talloc context for container object
765 **********************************************************************/
767 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
769 if ( !ctr )
770 return;
772 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
774 return;
777 /***********************************************************************
778 release all allocated memory and zero out structure
779 **********************************************************************/
781 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
783 if ( !ctr )
784 return;
786 if ( ctr->ctx )
787 talloc_destroy(ctr->ctx);
789 ZERO_STRUCTP(ctr);
791 return;
794 /***********************************************************************
795 **********************************************************************/
797 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
799 if ( !ctr )
800 return NULL;
802 return ctr->ctx;
805 /***********************************************************************
806 **********************************************************************/
808 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
810 if ( !ctr || !ctr->msg_groups )
811 return NULL;
813 if ( idx >= ctr->num_groups )
814 return NULL;
816 return &ctr->msg_groups[idx];
820 /***********************************************************************
821 How many groups of change messages do we have ?
822 **********************************************************************/
824 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
826 if ( !ctr )
827 return 0;
829 return ctr->num_groups;
832 /***********************************************************************
833 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
834 **********************************************************************/
836 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
838 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
839 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
840 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
841 int i, new_slot;
843 if ( !ctr || !msg )
844 return 0;
846 /* loop over all groups looking for a matching printer name */
848 for ( i=0; i<ctr->num_groups; i++ ) {
849 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
850 break;
853 /* add a new group? */
855 if ( i == ctr->num_groups ) {
856 ctr->num_groups++;
858 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
859 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
860 return 0;
862 ctr->msg_groups = groups;
864 /* clear the new entry and set the printer name */
866 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
867 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
870 /* add the change messages; 'i' is the correct index now regardless */
872 msg_grp = &ctr->msg_groups[i];
874 msg_grp->num_msgs++;
876 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
877 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
878 return 0;
880 msg_grp->msgs = msg_list;
882 new_slot = msg_grp->num_msgs-1;
883 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
885 /* need to allocate own copy of data */
887 if ( msg->len != 0 )
888 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
890 return ctr->num_groups;
893 /***********************************************************************
894 Send a change notication message on all handles which have a call
895 back registered
896 **********************************************************************/
898 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
900 Printer_entry *p;
901 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
902 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
903 SPOOLSS_NOTIFY_MSG *messages;
904 int sending_msg_count;
906 if ( !msg_group ) {
907 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
908 return;
911 messages = msg_group->msgs;
913 if ( !messages ) {
914 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
915 return;
918 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
920 /* loop over all printers */
922 for (p = printers_list; p; p = p->next) {
923 SPOOL_NOTIFY_INFO_DATA *data;
924 uint32 data_len = 0;
925 uint32 id;
926 int i, event_index;
928 /* Is there notification on this handle? */
930 if ( !p->notify.client_connected )
931 continue;
933 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
935 /* For this printer? Print servers always receive
936 notifications. */
938 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
939 ( !strequal(msg_group->printername, p->dev.handlename) ) )
940 continue;
942 DEBUG(10,("Our printer\n"));
944 /* allocate the max entries possible */
946 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
947 ZERO_STRUCTP(data);
949 event_index = 0;
951 /* build the array of change notifications */
953 sending_msg_count = 0;
955 for ( i=0; i<msg_group->num_msgs; i++ ) {
956 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
958 /* Are we monitoring this event? */
960 if (!is_monitoring_event(p, msg->type, msg->field))
961 continue;
963 sending_msg_count++;
966 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
967 msg->type, msg->field, p->dev.handlename));
970 * if the is a printer notification handle and not a job notification
971 * type, then set the id to 0. Other wise just use what was specified
972 * in the message.
974 * When registering change notification on a print server handle
975 * we always need to send back the id (snum) matching the printer
976 * for which the change took place. For change notify registered
977 * on a printer handle, this does not matter and the id should be 0.
979 * --jerry
982 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
983 id = 0;
984 else
985 id = msg->id;
988 /* Convert unix jobid to smb jobid */
990 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
991 id = sysjob_to_jobid(msg->id);
993 if (id == -1) {
994 DEBUG(3, ("no such unix jobid %d\n", msg->id));
995 goto done;
999 construct_info_data( &data[data_len], msg->type, msg->field, id );
1001 switch(msg->type) {
1002 case PRINTER_NOTIFY_TYPE:
1003 if ( printer_notify_table[msg->field].fn )
1004 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1005 break;
1007 case JOB_NOTIFY_TYPE:
1008 if ( job_notify_table[msg->field].fn )
1009 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1010 break;
1012 default:
1013 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1014 goto done;
1017 data_len++;
1020 if ( sending_msg_count ) {
1021 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1022 data_len, data, p->notify.change, 0 );
1026 done:
1027 DEBUG(8,("send_notify2_changes: Exit...\n"));
1028 return;
1031 /***********************************************************************
1032 **********************************************************************/
1034 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1037 uint32 tv_sec, tv_usec;
1038 size_t offset = 0;
1040 /* Unpack message */
1042 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1043 msg->printer);
1045 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1046 &tv_sec, &tv_usec,
1047 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1049 if (msg->len == 0)
1050 tdb_unpack((char *)buf + offset, len - offset, "dd",
1051 &msg->notify.value[0], &msg->notify.value[1]);
1052 else
1053 tdb_unpack((char *)buf + offset, len - offset, "B",
1054 &msg->len, &msg->notify.data);
1056 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1057 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1059 tv->tv_sec = tv_sec;
1060 tv->tv_usec = tv_usec;
1062 if (msg->len == 0)
1063 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1064 msg->notify.value[1]));
1065 else
1066 dump_data(3, msg->notify.data, msg->len);
1068 return True;
1071 /* ENUMJOB last timestamp list. */
1072 struct ejts_list {
1073 struct ejts_list *next, *prev;
1074 char *printer_name;
1075 struct timeval tv;
1078 static struct ejts_list *ejts_head;
1080 static struct ejts_list *find_enumjobs_timestamp(const char *printer_name)
1082 struct ejts_list *ejtsl;
1084 for( ejtsl = ejts_head; ejtsl; ejtsl = ejtsl->next)
1085 if (strequal(ejtsl->printer_name, printer_name))
1086 return ejtsl;
1087 return NULL;
1090 static void set_enumjobs_timestamp(int snum)
1092 const char *printer_name = lp_const_servicename(snum);
1093 struct ejts_list *ejtsl = find_enumjobs_timestamp(printer_name);
1095 if (!ejtsl) {
1096 ejtsl = (struct ejts_list *)malloc(sizeof(struct ejts_list));
1097 if (!ejtsl)
1098 return;
1099 ejtsl->printer_name = strdup(printer_name);
1100 if (!ejtsl->printer_name) {
1101 SAFE_FREE(ejtsl);
1102 return;
1104 DLIST_ADD(ejts_head, ejtsl);
1107 gettimeofday(&ejtsl->tv, NULL);
1110 static int timeval_diff(struct timeval *tv1, struct timeval *tv2)
1112 if (tv1->tv_sec > tv2->tv_sec)
1113 return 1;
1114 if (tv1->tv_sec < tv2->tv_sec)
1115 return -1;
1116 if (tv1->tv_usec > tv2->tv_usec)
1117 return 1;
1118 if (tv1->tv_usec < tv2->tv_usec)
1119 return -1;
1120 return 0;
1123 /********************************************************************
1124 Receive a notify2 message list
1125 ********************************************************************/
1127 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1129 size_t msg_count, i;
1130 char *buf = (char *)msg;
1131 char *msg_ptr;
1132 size_t msg_len;
1133 SPOOLSS_NOTIFY_MSG notify;
1134 SPOOLSS_NOTIFY_MSG_CTR messages;
1135 int num_groups;
1137 if (len < 4) {
1138 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1139 return;
1142 msg_count = IVAL(buf, 0);
1143 msg_ptr = buf + 4;
1145 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1147 if (msg_count == 0) {
1148 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1149 return;
1152 /* initialize the container */
1154 ZERO_STRUCT( messages );
1155 notify_msg_ctr_init( &messages );
1158 * build message groups for each printer identified
1159 * in a change_notify msg. Remember that a PCN message
1160 * includes the handle returned for the srv_spoolss_replyopenprinter()
1161 * call. Therefore messages are grouped according to printer handle.
1164 for ( i=0; i<msg_count; i++ ) {
1165 struct timeval msg_tv;
1167 if (msg_ptr + 4 - buf > len) {
1168 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1169 return;
1172 msg_len = IVAL(msg_ptr,0);
1173 msg_ptr += 4;
1175 if (msg_ptr + msg_len - buf > len) {
1176 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1177 return;
1180 /* unpack messages */
1182 ZERO_STRUCT( notify );
1183 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1184 msg_ptr += msg_len;
1186 /* See if it is still relevent. */
1187 if (notify.type == JOB_NOTIFY_TYPE) {
1188 BOOL status_is_deleting = False;
1190 if (notify.field == JOB_NOTIFY_STATUS && (notify.notify.value[0] & (JOB_STATUS_DELETING|JOB_STATUS_DELETED)))
1191 status_is_deleting = True;
1193 if (!status_is_deleting) {
1194 struct ejts_list *ejtsl = find_enumjobs_timestamp(notify.printer);
1196 if (ejtsl && (timeval_diff(&ejtsl->tv, &msg_tv) > 0)) {
1198 DEBUG(10, ("receive_notify2_message_list: enumjobs ts = %u, %u, msg ts = %u, %u discarding\n",
1199 (unsigned int)ejtsl->tv.tv_sec, (unsigned int)ejtsl->tv.tv_usec,
1200 (unsigned int)msg_tv.tv_sec, (unsigned int)msg_tv.tv_usec ));
1202 /* Message no longer relevent. Ignore it. */
1203 if ( notify.len != 0 )
1204 SAFE_FREE( notify.notify.data );
1205 continue;
1209 /* add to correct list in container */
1211 notify_msg_ctr_addmsg( &messages, &notify );
1213 /* free memory that might have been allocated by notify2_unpack_msg() */
1215 if ( notify.len != 0 )
1216 SAFE_FREE( notify.notify.data );
1219 /* process each group of messages */
1221 num_groups = notify_msg_ctr_numgroups( &messages );
1222 for ( i=0; i<num_groups; i++ )
1223 send_notify2_changes( &messages, i );
1226 /* cleanup */
1228 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1230 notify_msg_ctr_destroy( &messages );
1232 return;
1235 /********************************************************************
1236 Send a message to ourself about new driver being installed
1237 so we can upgrade the information for each printer bound to this
1238 driver
1239 ********************************************************************/
1241 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1243 int len = strlen(drivername);
1245 if (!len)
1246 return False;
1248 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1249 drivername));
1251 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1253 return True;
1256 /**********************************************************************
1257 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1258 over all printers, upgrading ones as necessary
1259 **********************************************************************/
1261 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1263 fstring drivername;
1264 int snum;
1265 int n_services = lp_numservices();
1267 len = MIN(len,sizeof(drivername)-1);
1268 strncpy(drivername, buf, len);
1270 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1272 /* Iterate the printer list */
1274 for (snum=0; snum<n_services; snum++)
1276 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1278 WERROR result;
1279 NT_PRINTER_INFO_LEVEL *printer = NULL;
1281 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1282 if (!W_ERROR_IS_OK(result))
1283 continue;
1285 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1287 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1289 /* all we care about currently is the change_id */
1291 result = mod_a_printer(*printer, 2);
1292 if (!W_ERROR_IS_OK(result)) {
1293 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1294 dos_errstr(result)));
1298 free_a_printer(&printer, 2);
1302 /* all done */
1305 /********************************************************************
1306 Update the cache for all printq's with a registered client
1307 connection
1308 ********************************************************************/
1310 void update_monitored_printq_cache( void )
1312 Printer_entry *printer = printers_list;
1313 int snum;
1315 /* loop through all printers and update the cache where
1316 client_connected == True */
1317 while ( printer )
1319 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1320 && printer->notify.client_connected )
1322 snum = print_queue_snum(printer->dev.handlename);
1323 print_queue_status( snum, NULL, NULL );
1326 printer = printer->next;
1329 return;
1331 /********************************************************************
1332 Send a message to ourself about new driver being installed
1333 so we can upgrade the information for each printer bound to this
1334 driver
1335 ********************************************************************/
1337 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1339 int len = strlen(drivername);
1341 if (!len)
1342 return False;
1344 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1345 drivername));
1347 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1349 return True;
1352 /**********************************************************************
1353 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1354 over all printers, resetting printer data as neessary
1355 **********************************************************************/
1357 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1359 fstring drivername;
1360 int snum;
1361 int n_services = lp_numservices();
1363 len = MIN( len, sizeof(drivername)-1 );
1364 strncpy( drivername, buf, len );
1366 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1368 /* Iterate the printer list */
1370 for ( snum=0; snum<n_services; snum++ )
1372 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1374 WERROR result;
1375 NT_PRINTER_INFO_LEVEL *printer = NULL;
1377 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1378 if ( !W_ERROR_IS_OK(result) )
1379 continue;
1382 * if the printer is bound to the driver,
1383 * then reset to the new driver initdata
1386 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1388 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1390 if ( !set_driver_init(printer, 2) ) {
1391 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1392 printer->info_2->printername, printer->info_2->drivername));
1395 result = mod_a_printer( *printer, 2 );
1396 if ( !W_ERROR_IS_OK(result) ) {
1397 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1398 get_dos_error_msg(result)));
1402 free_a_printer( &printer, 2 );
1406 /* all done */
1408 return;
1411 /********************************************************************
1412 Copy routines used by convert_to_openprinterex()
1413 *******************************************************************/
1415 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1417 DEVICEMODE *d;
1418 int len;
1420 if (!devmode)
1421 return NULL;
1423 DEBUG (8,("dup_devmode\n"));
1425 /* bulk copy first */
1427 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1428 if (!d)
1429 return NULL;
1431 /* dup the pointer members separately */
1433 len = unistrlen(devmode->devicename.buffer);
1434 if (len != -1) {
1435 d->devicename.buffer = talloc(ctx, len*2);
1436 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1437 return NULL;
1441 len = unistrlen(devmode->formname.buffer);
1442 if (len != -1) {
1443 d->devicename.buffer = talloc(ctx, len*2);
1444 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1445 return NULL;
1448 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1450 return d;
1453 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1455 if (!new_ctr || !ctr)
1456 return;
1458 DEBUG(8,("copy_devmode_ctr\n"));
1460 new_ctr->size = ctr->size;
1461 new_ctr->devmode_ptr = ctr->devmode_ptr;
1463 if(ctr->devmode_ptr)
1464 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1467 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1469 if (!new_def || !def)
1470 return;
1472 DEBUG(8,("copy_printer_defaults\n"));
1474 new_def->datatype_ptr = def->datatype_ptr;
1476 if (def->datatype_ptr)
1477 copy_unistr2(&new_def->datatype, &def->datatype);
1479 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1481 new_def->access_required = def->access_required;
1484 /********************************************************************
1485 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1486 * SPOOL_Q_OPEN_PRINTER_EX structure
1487 ********************************************************************/
1489 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1491 if (!q_u_ex || !q_u)
1492 return;
1494 DEBUG(8,("convert_to_openprinterex\n"));
1496 q_u_ex->printername_ptr = q_u->printername_ptr;
1498 if (q_u->printername_ptr)
1499 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1501 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1504 /********************************************************************
1505 * spoolss_open_printer
1507 * called from the spoolss dispatcher
1508 ********************************************************************/
1510 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1512 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1513 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1515 if (!q_u || !r_u)
1516 return WERR_NOMEM;
1518 ZERO_STRUCT(q_u_ex);
1519 ZERO_STRUCT(r_u_ex);
1521 /* convert the OpenPrinter() call to OpenPrinterEx() */
1523 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1525 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1527 /* convert back to OpenPrinter() */
1529 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1531 return r_u->status;
1534 /********************************************************************
1535 * spoolss_open_printer
1537 * If the openprinterex rpc call contains a devmode,
1538 * it's a per-user one. This per-user devmode is derivated
1539 * from the global devmode. Openprinterex() contains a per-user
1540 * devmode for when you do EMF printing and spooling.
1541 * In the EMF case, the NT workstation is only doing half the job
1542 * of rendering the page. The other half is done by running the printer
1543 * driver on the server.
1544 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1545 * The EMF file only contains what is to be printed on the page.
1546 * So in order for the server to know how to print, the NT client sends
1547 * a devicemode attached to the openprinterex call.
1548 * But this devicemode is short lived, it's only valid for the current print job.
1550 * If Samba would have supported EMF spooling, this devicemode would
1551 * have been attached to the handle, to sent it to the driver to correctly
1552 * rasterize the EMF file.
1554 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1555 * we just act as a pass-thru between windows and the printer.
1557 * In order to know that Samba supports only RAW spooling, NT has to call
1558 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1559 * and until NT sends a RAW job, we refuse it.
1561 * But to call getprinter() or startdoc(), you first need a valid handle,
1562 * and to get an handle you have to call openprintex(). Hence why you have
1563 * a devicemode in the openprinterex() call.
1566 * Differences between NT4 and NT 2000.
1567 * NT4:
1568 * ---
1569 * On NT4, you only have a global devicemode. This global devicemode can be changed
1570 * by the administrator (or by a user with enough privs). Everytime a user
1571 * wants to print, the devicemode is resetted to the default. In Word, everytime
1572 * you print, the printer's characteristics are always reset to the global devicemode.
1574 * NT 2000:
1575 * -------
1576 * In W2K, there is the notion of per-user devicemode. The first time you use
1577 * a printer, a per-user devicemode is build from the global devicemode.
1578 * If you change your per-user devicemode, it is saved in the registry, under the
1579 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1580 * printer preferences available.
1582 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1583 * on the General Tab of the printer properties windows.
1585 * To change the global devicemode: it's the "Printing Defaults..." button
1586 * on the Advanced Tab of the printer properties window.
1588 * JFM.
1589 ********************************************************************/
1591 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1593 UNISTR2 *printername = NULL;
1594 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1595 POLICY_HND *handle = &r_u->handle;
1597 fstring name;
1598 int snum;
1599 struct current_user user;
1600 Printer_entry *Printer=NULL;
1602 if (q_u->printername_ptr != 0)
1603 printername = &q_u->printername;
1605 if (printername == NULL)
1606 return WERR_INVALID_PRINTER_NAME;
1608 /* some sanity check because you can open a printer or a print server */
1609 /* aka: \\server\printer or \\server */
1610 unistr2_to_ascii(name, printername, sizeof(name)-1);
1612 DEBUGADD(3,("checking name: %s\n",name));
1614 if (!open_printer_hnd(p, handle, name, 0))
1615 return WERR_INVALID_PRINTER_NAME;
1617 Printer=find_printer_index_by_hnd(p, handle);
1618 if (!Printer) {
1619 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1620 Can't find printer handle we created for printer %s\n", name ));
1621 close_printer_handle(p,handle);
1622 return WERR_INVALID_PRINTER_NAME;
1625 get_current_user(&user, p);
1628 * First case: the user is opening the print server:
1630 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1631 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1633 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1634 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1635 * or if the user is listed in the smb.conf printer admin parameter.
1637 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1638 * client view printer folder, but does not show the MSAPW.
1640 * Note: this test needs code to check access rights here too. Jeremy
1641 * could you look at this?
1643 * Second case: the user is opening a printer:
1644 * NT doesn't let us connect to a printer if the connecting user
1645 * doesn't have print permission.
1648 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1650 /* Printserver handles use global struct... */
1652 snum = -1;
1654 /* Map standard access rights to object specific access rights */
1656 se_map_standard(&printer_default->access_required,
1657 &printserver_std_mapping);
1659 /* Deny any object specific bits that don't apply to print
1660 servers (i.e printer and job specific bits) */
1662 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1664 if (printer_default->access_required &
1665 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1666 DEBUG(3, ("access DENIED for non-printserver bits"));
1667 close_printer_handle(p, handle);
1668 return WERR_ACCESS_DENIED;
1671 /* Allow admin access */
1673 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1675 if (!lp_ms_add_printer_wizard()) {
1676 close_printer_handle(p, handle);
1677 return WERR_ACCESS_DENIED;
1680 /* if the user is not root and not a printer admin, then fail */
1682 if ( user.uid != 0
1683 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1685 close_printer_handle(p, handle);
1686 return WERR_ACCESS_DENIED;
1689 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1691 else
1693 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1696 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1697 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1699 /* We fall through to return WERR_OK */
1702 else
1704 /* NT doesn't let us connect to a printer if the connecting user
1705 doesn't have print permission. */
1707 if (!get_printer_snum(p, handle, &snum)) {
1708 close_printer_handle(p, handle);
1709 return WERR_BADFID;
1712 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1714 /* map an empty access mask to the minimum access mask */
1715 if (printer_default->access_required == 0x0)
1716 printer_default->access_required = PRINTER_ACCESS_USE;
1719 * If we are not serving the printer driver for this printer,
1720 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1721 * will keep NT clients happy --jerry
1724 if (lp_use_client_driver(snum)
1725 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1727 printer_default->access_required = PRINTER_ACCESS_USE;
1730 /* check smb.conf parameters and the the sec_desc */
1732 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1733 DEBUG(3, ("access DENIED for printer open\n"));
1734 close_printer_handle(p, handle);
1735 return WERR_ACCESS_DENIED;
1738 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1739 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1740 close_printer_handle(p, handle);
1741 return WERR_ACCESS_DENIED;
1744 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1745 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1746 else
1747 printer_default->access_required = PRINTER_ACCESS_USE;
1749 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1750 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1754 Printer->access_granted = printer_default->access_required;
1757 * If the client sent a devmode in the OpenPrinter() call, then
1758 * save it here in case we get a job submission on this handle
1761 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1762 && q_u->printer_default.devmode_cont.devmode_ptr )
1764 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1765 &Printer->nt_devmode );
1768 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1769 optimization in Windows 2000 clients --jerry */
1771 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1772 && (RA_WIN2K == get_remote_arch()) )
1774 usleep( 500000 );
1777 return WERR_OK;
1780 /****************************************************************************
1781 ****************************************************************************/
1783 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1784 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1786 BOOL ret = True;
1788 switch (level) {
1789 case 2:
1790 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1791 break;
1792 default:
1793 break;
1796 return ret;
1799 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1800 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1802 BOOL result = True;
1804 switch (level) {
1805 case 3:
1806 printer->info_3=NULL;
1807 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1808 result = False;
1809 break;
1810 case 6:
1811 printer->info_6=NULL;
1812 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1813 result = False;
1814 break;
1815 default:
1816 break;
1819 return result;
1822 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1823 NT_DEVICEMODE **pp_nt_devmode)
1825 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1828 * Ensure nt_devmode is a valid pointer
1829 * as we will be overwriting it.
1832 if (nt_devmode == NULL) {
1833 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1834 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1835 return False;
1838 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1839 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1841 nt_devmode->specversion=devmode->specversion;
1842 nt_devmode->driverversion=devmode->driverversion;
1843 nt_devmode->size=devmode->size;
1844 nt_devmode->fields=devmode->fields;
1845 nt_devmode->orientation=devmode->orientation;
1846 nt_devmode->papersize=devmode->papersize;
1847 nt_devmode->paperlength=devmode->paperlength;
1848 nt_devmode->paperwidth=devmode->paperwidth;
1849 nt_devmode->scale=devmode->scale;
1850 nt_devmode->copies=devmode->copies;
1851 nt_devmode->defaultsource=devmode->defaultsource;
1852 nt_devmode->printquality=devmode->printquality;
1853 nt_devmode->color=devmode->color;
1854 nt_devmode->duplex=devmode->duplex;
1855 nt_devmode->yresolution=devmode->yresolution;
1856 nt_devmode->ttoption=devmode->ttoption;
1857 nt_devmode->collate=devmode->collate;
1859 nt_devmode->logpixels=devmode->logpixels;
1860 nt_devmode->bitsperpel=devmode->bitsperpel;
1861 nt_devmode->pelswidth=devmode->pelswidth;
1862 nt_devmode->pelsheight=devmode->pelsheight;
1863 nt_devmode->displayflags=devmode->displayflags;
1864 nt_devmode->displayfrequency=devmode->displayfrequency;
1865 nt_devmode->icmmethod=devmode->icmmethod;
1866 nt_devmode->icmintent=devmode->icmintent;
1867 nt_devmode->mediatype=devmode->mediatype;
1868 nt_devmode->dithertype=devmode->dithertype;
1869 nt_devmode->reserved1=devmode->reserved1;
1870 nt_devmode->reserved2=devmode->reserved2;
1871 nt_devmode->panningwidth=devmode->panningwidth;
1872 nt_devmode->panningheight=devmode->panningheight;
1875 * Only change private and driverextra if the incoming devmode
1876 * has a new one. JRA.
1879 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1880 SAFE_FREE(nt_devmode->private);
1881 nt_devmode->driverextra=devmode->driverextra;
1882 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1883 return False;
1884 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1887 *pp_nt_devmode = nt_devmode;
1889 return True;
1892 /********************************************************************
1893 * _spoolss_enddocprinter_internal.
1894 ********************************************************************/
1896 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1898 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1899 int snum;
1901 if (!Printer) {
1902 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1903 return WERR_BADFID;
1906 if (!get_printer_snum(p, handle, &snum))
1907 return WERR_BADFID;
1909 Printer->document_started=False;
1910 print_job_end(snum, Printer->jobid,True);
1911 /* error codes unhandled so far ... */
1913 return WERR_OK;
1916 /********************************************************************
1917 * api_spoolss_closeprinter
1918 ********************************************************************/
1920 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1922 POLICY_HND *handle = &q_u->handle;
1924 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1926 if (Printer && Printer->document_started)
1927 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1929 if (!close_printer_handle(p, handle))
1930 return WERR_BADFID;
1932 /* clear the returned printer handle. Observed behavior
1933 from Win2k server. Don't think this really matters.
1934 Previous code just copied the value of the closed
1935 handle. --jerry */
1937 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1939 return WERR_OK;
1942 /********************************************************************
1943 * api_spoolss_deleteprinter
1945 ********************************************************************/
1947 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1949 POLICY_HND *handle = &q_u->handle;
1950 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1951 WERROR result;
1953 if (Printer && Printer->document_started)
1954 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1956 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1958 result = delete_printer_handle(p, handle);
1960 update_c_setprinter(False);
1962 return result;
1965 /*******************************************************************
1966 * static function to lookup the version id corresponding to an
1967 * long architecture string
1968 ******************************************************************/
1970 static int get_version_id (char * arch)
1972 int i;
1973 struct table_node archi_table[]= {
1975 {"Windows 4.0", "WIN40", 0 },
1976 {"Windows NT x86", "W32X86", 2 },
1977 {"Windows NT R4000", "W32MIPS", 2 },
1978 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1979 {"Windows NT PowerPC", "W32PPC", 2 },
1980 {NULL, "", -1 }
1983 for (i=0; archi_table[i].long_archi != NULL; i++)
1985 if (strcmp(arch, archi_table[i].long_archi) == 0)
1986 return (archi_table[i].version);
1989 return -1;
1992 /********************************************************************
1993 * _spoolss_deleteprinterdriver
1994 ********************************************************************/
1996 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1998 fstring driver;
1999 fstring arch;
2000 NT_PRINTER_DRIVER_INFO_LEVEL info;
2001 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2002 int version;
2003 struct current_user user;
2004 WERROR status;
2005 WERROR status_win2k = WERR_ACCESS_DENIED;
2007 get_current_user(&user, p);
2009 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2010 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2012 /* check that we have a valid driver name first */
2014 if ((version=get_version_id(arch)) == -1)
2015 return WERR_INVALID_ENVIRONMENT;
2017 ZERO_STRUCT(info);
2018 ZERO_STRUCT(info_win2k);
2020 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2022 /* try for Win2k driver if "Windows NT x86" */
2024 if ( version == 2 ) {
2025 version = 3;
2026 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2027 status = WERR_UNKNOWN_PRINTER_DRIVER;
2028 goto done;
2031 /* otherwise it was a failure */
2032 else {
2033 status = WERR_UNKNOWN_PRINTER_DRIVER;
2034 goto done;
2039 if (printer_driver_in_use(info.info_3)) {
2040 status = WERR_PRINTER_DRIVER_IN_USE;
2041 goto done;
2044 if ( version == 2 )
2046 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2048 /* if we get to here, we now have 2 driver info structures to remove */
2049 /* remove the Win2k driver first*/
2051 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2052 free_a_printer_driver( info_win2k, 3 );
2054 /* this should not have failed---if it did, report to client */
2055 if ( !W_ERROR_IS_OK(status_win2k) )
2056 goto done;
2060 status = delete_printer_driver(info.info_3, &user, version, False);
2062 /* if at least one of the deletes succeeded return OK */
2064 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2065 status = WERR_OK;
2067 done:
2068 free_a_printer_driver( info, 3 );
2070 return status;
2073 /********************************************************************
2074 * spoolss_deleteprinterdriverex
2075 ********************************************************************/
2077 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2079 fstring driver;
2080 fstring arch;
2081 NT_PRINTER_DRIVER_INFO_LEVEL info;
2082 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2083 int version;
2084 uint32 flags = q_u->delete_flags;
2085 BOOL delete_files;
2086 struct current_user user;
2087 WERROR status;
2088 WERROR status_win2k = WERR_ACCESS_DENIED;
2090 get_current_user(&user, p);
2092 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2093 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2095 /* check that we have a valid driver name first */
2096 if ((version=get_version_id(arch)) == -1) {
2097 /* this is what NT returns */
2098 return WERR_INVALID_ENVIRONMENT;
2101 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2102 version = q_u->version;
2104 ZERO_STRUCT(info);
2105 ZERO_STRUCT(info_win2k);
2107 status = get_a_printer_driver(&info, 3, driver, arch, version);
2109 if ( !W_ERROR_IS_OK(status) )
2112 * if the client asked for a specific version,
2113 * or this is something other than Windows NT x86,
2114 * then we've failed
2117 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2118 goto done;
2120 /* try for Win2k driver if "Windows NT x86" */
2122 version = 3;
2123 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2124 status = WERR_UNKNOWN_PRINTER_DRIVER;
2125 goto done;
2129 if ( printer_driver_in_use(info.info_3) ) {
2130 status = WERR_PRINTER_DRIVER_IN_USE;
2131 goto done;
2135 * we have a couple of cases to consider.
2136 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2137 * then the delete should fail if **any** files overlap with
2138 * other drivers
2139 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2140 * non-overlapping files
2141 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2142 * is set, the do not delete any files
2143 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2146 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2148 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2150 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2151 /* no idea of the correct error here */
2152 status = WERR_ACCESS_DENIED;
2153 goto done;
2157 /* also check for W32X86/3 if necessary; maybe we already have? */
2159 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2160 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2163 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2164 /* no idea of the correct error here */
2165 free_a_printer_driver( info_win2k, 3 );
2166 status = WERR_ACCESS_DENIED;
2167 goto done;
2170 /* if we get to here, we now have 2 driver info structures to remove */
2171 /* remove the Win2k driver first*/
2173 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2174 free_a_printer_driver( info_win2k, 3 );
2176 /* this should not have failed---if it did, report to client */
2178 if ( !W_ERROR_IS_OK(status_win2k) )
2179 goto done;
2183 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2185 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2186 status = WERR_OK;
2187 done:
2188 free_a_printer_driver( info, 3 );
2190 return status;
2194 /****************************************************************************
2195 Internal routine for retreiving printerdata
2196 ***************************************************************************/
2198 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2199 const char *key, const char *value, uint32 *type, uint8 **data,
2200 uint32 *needed, uint32 in_size )
2202 REGISTRY_VALUE *val;
2203 int size, data_len;
2205 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2206 return WERR_BADFILE;
2208 *type = regval_type( val );
2210 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2212 size = regval_size( val );
2214 /* copy the min(in_size, len) */
2216 if ( in_size ) {
2217 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2219 /* special case for 0 length values */
2220 if ( data_len ) {
2221 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2222 return WERR_NOMEM;
2224 else {
2225 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2226 return WERR_NOMEM;
2229 else
2230 *data = NULL;
2232 *needed = size;
2234 DEBUG(5,("get_printer_dataex: copy done\n"));
2236 return WERR_OK;
2239 /****************************************************************************
2240 Internal routine for removing printerdata
2241 ***************************************************************************/
2243 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2245 return delete_printer_data( printer->info_2, key, value );
2248 /****************************************************************************
2249 Internal routine for storing printerdata
2250 ***************************************************************************/
2252 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2253 uint32 type, uint8 *data, int real_len )
2255 delete_printer_data( printer->info_2, key, value );
2257 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2260 /********************************************************************
2261 GetPrinterData on a printer server Handle.
2262 ********************************************************************/
2264 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2266 int i;
2268 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2270 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2271 *type = 0x4;
2272 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2273 return WERR_NOMEM;
2274 *needed = 0x4;
2275 return WERR_OK;
2278 if (!StrCaseCmp(value, "BeepEnabled")) {
2279 *type = 0x4;
2280 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2281 return WERR_NOMEM;
2282 SIVAL(*data, 0, 0x00);
2283 *needed = 0x4;
2284 return WERR_OK;
2287 if (!StrCaseCmp(value, "EventLog")) {
2288 *type = 0x4;
2289 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2290 return WERR_NOMEM;
2291 /* formally was 0x1b */
2292 SIVAL(*data, 0, 0x0);
2293 *needed = 0x4;
2294 return WERR_OK;
2297 if (!StrCaseCmp(value, "NetPopup")) {
2298 *type = 0x4;
2299 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2300 return WERR_NOMEM;
2301 SIVAL(*data, 0, 0x00);
2302 *needed = 0x4;
2303 return WERR_OK;
2306 if (!StrCaseCmp(value, "MajorVersion")) {
2307 *type = 0x4;
2308 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2309 return WERR_NOMEM;
2311 /* Windows NT 4.0 seems to not allow uploading of drivers
2312 to a server that reports 0x3 as the MajorVersion.
2313 need to investigate more how Win2k gets around this .
2314 -- jerry */
2316 if ( RA_WINNT == get_remote_arch() )
2317 SIVAL(*data, 0, 2);
2318 else
2319 SIVAL(*data, 0, 3);
2321 *needed = 0x4;
2322 return WERR_OK;
2325 if (!StrCaseCmp(value, "MinorVersion")) {
2326 *type = 0x4;
2327 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2328 return WERR_NOMEM;
2329 SIVAL(*data, 0, 0);
2330 *needed = 0x4;
2331 return WERR_OK;
2334 #if 0 /* JERRY */
2335 /* REG_BINARY
2336 * uint32 size = 0x114
2337 * uint32 major = 5
2338 * uint32 minor = [0|1]
2339 * uint32 build = [2195|2600]
2340 * extra unicode string = e.g. "Service Pack 3"
2342 if (!StrCaseCmp(value, "OSVersion")) {
2343 *type = 0x4;
2344 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2345 return WERR_NOMEM;
2346 SIVAL(*data, 0, 2);
2347 *needed = 0x4;
2348 return WERR_OK;
2350 #endif
2352 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2353 fstring string;
2355 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2356 *type = 0x1;
2357 *needed = 2*(strlen(string)+1);
2358 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2359 return WERR_NOMEM;
2360 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2362 /* it's done by hand ready to go on the wire */
2363 for (i=0; i<strlen(string); i++) {
2364 (*data)[2*i]=string[i];
2365 (*data)[2*i+1]='\0';
2367 return WERR_OK;
2370 if (!StrCaseCmp(value, "Architecture")) {
2371 pstring string="Windows NT x86";
2372 *type = 0x1;
2373 *needed = 2*(strlen(string)+1);
2374 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2375 return WERR_NOMEM;
2376 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2377 for (i=0; i<strlen(string); i++) {
2378 (*data)[2*i]=string[i];
2379 (*data)[2*i+1]='\0';
2381 return WERR_OK;
2384 if (!StrCaseCmp(value, "DsPresent")) {
2385 *type = 0x4;
2386 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2387 return WERR_NOMEM;
2388 SIVAL(*data, 0, 0x01);
2389 *needed = 0x4;
2390 return WERR_OK;
2393 if (!StrCaseCmp(value, "DNSMachineName")) {
2394 pstring hostname;
2396 if (!get_myfullname(hostname))
2397 return WERR_BADFILE;
2398 *type = 0x1;
2399 *needed = 2*(strlen(hostname)+1);
2400 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2401 return WERR_NOMEM;
2402 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2403 for (i=0; i<strlen(hostname); i++) {
2404 (*data)[2*i]=hostname[i];
2405 (*data)[2*i+1]='\0';
2407 return WERR_OK;
2411 return WERR_BADFILE;
2414 /********************************************************************
2415 * spoolss_getprinterdata
2416 ********************************************************************/
2418 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2420 POLICY_HND *handle = &q_u->handle;
2421 UNISTR2 *valuename = &q_u->valuename;
2422 uint32 in_size = q_u->size;
2423 uint32 *type = &r_u->type;
2424 uint32 *out_size = &r_u->size;
2425 uint8 **data = &r_u->data;
2426 uint32 *needed = &r_u->needed;
2427 WERROR status;
2428 fstring value;
2429 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2430 NT_PRINTER_INFO_LEVEL *printer = NULL;
2431 int snum = 0;
2434 * Reminder: when it's a string, the length is in BYTES
2435 * even if UNICODE is negociated.
2437 * JFM, 4/19/1999
2440 *out_size = in_size;
2442 /* in case of problem, return some default values */
2444 *needed = 0;
2445 *type = 0;
2447 DEBUG(4,("_spoolss_getprinterdata\n"));
2449 if ( !Printer ) {
2450 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2451 status = WERR_BADFID;
2452 goto done;
2455 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2457 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2458 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2459 else
2461 if ( !get_printer_snum(p,handle, &snum) ) {
2462 status = WERR_BADFID;
2463 goto done;
2466 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2467 if ( !W_ERROR_IS_OK(status) )
2468 goto done;
2470 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2472 if ( strequal(value, "ChangeId") ) {
2473 *type = REG_DWORD;
2474 *needed = sizeof(uint32);
2475 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2476 status = WERR_NOMEM;
2477 goto done;
2479 SIVAL( *data, 0, printer->info_2->changeid );
2480 status = WERR_OK;
2482 else
2483 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2486 if (*needed > *out_size)
2487 status = WERR_MORE_DATA;
2489 done:
2490 if ( !W_ERROR_IS_OK(status) )
2492 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2494 /* reply this param doesn't exist */
2496 if ( *out_size ) {
2497 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2498 if ( printer )
2499 free_a_printer( &printer, 2 );
2500 return WERR_NOMEM;
2503 else {
2504 *data = NULL;
2508 /* cleanup & exit */
2510 if ( printer )
2511 free_a_printer( &printer, 2 );
2513 return status;
2516 /*********************************************************
2517 Connect to the client machine.
2518 **********************************************************/
2520 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2521 struct in_addr *client_ip, const char *remote_machine)
2523 ZERO_STRUCTP(the_cli);
2525 if(cli_initialise(the_cli) == NULL) {
2526 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2527 return False;
2530 if ( is_zero_ip(*client_ip) ) {
2531 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2532 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2533 cli_shutdown(the_cli);
2534 return False;
2537 if (ismyip(the_cli->dest_ip)) {
2538 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2539 cli_shutdown(the_cli);
2540 return False;
2543 else {
2544 the_cli->dest_ip.s_addr = client_ip->s_addr;
2545 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2546 inet_ntoa(*client_ip) ));
2549 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2550 DEBUG(0,("spoolss_connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2551 cli_shutdown(the_cli);
2552 return False;
2555 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2556 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2557 remote_machine));
2558 cli_shutdown(the_cli);
2559 return False;
2562 the_cli->protocol = PROTOCOL_NT1;
2564 if (!cli_negprot(the_cli)) {
2565 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2566 cli_shutdown(the_cli);
2567 return False;
2570 if (the_cli->protocol != PROTOCOL_NT1) {
2571 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2572 cli_shutdown(the_cli);
2573 return False;
2577 * Do an anonymous session setup.
2580 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2581 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2582 cli_shutdown(the_cli);
2583 return False;
2586 if (!(the_cli->sec_mode & 1)) {
2587 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2588 cli_shutdown(the_cli);
2589 return False;
2592 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2593 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2594 cli_shutdown(the_cli);
2595 return False;
2599 * Ok - we have an anonymous connection to the IPC$ share.
2600 * Now start the NT Domain stuff :-).
2603 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2604 DEBUG(0,("spoolss_connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2605 cli_nt_session_close(the_cli);
2606 cli_ulogoff(the_cli);
2607 cli_shutdown(the_cli);
2608 return False;
2611 return True;
2614 /***************************************************************************
2615 Connect to the client.
2616 ****************************************************************************/
2618 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2619 uint32 localprinter, uint32 type,
2620 POLICY_HND *handle, struct in_addr *client_ip)
2622 WERROR result;
2625 * If it's the first connection, contact the client
2626 * and connect to the IPC$ share anonymously
2628 if (smb_connections==0) {
2629 fstring unix_printer;
2631 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2633 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2634 return False;
2636 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2637 /* Tell the connections db we're now interested in printer
2638 * notify messages. */
2639 register_message_flags( True, FLAG_MSG_PRINTING );
2643 * Tell the specific printing tdb we want messages for this printer
2644 * by registering our PID.
2647 if (!print_notify_register_pid(snum))
2648 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2650 smb_connections++;
2652 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2653 type, handle);
2655 if (!W_ERROR_IS_OK(result))
2656 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2657 dos_errstr(result)));
2659 return (W_ERROR_IS_OK(result));
2662 /********************************************************************
2663 * _spoolss_rffpcnex
2664 * ReplyFindFirstPrinterChangeNotifyEx
2666 * before replying OK: status=0 a rpc call is made to the workstation
2667 * asking ReplyOpenPrinter
2669 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2670 * called from api_spoolss_rffpcnex
2671 ********************************************************************/
2673 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2675 POLICY_HND *handle = &q_u->handle;
2676 uint32 flags = q_u->flags;
2677 uint32 options = q_u->options;
2678 UNISTR2 *localmachine = &q_u->localmachine;
2679 uint32 printerlocal = q_u->printerlocal;
2680 int snum = -1;
2681 SPOOL_NOTIFY_OPTION *option = q_u->option;
2682 struct in_addr client_ip;
2684 /* store the notify value in the printer struct */
2686 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2688 if (!Printer) {
2689 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2690 return WERR_BADFID;
2693 Printer->notify.flags=flags;
2694 Printer->notify.options=options;
2695 Printer->notify.printerlocal=printerlocal;
2697 if (Printer->notify.option)
2698 free_spool_notify_option(&Printer->notify.option);
2700 Printer->notify.option=dup_spool_notify_option(option);
2702 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2703 sizeof(Printer->notify.localmachine)-1);
2705 /* Connect to the client machine and send a ReplyOpenPrinter */
2707 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2708 snum = -1;
2709 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2710 !get_printer_snum(p, handle, &snum) )
2711 return WERR_BADFID;
2713 client_ip.s_addr = inet_addr(p->conn->client_address);
2715 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2716 Printer->notify.printerlocal, 1,
2717 &Printer->notify.client_hnd, &client_ip))
2718 return WERR_SERVER_UNAVAILABLE;
2720 Printer->notify.client_connected=True;
2722 return WERR_OK;
2725 /*******************************************************************
2726 * fill a notify_info_data with the servername
2727 ********************************************************************/
2729 void spoolss_notify_server_name(int snum,
2730 SPOOL_NOTIFY_INFO_DATA *data,
2731 print_queue_struct *queue,
2732 NT_PRINTER_INFO_LEVEL *printer,
2733 TALLOC_CTX *mem_ctx)
2735 pstring temp_name, temp;
2736 uint32 len;
2738 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2740 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2742 data->notify_data.data.length = len;
2743 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2745 if (!data->notify_data.data.string) {
2746 data->notify_data.data.length = 0;
2747 return;
2750 memcpy(data->notify_data.data.string, temp, len);
2753 /*******************************************************************
2754 * fill a notify_info_data with the printername (not including the servername).
2755 ********************************************************************/
2757 void spoolss_notify_printer_name(int snum,
2758 SPOOL_NOTIFY_INFO_DATA *data,
2759 print_queue_struct *queue,
2760 NT_PRINTER_INFO_LEVEL *printer,
2761 TALLOC_CTX *mem_ctx)
2763 pstring temp;
2764 uint32 len;
2766 /* the notify name should not contain the \\server\ part */
2767 char *p = strrchr(printer->info_2->printername, '\\');
2769 if (!p) {
2770 p = printer->info_2->printername;
2771 } else {
2772 p++;
2775 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2777 data->notify_data.data.length = len;
2778 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2780 if (!data->notify_data.data.string) {
2781 data->notify_data.data.length = 0;
2782 return;
2785 memcpy(data->notify_data.data.string, temp, len);
2788 /*******************************************************************
2789 * fill a notify_info_data with the servicename
2790 ********************************************************************/
2792 void spoolss_notify_share_name(int snum,
2793 SPOOL_NOTIFY_INFO_DATA *data,
2794 print_queue_struct *queue,
2795 NT_PRINTER_INFO_LEVEL *printer,
2796 TALLOC_CTX *mem_ctx)
2798 pstring temp;
2799 uint32 len;
2801 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2803 data->notify_data.data.length = len;
2804 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2806 if (!data->notify_data.data.string) {
2807 data->notify_data.data.length = 0;
2808 return;
2811 memcpy(data->notify_data.data.string, temp, len);
2814 /*******************************************************************
2815 * fill a notify_info_data with the port name
2816 ********************************************************************/
2818 void spoolss_notify_port_name(int snum,
2819 SPOOL_NOTIFY_INFO_DATA *data,
2820 print_queue_struct *queue,
2821 NT_PRINTER_INFO_LEVEL *printer,
2822 TALLOC_CTX *mem_ctx)
2824 pstring temp;
2825 uint32 len;
2827 /* even if it's strange, that's consistant in all the code */
2829 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2831 data->notify_data.data.length = len;
2832 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2834 if (!data->notify_data.data.string) {
2835 data->notify_data.data.length = 0;
2836 return;
2839 memcpy(data->notify_data.data.string, temp, len);
2842 /*******************************************************************
2843 * fill a notify_info_data with the printername
2844 * but it doesn't exist, have to see what to do
2845 ********************************************************************/
2847 void spoolss_notify_driver_name(int snum,
2848 SPOOL_NOTIFY_INFO_DATA *data,
2849 print_queue_struct *queue,
2850 NT_PRINTER_INFO_LEVEL *printer,
2851 TALLOC_CTX *mem_ctx)
2853 pstring temp;
2854 uint32 len;
2856 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2858 data->notify_data.data.length = len;
2859 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2861 if (!data->notify_data.data.string) {
2862 data->notify_data.data.length = 0;
2863 return;
2866 memcpy(data->notify_data.data.string, temp, len);
2869 /*******************************************************************
2870 * fill a notify_info_data with the comment
2871 ********************************************************************/
2873 void spoolss_notify_comment(int snum,
2874 SPOOL_NOTIFY_INFO_DATA *data,
2875 print_queue_struct *queue,
2876 NT_PRINTER_INFO_LEVEL *printer,
2877 TALLOC_CTX *mem_ctx)
2879 pstring temp;
2880 uint32 len;
2882 if (*printer->info_2->comment == '\0')
2883 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2884 else
2885 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2887 data->notify_data.data.length = len;
2888 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2890 if (!data->notify_data.data.string) {
2891 data->notify_data.data.length = 0;
2892 return;
2895 memcpy(data->notify_data.data.string, temp, len);
2898 /*******************************************************************
2899 * fill a notify_info_data with the comment
2900 * location = "Room 1, floor 2, building 3"
2901 ********************************************************************/
2903 void spoolss_notify_location(int snum,
2904 SPOOL_NOTIFY_INFO_DATA *data,
2905 print_queue_struct *queue,
2906 NT_PRINTER_INFO_LEVEL *printer,
2907 TALLOC_CTX *mem_ctx)
2909 pstring temp;
2910 uint32 len;
2912 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2914 data->notify_data.data.length = len;
2915 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2917 if (!data->notify_data.data.string) {
2918 data->notify_data.data.length = 0;
2919 return;
2922 memcpy(data->notify_data.data.string, temp, len);
2925 /*******************************************************************
2926 * fill a notify_info_data with the device mode
2927 * jfm:xxxx don't to it for know but that's a real problem !!!
2928 ********************************************************************/
2930 static void spoolss_notify_devmode(int snum,
2931 SPOOL_NOTIFY_INFO_DATA *data,
2932 print_queue_struct *queue,
2933 NT_PRINTER_INFO_LEVEL *printer,
2934 TALLOC_CTX *mem_ctx)
2938 /*******************************************************************
2939 * fill a notify_info_data with the separator file name
2940 ********************************************************************/
2942 void spoolss_notify_sepfile(int snum,
2943 SPOOL_NOTIFY_INFO_DATA *data,
2944 print_queue_struct *queue,
2945 NT_PRINTER_INFO_LEVEL *printer,
2946 TALLOC_CTX *mem_ctx)
2948 pstring temp;
2949 uint32 len;
2951 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2953 data->notify_data.data.length = len;
2954 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2956 if (!data->notify_data.data.string) {
2957 data->notify_data.data.length = 0;
2958 return;
2961 memcpy(data->notify_data.data.string, temp, len);
2964 /*******************************************************************
2965 * fill a notify_info_data with the print processor
2966 * jfm:xxxx return always winprint to indicate we don't do anything to it
2967 ********************************************************************/
2969 void spoolss_notify_print_processor(int snum,
2970 SPOOL_NOTIFY_INFO_DATA *data,
2971 print_queue_struct *queue,
2972 NT_PRINTER_INFO_LEVEL *printer,
2973 TALLOC_CTX *mem_ctx)
2975 pstring temp;
2976 uint32 len;
2978 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2980 data->notify_data.data.length = len;
2981 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2983 if (!data->notify_data.data.string) {
2984 data->notify_data.data.length = 0;
2985 return;
2988 memcpy(data->notify_data.data.string, temp, len);
2991 /*******************************************************************
2992 * fill a notify_info_data with the print processor options
2993 * jfm:xxxx send an empty string
2994 ********************************************************************/
2996 void spoolss_notify_parameters(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 pstring temp;
3003 uint32 len;
3005 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3007 data->notify_data.data.length = len;
3008 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3010 if (!data->notify_data.data.string) {
3011 data->notify_data.data.length = 0;
3012 return;
3015 memcpy(data->notify_data.data.string, temp, len);
3018 /*******************************************************************
3019 * fill a notify_info_data with the data type
3020 * jfm:xxxx always send RAW as data type
3021 ********************************************************************/
3023 void spoolss_notify_datatype(int snum,
3024 SPOOL_NOTIFY_INFO_DATA *data,
3025 print_queue_struct *queue,
3026 NT_PRINTER_INFO_LEVEL *printer,
3027 TALLOC_CTX *mem_ctx)
3029 pstring temp;
3030 uint32 len;
3032 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3034 data->notify_data.data.length = len;
3035 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3037 if (!data->notify_data.data.string) {
3038 data->notify_data.data.length = 0;
3039 return;
3042 memcpy(data->notify_data.data.string, temp, len);
3045 /*******************************************************************
3046 * fill a notify_info_data with the security descriptor
3047 * jfm:xxxx send an null pointer to say no security desc
3048 * have to implement security before !
3049 ********************************************************************/
3051 static void spoolss_notify_security_desc(int snum,
3052 SPOOL_NOTIFY_INFO_DATA *data,
3053 print_queue_struct *queue,
3054 NT_PRINTER_INFO_LEVEL *printer,
3055 TALLOC_CTX *mem_ctx)
3057 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3058 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3061 /*******************************************************************
3062 * fill a notify_info_data with the attributes
3063 * jfm:xxxx a samba printer is always shared
3064 ********************************************************************/
3066 void spoolss_notify_attributes(int snum,
3067 SPOOL_NOTIFY_INFO_DATA *data,
3068 print_queue_struct *queue,
3069 NT_PRINTER_INFO_LEVEL *printer,
3070 TALLOC_CTX *mem_ctx)
3072 data->notify_data.value[0] = printer->info_2->attributes;
3073 data->notify_data.value[1] = 0;
3076 /*******************************************************************
3077 * fill a notify_info_data with the priority
3078 ********************************************************************/
3080 static void spoolss_notify_priority(int snum,
3081 SPOOL_NOTIFY_INFO_DATA *data,
3082 print_queue_struct *queue,
3083 NT_PRINTER_INFO_LEVEL *printer,
3084 TALLOC_CTX *mem_ctx)
3086 data->notify_data.value[0] = printer->info_2->priority;
3087 data->notify_data.value[1] = 0;
3090 /*******************************************************************
3091 * fill a notify_info_data with the default priority
3092 ********************************************************************/
3094 static void spoolss_notify_default_priority(int snum,
3095 SPOOL_NOTIFY_INFO_DATA *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 data->notify_data.value[0] = printer->info_2->default_priority;
3101 data->notify_data.value[1] = 0;
3104 /*******************************************************************
3105 * fill a notify_info_data with the start time
3106 ********************************************************************/
3108 static void spoolss_notify_start_time(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 data->notify_data.value[0] = printer->info_2->starttime;
3115 data->notify_data.value[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the until time
3120 ********************************************************************/
3122 static void spoolss_notify_until_time(int snum,
3123 SPOOL_NOTIFY_INFO_DATA *data,
3124 print_queue_struct *queue,
3125 NT_PRINTER_INFO_LEVEL *printer,
3126 TALLOC_CTX *mem_ctx)
3128 data->notify_data.value[0] = printer->info_2->untiltime;
3129 data->notify_data.value[1] = 0;
3132 /*******************************************************************
3133 * fill a notify_info_data with the status
3134 ********************************************************************/
3136 static void spoolss_notify_status(int snum,
3137 SPOOL_NOTIFY_INFO_DATA *data,
3138 print_queue_struct *queue,
3139 NT_PRINTER_INFO_LEVEL *printer,
3140 TALLOC_CTX *mem_ctx)
3142 print_status_struct status;
3144 print_queue_length(snum, &status);
3145 data->notify_data.value[0]=(uint32) status.status;
3146 data->notify_data.value[1] = 0;
3149 /*******************************************************************
3150 * fill a notify_info_data with the number of jobs queued
3151 ********************************************************************/
3153 void spoolss_notify_cjobs(int snum,
3154 SPOOL_NOTIFY_INFO_DATA *data,
3155 print_queue_struct *queue,
3156 NT_PRINTER_INFO_LEVEL *printer,
3157 TALLOC_CTX *mem_ctx)
3159 data->notify_data.value[0] = print_queue_length(snum, NULL);
3160 data->notify_data.value[1] = 0;
3163 /*******************************************************************
3164 * fill a notify_info_data with the average ppm
3165 ********************************************************************/
3167 static void spoolss_notify_average_ppm(int snum,
3168 SPOOL_NOTIFY_INFO_DATA *data,
3169 print_queue_struct *queue,
3170 NT_PRINTER_INFO_LEVEL *printer,
3171 TALLOC_CTX *mem_ctx)
3173 /* always respond 8 pages per minutes */
3174 /* a little hard ! */
3175 data->notify_data.value[0] = printer->info_2->averageppm;
3176 data->notify_data.value[1] = 0;
3179 /*******************************************************************
3180 * fill a notify_info_data with username
3181 ********************************************************************/
3183 static void spoolss_notify_username(int snum,
3184 SPOOL_NOTIFY_INFO_DATA *data,
3185 print_queue_struct *queue,
3186 NT_PRINTER_INFO_LEVEL *printer,
3187 TALLOC_CTX *mem_ctx)
3189 pstring temp;
3190 uint32 len;
3192 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3194 data->notify_data.data.length = len;
3195 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3197 if (!data->notify_data.data.string) {
3198 data->notify_data.data.length = 0;
3199 return;
3202 memcpy(data->notify_data.data.string, temp, len);
3205 /*******************************************************************
3206 * fill a notify_info_data with job status
3207 ********************************************************************/
3209 static void spoolss_notify_job_status(int snum,
3210 SPOOL_NOTIFY_INFO_DATA *data,
3211 print_queue_struct *queue,
3212 NT_PRINTER_INFO_LEVEL *printer,
3213 TALLOC_CTX *mem_ctx)
3215 data->notify_data.value[0]=nt_printj_status(queue->status);
3216 data->notify_data.value[1] = 0;
3219 /*******************************************************************
3220 * fill a notify_info_data with job name
3221 ********************************************************************/
3223 static void spoolss_notify_job_name(int snum,
3224 SPOOL_NOTIFY_INFO_DATA *data,
3225 print_queue_struct *queue,
3226 NT_PRINTER_INFO_LEVEL *printer,
3227 TALLOC_CTX *mem_ctx)
3229 pstring temp;
3230 uint32 len;
3232 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3234 data->notify_data.data.length = len;
3235 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3237 if (!data->notify_data.data.string) {
3238 data->notify_data.data.length = 0;
3239 return;
3242 memcpy(data->notify_data.data.string, temp, len);
3245 /*******************************************************************
3246 * fill a notify_info_data with job status
3247 ********************************************************************/
3249 static void spoolss_notify_job_status_string(int snum,
3250 SPOOL_NOTIFY_INFO_DATA *data,
3251 print_queue_struct *queue,
3252 NT_PRINTER_INFO_LEVEL *printer,
3253 TALLOC_CTX *mem_ctx)
3256 * Now we're returning job status codes we just return a "" here. JRA.
3259 const char *p = "";
3260 pstring temp;
3261 uint32 len;
3263 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3264 p = "unknown";
3266 switch (queue->status) {
3267 case LPQ_QUEUED:
3268 p = "Queued";
3269 break;
3270 case LPQ_PAUSED:
3271 p = ""; /* NT provides the paused string */
3272 break;
3273 case LPQ_SPOOLING:
3274 p = "Spooling";
3275 break;
3276 case LPQ_PRINTING:
3277 p = "Printing";
3278 break;
3280 #endif /* NO LONGER NEEDED. */
3282 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3284 data->notify_data.data.length = len;
3285 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3287 if (!data->notify_data.data.string) {
3288 data->notify_data.data.length = 0;
3289 return;
3292 memcpy(data->notify_data.data.string, temp, len);
3295 /*******************************************************************
3296 * fill a notify_info_data with job time
3297 ********************************************************************/
3299 static void spoolss_notify_job_time(int snum,
3300 SPOOL_NOTIFY_INFO_DATA *data,
3301 print_queue_struct *queue,
3302 NT_PRINTER_INFO_LEVEL *printer,
3303 TALLOC_CTX *mem_ctx)
3305 data->notify_data.value[0]=0x0;
3306 data->notify_data.value[1]=0;
3309 /*******************************************************************
3310 * fill a notify_info_data with job size
3311 ********************************************************************/
3313 static void spoolss_notify_job_size(int snum,
3314 SPOOL_NOTIFY_INFO_DATA *data,
3315 print_queue_struct *queue,
3316 NT_PRINTER_INFO_LEVEL *printer,
3317 TALLOC_CTX *mem_ctx)
3319 data->notify_data.value[0]=queue->size;
3320 data->notify_data.value[1]=0;
3323 /*******************************************************************
3324 * fill a notify_info_data with page info
3325 ********************************************************************/
3326 static void spoolss_notify_total_pages(int snum,
3327 SPOOL_NOTIFY_INFO_DATA *data,
3328 print_queue_struct *queue,
3329 NT_PRINTER_INFO_LEVEL *printer,
3330 TALLOC_CTX *mem_ctx)
3332 data->notify_data.value[0]=queue->page_count;
3333 data->notify_data.value[1]=0;
3336 /*******************************************************************
3337 * fill a notify_info_data with pages printed info.
3338 ********************************************************************/
3339 static void spoolss_notify_pages_printed(int snum,
3340 SPOOL_NOTIFY_INFO_DATA *data,
3341 print_queue_struct *queue,
3342 NT_PRINTER_INFO_LEVEL *printer,
3343 TALLOC_CTX *mem_ctx)
3345 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3346 data->notify_data.value[1]=0;
3349 /*******************************************************************
3350 Fill a notify_info_data with job position.
3351 ********************************************************************/
3353 static void spoolss_notify_job_position(int snum,
3354 SPOOL_NOTIFY_INFO_DATA *data,
3355 print_queue_struct *queue,
3356 NT_PRINTER_INFO_LEVEL *printer,
3357 TALLOC_CTX *mem_ctx)
3359 data->notify_data.value[0]=queue->job;
3360 data->notify_data.value[1]=0;
3363 /*******************************************************************
3364 Fill a notify_info_data with submitted time.
3365 ********************************************************************/
3367 static void spoolss_notify_submitted_time(int snum,
3368 SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer,
3371 TALLOC_CTX *mem_ctx)
3373 struct tm *t;
3374 uint32 len;
3375 SYSTEMTIME st;
3376 char *p;
3378 t=gmtime(&queue->time);
3380 len = sizeof(SYSTEMTIME);
3382 data->notify_data.data.length = len;
3383 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3385 if (!data->notify_data.data.string) {
3386 data->notify_data.data.length = 0;
3387 return;
3390 make_systemtime(&st, t);
3393 * Systemtime must be linearized as a set of UINT16's.
3394 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3397 p = (char *)data->notify_data.data.string;
3398 SSVAL(p, 0, st.year);
3399 SSVAL(p, 2, st.month);
3400 SSVAL(p, 4, st.dayofweek);
3401 SSVAL(p, 6, st.day);
3402 SSVAL(p, 8, st.hour);
3403 SSVAL(p, 10, st.minute);
3404 SSVAL(p, 12, st.second);
3405 SSVAL(p, 14, st.milliseconds);
3408 struct s_notify_info_data_table
3410 uint16 type;
3411 uint16 field;
3412 const char *name;
3413 uint32 size;
3414 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3415 print_queue_struct *queue,
3416 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3419 /* A table describing the various print notification constants and
3420 whether the notification data is a pointer to a variable sized
3421 buffer, a one value uint32 or a two value uint32. */
3423 static const struct s_notify_info_data_table notify_info_data_table[] =
3425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3452 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3453 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3454 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3455 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3456 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3457 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3458 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3463 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3476 /*******************************************************************
3477 Return the size of info_data structure.
3478 ********************************************************************/
3480 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3482 int i=0;
3484 for (i = 0; i < sizeof(notify_info_data_table); i++)
3486 if ( (notify_info_data_table[i].type == type)
3487 && (notify_info_data_table[i].field == field) )
3489 switch(notify_info_data_table[i].size)
3491 case NOTIFY_ONE_VALUE:
3492 case NOTIFY_TWO_VALUE:
3493 return 1;
3494 case NOTIFY_STRING:
3495 return 2;
3497 /* The only pointer notify data I have seen on
3498 the wire is the submitted time and this has
3499 the notify size set to 4. -tpot */
3501 case NOTIFY_POINTER:
3502 return 4;
3504 case NOTIFY_SECDESC:
3505 return 5;
3510 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3512 return 0;
3515 /*******************************************************************
3516 Return the type of notify_info_data.
3517 ********************************************************************/
3519 static int type_of_notify_info_data(uint16 type, uint16 field)
3521 int i=0;
3523 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3524 if (notify_info_data_table[i].type == type &&
3525 notify_info_data_table[i].field == field)
3526 return notify_info_data_table[i].size;
3529 return False;
3532 /****************************************************************************
3533 ****************************************************************************/
3535 static int search_notify(uint16 type, uint16 field, int *value)
3537 int i;
3539 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3540 if (notify_info_data_table[i].type == type &&
3541 notify_info_data_table[i].field == field &&
3542 notify_info_data_table[i].fn != NULL) {
3543 *value = i;
3544 return True;
3548 return False;
3551 /****************************************************************************
3552 ****************************************************************************/
3554 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3556 info_data->type = type;
3557 info_data->field = field;
3558 info_data->reserved = 0;
3560 info_data->size = size_of_notify_info_data(type, field);
3561 info_data->enc_type = type_of_notify_info_data(type, field);
3563 info_data->id = id;
3568 /*******************************************************************
3570 * fill a notify_info struct with info asked
3572 ********************************************************************/
3574 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3575 snum, SPOOL_NOTIFY_OPTION_TYPE
3576 *option_type, uint32 id,
3577 TALLOC_CTX *mem_ctx)
3579 int field_num,j;
3580 uint16 type;
3581 uint16 field;
3583 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3584 NT_PRINTER_INFO_LEVEL *printer = NULL;
3585 print_queue_struct *queue=NULL;
3587 type=option_type->type;
3589 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3590 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3591 option_type->count, lp_servicename(snum)));
3593 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3594 return False;
3596 for(field_num=0; field_num<option_type->count; field_num++) {
3597 field = option_type->fields[field_num];
3599 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3601 if (!search_notify(type, field, &j) )
3602 continue;
3604 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3605 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3606 return False;
3607 } else
3608 info->data = tid;
3610 current_data = &info->data[info->count];
3612 construct_info_data(current_data, type, field, id);
3614 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3615 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3617 notify_info_data_table[j].fn(snum, current_data, queue,
3618 printer, mem_ctx);
3620 info->count++;
3623 free_a_printer(&printer, 2);
3624 return True;
3627 /*******************************************************************
3629 * fill a notify_info struct with info asked
3631 ********************************************************************/
3633 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3634 SPOOL_NOTIFY_INFO *info,
3635 NT_PRINTER_INFO_LEVEL *printer,
3636 int snum, SPOOL_NOTIFY_OPTION_TYPE
3637 *option_type, uint32 id,
3638 TALLOC_CTX *mem_ctx)
3640 int field_num,j;
3641 uint16 type;
3642 uint16 field;
3644 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3646 DEBUG(4,("construct_notify_jobs_info\n"));
3648 type = option_type->type;
3650 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3651 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3652 option_type->count));
3654 for(field_num=0; field_num<option_type->count; field_num++) {
3655 field = option_type->fields[field_num];
3657 if (!search_notify(type, field, &j) )
3658 continue;
3660 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3661 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3662 return False;
3664 else info->data = tid;
3666 current_data=&(info->data[info->count]);
3668 construct_info_data(current_data, type, field, id);
3669 notify_info_data_table[j].fn(snum, current_data, queue,
3670 printer, mem_ctx);
3671 info->count++;
3674 return True;
3678 * JFM: The enumeration is not that simple, it's even non obvious.
3680 * let's take an example: I want to monitor the PRINTER SERVER for
3681 * the printer's name and the number of jobs currently queued.
3682 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3683 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3685 * I have 3 printers on the back of my server.
3687 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3688 * structures.
3689 * Number Data Id
3690 * 1 printer 1 name 1
3691 * 2 printer 1 cjob 1
3692 * 3 printer 2 name 2
3693 * 4 printer 2 cjob 2
3694 * 5 printer 3 name 3
3695 * 6 printer 3 name 3
3697 * that's the print server case, the printer case is even worse.
3700 /*******************************************************************
3702 * enumerate all printers on the printserver
3703 * fill a notify_info struct with info asked
3705 ********************************************************************/
3707 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3708 SPOOL_NOTIFY_INFO *info,
3709 TALLOC_CTX *mem_ctx)
3711 int snum;
3712 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3713 int n_services=lp_numservices();
3714 int i;
3715 uint32 id;
3716 SPOOL_NOTIFY_OPTION *option;
3717 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3719 DEBUG(4,("printserver_notify_info\n"));
3721 if (!Printer)
3722 return WERR_BADFID;
3724 option=Printer->notify.option;
3725 id=1;
3726 info->version=2;
3727 info->data=NULL;
3728 info->count=0;
3730 for (i=0; i<option->count; i++) {
3731 option_type=&(option->ctr.type[i]);
3733 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3734 continue;
3736 for (snum=0; snum<n_services; snum++)
3738 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3739 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3743 #if 0
3745 * Debugging information, don't delete.
3748 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3749 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3750 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3752 for (i=0; i<info->count; i++) {
3753 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3754 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3755 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3757 #endif
3759 return WERR_OK;
3762 /*******************************************************************
3764 * fill a notify_info struct with info asked
3766 ********************************************************************/
3768 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3769 TALLOC_CTX *mem_ctx)
3771 int snum;
3772 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3773 int i;
3774 uint32 id;
3775 SPOOL_NOTIFY_OPTION *option;
3776 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3777 int count,j;
3778 print_queue_struct *queue=NULL;
3779 print_status_struct status;
3781 DEBUG(4,("printer_notify_info\n"));
3783 if (!Printer)
3784 return WERR_BADFID;
3786 option=Printer->notify.option;
3787 id = 0x0;
3788 info->version=2;
3789 info->data=NULL;
3790 info->count=0;
3792 get_printer_snum(p, hnd, &snum);
3794 for (i=0; i<option->count; i++) {
3795 option_type=&option->ctr.type[i];
3797 switch ( option_type->type ) {
3798 case PRINTER_NOTIFY_TYPE:
3799 if(construct_notify_printer_info(Printer, info, snum,
3800 option_type, id,
3801 mem_ctx))
3802 id--;
3803 break;
3805 case JOB_NOTIFY_TYPE: {
3806 NT_PRINTER_INFO_LEVEL *printer = NULL;
3808 count = print_queue_status(snum, &queue, &status);
3810 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3811 goto done;
3813 for (j=0; j<count; j++) {
3814 construct_notify_jobs_info(&queue[j], info,
3815 printer, snum,
3816 option_type,
3817 queue[j].job,
3818 mem_ctx);
3821 free_a_printer(&printer, 2);
3823 done:
3824 SAFE_FREE(queue);
3825 break;
3831 * Debugging information, don't delete.
3834 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3835 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3836 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3838 for (i=0; i<info->count; i++) {
3839 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3840 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3841 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3844 return WERR_OK;
3847 /********************************************************************
3848 * spoolss_rfnpcnex
3849 ********************************************************************/
3851 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3853 POLICY_HND *handle = &q_u->handle;
3854 SPOOL_NOTIFY_INFO *info = &r_u->info;
3856 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3857 WERROR result = WERR_BADFID;
3859 /* we always have a NOTIFY_INFO struct */
3860 r_u->info_ptr=0x1;
3862 if (!Printer) {
3863 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3864 OUR_HANDLE(handle)));
3865 goto done;
3868 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3871 * We are now using the change value, and
3872 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3873 * I don't have a global notification system, I'm sending back all the
3874 * informations even when _NOTHING_ has changed.
3877 /* We need to keep track of the change value to send back in
3878 RRPCN replies otherwise our updates are ignored. */
3880 Printer->notify.fnpcn = True;
3882 if (Printer->notify.client_connected) {
3883 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3884 Printer->notify.change = q_u->change;
3887 /* just ignore the SPOOL_NOTIFY_OPTION */
3889 switch (Printer->printer_type) {
3890 case PRINTER_HANDLE_IS_PRINTSERVER:
3891 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3892 break;
3894 case PRINTER_HANDLE_IS_PRINTER:
3895 result = printer_notify_info(p, handle, info, p->mem_ctx);
3896 break;
3899 Printer->notify.fnpcn = False;
3901 done:
3902 return result;
3905 /********************************************************************
3906 * construct_printer_info_0
3907 * fill a printer_info_0 struct
3908 ********************************************************************/
3910 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3912 pstring chaine;
3913 int count;
3914 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3915 counter_printer_0 *session_counter;
3916 uint32 global_counter;
3917 struct tm *t;
3918 time_t setuptime;
3919 print_status_struct status;
3921 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3922 return False;
3924 count = print_queue_length(snum, &status);
3926 /* check if we already have a counter for this printer */
3927 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3929 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3930 if (session_counter->snum == snum)
3931 break;
3934 /* it's the first time, add it to the list */
3935 if (session_counter==NULL) {
3936 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3937 free_a_printer(&ntprinter, 2);
3938 return False;
3940 ZERO_STRUCTP(session_counter);
3941 session_counter->snum=snum;
3942 session_counter->counter=0;
3943 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3946 /* increment it */
3947 session_counter->counter++;
3949 /* JFM:
3950 * the global_counter should be stored in a TDB as it's common to all the clients
3951 * and should be zeroed on samba startup
3953 global_counter=session_counter->counter;
3955 pstrcpy(chaine,ntprinter->info_2->printername);
3957 init_unistr(&printer->printername, chaine);
3959 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3960 init_unistr(&printer->servername, chaine);
3962 printer->cjobs = count;
3963 printer->total_jobs = 0;
3964 printer->total_bytes = 0;
3966 setuptime = (time_t)ntprinter->info_2->setuptime;
3967 t=gmtime(&setuptime);
3969 printer->year = t->tm_year+1900;
3970 printer->month = t->tm_mon+1;
3971 printer->dayofweek = t->tm_wday;
3972 printer->day = t->tm_mday;
3973 printer->hour = t->tm_hour;
3974 printer->minute = t->tm_min;
3975 printer->second = t->tm_sec;
3976 printer->milliseconds = 0;
3978 printer->global_counter = global_counter;
3979 printer->total_pages = 0;
3981 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3982 printer->major_version = 0x0005; /* NT 5 */
3983 printer->build_version = 0x0893; /* build 2195 */
3985 printer->unknown7 = 0x1;
3986 printer->unknown8 = 0x0;
3987 printer->unknown9 = 0x0;
3988 printer->session_counter = session_counter->counter;
3989 printer->unknown11 = 0x0;
3990 printer->printer_errors = 0x0; /* number of print failure */
3991 printer->unknown13 = 0x0;
3992 printer->unknown14 = 0x1;
3993 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3994 printer->unknown16 = 0x0;
3995 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3996 printer->unknown18 = 0x0;
3997 printer->status = nt_printq_status(status.status);
3998 printer->unknown20 = 0x0;
3999 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4000 printer->unknown22 = 0x0;
4001 printer->unknown23 = 0x6; /* 6 ???*/
4002 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4003 printer->unknown25 = 0;
4004 printer->unknown26 = 0;
4005 printer->unknown27 = 0;
4006 printer->unknown28 = 0;
4007 printer->unknown29 = 0;
4009 free_a_printer(&ntprinter,2);
4010 return (True);
4013 /********************************************************************
4014 * construct_printer_info_1
4015 * fill a printer_info_1 struct
4016 ********************************************************************/
4017 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4019 pstring chaine;
4020 pstring chaine2;
4021 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4023 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4024 return False;
4026 printer->flags=flags;
4028 if (*ntprinter->info_2->comment == '\0') {
4029 init_unistr(&printer->comment, lp_comment(snum));
4030 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4031 ntprinter->info_2->drivername, lp_comment(snum));
4033 else {
4034 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4035 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4036 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4039 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4041 init_unistr(&printer->description, chaine);
4042 init_unistr(&printer->name, chaine2);
4044 free_a_printer(&ntprinter,2);
4046 return True;
4049 /****************************************************************************
4050 Free a DEVMODE struct.
4051 ****************************************************************************/
4053 static void free_dev_mode(DEVICEMODE *dev)
4055 if (dev == NULL)
4056 return;
4058 SAFE_FREE(dev->private);
4059 SAFE_FREE(dev);
4063 /****************************************************************************
4064 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4065 should be valid upon entry
4066 ****************************************************************************/
4068 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4070 if ( !devmode || !ntdevmode )
4071 return False;
4073 init_unistr(&devmode->devicename, ntdevmode->devicename);
4075 init_unistr(&devmode->formname, ntdevmode->formname);
4077 devmode->specversion = ntdevmode->specversion;
4078 devmode->driverversion = ntdevmode->driverversion;
4079 devmode->size = ntdevmode->size;
4080 devmode->driverextra = ntdevmode->driverextra;
4081 devmode->fields = ntdevmode->fields;
4083 devmode->orientation = ntdevmode->orientation;
4084 devmode->papersize = ntdevmode->papersize;
4085 devmode->paperlength = ntdevmode->paperlength;
4086 devmode->paperwidth = ntdevmode->paperwidth;
4087 devmode->scale = ntdevmode->scale;
4088 devmode->copies = ntdevmode->copies;
4089 devmode->defaultsource = ntdevmode->defaultsource;
4090 devmode->printquality = ntdevmode->printquality;
4091 devmode->color = ntdevmode->color;
4092 devmode->duplex = ntdevmode->duplex;
4093 devmode->yresolution = ntdevmode->yresolution;
4094 devmode->ttoption = ntdevmode->ttoption;
4095 devmode->collate = ntdevmode->collate;
4096 devmode->icmmethod = ntdevmode->icmmethod;
4097 devmode->icmintent = ntdevmode->icmintent;
4098 devmode->mediatype = ntdevmode->mediatype;
4099 devmode->dithertype = ntdevmode->dithertype;
4101 if (ntdevmode->private != NULL) {
4102 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4103 return False;
4106 return True;
4109 /****************************************************************************
4110 Create a DEVMODE struct. Returns malloced memory.
4111 ****************************************************************************/
4113 DEVICEMODE *construct_dev_mode(int snum)
4115 NT_PRINTER_INFO_LEVEL *printer = NULL;
4116 DEVICEMODE *devmode = NULL;
4118 DEBUG(7,("construct_dev_mode\n"));
4120 DEBUGADD(8,("getting printer characteristics\n"));
4122 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4123 return NULL;
4125 if ( !printer->info_2->devmode ) {
4126 DEBUG(5, ("BONG! There was no device mode!\n"));
4127 goto done;
4130 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4131 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4132 goto done;
4135 ZERO_STRUCTP(devmode);
4137 DEBUGADD(8,("loading DEVICEMODE\n"));
4139 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4140 free_dev_mode( devmode );
4141 devmode = NULL;
4144 done:
4145 free_a_printer(&printer,2);
4147 return devmode;
4150 /********************************************************************
4151 * construct_printer_info_2
4152 * fill a printer_info_2 struct
4153 ********************************************************************/
4155 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4157 int count;
4158 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4160 print_status_struct status;
4162 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4163 return False;
4165 count = print_queue_length(snum, &status);
4167 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4168 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4169 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4170 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4171 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4173 if (*ntprinter->info_2->comment == '\0')
4174 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4175 else
4176 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4178 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4179 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4180 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4181 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4182 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4184 printer->attributes = ntprinter->info_2->attributes;
4186 printer->priority = ntprinter->info_2->priority; /* priority */
4187 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4188 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4189 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4190 printer->status = nt_printq_status(status.status); /* status */
4191 printer->cjobs = count; /* jobs */
4192 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4194 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4195 DEBUG(8, ("Returning NULL Devicemode!\n"));
4198 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4199 /* steal the printer info sec_desc structure. [badly done]. */
4200 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4201 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4202 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4203 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4205 else {
4206 printer->secdesc = NULL;
4209 free_a_printer(&ntprinter, 2);
4210 return True;
4213 /********************************************************************
4214 * construct_printer_info_3
4215 * fill a printer_info_3 struct
4216 ********************************************************************/
4218 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4220 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4221 PRINTER_INFO_3 *printer = NULL;
4223 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4224 return False;
4226 *pp_printer = NULL;
4227 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4228 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4229 return False;
4232 ZERO_STRUCTP(printer);
4234 printer->flags = 4; /* These are the components of the SD we are returning. */
4235 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4236 /* steal the printer info sec_desc structure. [badly done]. */
4237 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4239 #if 0
4241 * Set the flags for the components we are returning.
4244 if (printer->secdesc->owner_sid)
4245 printer->flags |= OWNER_SECURITY_INFORMATION;
4247 if (printer->secdesc->grp_sid)
4248 printer->flags |= GROUP_SECURITY_INFORMATION;
4250 if (printer->secdesc->dacl)
4251 printer->flags |= DACL_SECURITY_INFORMATION;
4253 if (printer->secdesc->sacl)
4254 printer->flags |= SACL_SECURITY_INFORMATION;
4255 #endif
4257 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4258 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4259 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4262 free_a_printer(&ntprinter, 2);
4264 *pp_printer = printer;
4265 return True;
4268 /********************************************************************
4269 * construct_printer_info_4
4270 * fill a printer_info_4 struct
4271 ********************************************************************/
4273 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4275 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4277 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4278 return False;
4280 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4281 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4282 printer->attributes = ntprinter->info_2->attributes;
4284 free_a_printer(&ntprinter, 2);
4285 return True;
4288 /********************************************************************
4289 * construct_printer_info_5
4290 * fill a printer_info_5 struct
4291 ********************************************************************/
4293 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4295 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4297 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4298 return False;
4300 init_unistr(&printer->printername, ntprinter->info_2->printername);
4301 init_unistr(&printer->portname, ntprinter->info_2->portname);
4302 printer->attributes = ntprinter->info_2->attributes;
4304 /* these two are not used by NT+ according to MSDN */
4306 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4307 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4309 free_a_printer(&ntprinter, 2);
4311 return True;
4314 /********************************************************************
4315 * construct_printer_info_7
4316 * fill a printer_info_7 struct
4317 ********************************************************************/
4319 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4321 char *guid_str = NULL;
4322 GUID guid;
4324 if (is_printer_published(print_hnd, snum, &guid)) {
4325 asprintf(&guid_str, "{%s}", uuid_string_static(guid));
4326 strupper(guid_str);
4327 init_unistr(&printer->guid, guid_str);
4328 printer->action = SPOOL_DS_PUBLISH;
4329 } else {
4330 init_unistr(&printer->guid, "");
4331 printer->action = SPOOL_DS_UNPUBLISH;
4334 return True;
4337 /********************************************************************
4338 Spoolss_enumprinters.
4339 ********************************************************************/
4341 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4343 int snum;
4344 int i;
4345 int n_services=lp_numservices();
4346 PRINTER_INFO_1 *tp, *printers=NULL;
4347 PRINTER_INFO_1 current_prt;
4349 DEBUG(4,("enum_all_printers_info_1\n"));
4351 for (snum=0; snum<n_services; snum++) {
4352 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4353 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4355 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4356 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4357 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4358 SAFE_FREE(printers);
4359 *returned=0;
4360 return WERR_NOMEM;
4362 else printers = tp;
4363 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4365 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4366 (*returned)++;
4371 /* check the required size. */
4372 for (i=0; i<*returned; i++)
4373 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4375 if (!alloc_buffer_size(buffer, *needed))
4376 return WERR_INSUFFICIENT_BUFFER;
4378 /* fill the buffer with the structures */
4379 for (i=0; i<*returned; i++)
4380 smb_io_printer_info_1("", buffer, &printers[i], 0);
4382 /* clear memory */
4383 SAFE_FREE(printers);
4385 if (*needed > offered) {
4386 *returned=0;
4387 return WERR_INSUFFICIENT_BUFFER;
4389 else
4390 return WERR_OK;
4393 /********************************************************************
4394 enum_all_printers_info_1_local.
4395 *********************************************************************/
4397 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4399 DEBUG(4,("enum_all_printers_info_1_local\n"));
4401 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4404 /********************************************************************
4405 enum_all_printers_info_1_name.
4406 *********************************************************************/
4408 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4410 char *s = name;
4412 DEBUG(4,("enum_all_printers_info_1_name\n"));
4414 if ((name[0] == '\\') && (name[1] == '\\'))
4415 s = name + 2;
4417 if (is_myname_or_ipaddr(s)) {
4418 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4420 else
4421 return WERR_INVALID_NAME;
4424 /********************************************************************
4425 enum_all_printers_info_1_remote.
4426 *********************************************************************/
4428 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4430 PRINTER_INFO_1 *printer;
4431 fstring printername;
4432 fstring desc;
4433 fstring comment;
4434 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4436 /* JFM: currently it's more a place holder than anything else.
4437 * In the spooler world there is a notion of server registration.
4438 * the print servers are registring (sp ?) on the PDC (in the same domain)
4440 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4443 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4444 return WERR_NOMEM;
4446 *returned=1;
4448 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4449 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4450 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4452 init_unistr(&printer->description, desc);
4453 init_unistr(&printer->name, printername);
4454 init_unistr(&printer->comment, comment);
4455 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4457 /* check the required size. */
4458 *needed += spoolss_size_printer_info_1(printer);
4460 if (!alloc_buffer_size(buffer, *needed)) {
4461 SAFE_FREE(printer);
4462 return WERR_INSUFFICIENT_BUFFER;
4465 /* fill the buffer with the structures */
4466 smb_io_printer_info_1("", buffer, printer, 0);
4468 /* clear memory */
4469 SAFE_FREE(printer);
4471 if (*needed > offered) {
4472 *returned=0;
4473 return WERR_INSUFFICIENT_BUFFER;
4475 else
4476 return WERR_OK;
4479 /********************************************************************
4480 enum_all_printers_info_1_network.
4481 *********************************************************************/
4483 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4485 char *s = name;
4487 DEBUG(4,("enum_all_printers_info_1_network\n"));
4489 /* If we respond to a enum_printers level 1 on our name with flags
4490 set to PRINTER_ENUM_REMOTE with a list of printers then these
4491 printers incorrectly appear in the APW browse list.
4492 Specifically the printers for the server appear at the workgroup
4493 level where all the other servers in the domain are
4494 listed. Windows responds to this call with a
4495 WERR_CAN_NOT_COMPLETE so we should do the same. */
4497 if (name[0] == '\\' && name[1] == '\\')
4498 s = name + 2;
4500 if (is_myname_or_ipaddr(s))
4501 return WERR_CAN_NOT_COMPLETE;
4503 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4506 /********************************************************************
4507 * api_spoolss_enumprinters
4509 * called from api_spoolss_enumprinters (see this to understand)
4510 ********************************************************************/
4512 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4514 int snum;
4515 int i;
4516 int n_services=lp_numservices();
4517 PRINTER_INFO_2 *tp, *printers=NULL;
4518 PRINTER_INFO_2 current_prt;
4520 for (snum=0; snum<n_services; snum++) {
4521 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4522 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4524 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4525 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4526 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4527 SAFE_FREE(printers);
4528 *returned = 0;
4529 return WERR_NOMEM;
4531 else printers = tp;
4532 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4533 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4534 (*returned)++;
4539 /* check the required size. */
4540 for (i=0; i<*returned; i++)
4541 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4543 if (!alloc_buffer_size(buffer, *needed)) {
4544 for (i=0; i<*returned; i++) {
4545 free_devmode(printers[i].devmode);
4547 SAFE_FREE(printers);
4548 return WERR_INSUFFICIENT_BUFFER;
4551 /* fill the buffer with the structures */
4552 for (i=0; i<*returned; i++)
4553 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4555 /* clear memory */
4556 for (i=0; i<*returned; i++) {
4557 free_devmode(printers[i].devmode);
4559 SAFE_FREE(printers);
4561 if (*needed > offered) {
4562 *returned=0;
4563 return WERR_INSUFFICIENT_BUFFER;
4565 else
4566 return WERR_OK;
4569 /********************************************************************
4570 * handle enumeration of printers at level 1
4571 ********************************************************************/
4573 static WERROR enumprinters_level1( uint32 flags, fstring name,
4574 NEW_BUFFER *buffer, uint32 offered,
4575 uint32 *needed, uint32 *returned)
4577 /* Not all the flags are equals */
4579 if (flags & PRINTER_ENUM_LOCAL)
4580 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4582 if (flags & PRINTER_ENUM_NAME)
4583 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4585 if (flags & PRINTER_ENUM_REMOTE)
4586 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4588 if (flags & PRINTER_ENUM_NETWORK)
4589 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4591 return WERR_OK; /* NT4sp5 does that */
4594 /********************************************************************
4595 * handle enumeration of printers at level 2
4596 ********************************************************************/
4598 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4599 NEW_BUFFER *buffer, uint32 offered,
4600 uint32 *needed, uint32 *returned)
4602 char *s = servername;
4604 if (flags & PRINTER_ENUM_LOCAL) {
4605 return enum_all_printers_info_2(buffer, offered, needed, returned);
4608 if (flags & PRINTER_ENUM_NAME) {
4609 if ((servername[0] == '\\') && (servername[1] == '\\'))
4610 s = servername + 2;
4611 if (is_myname_or_ipaddr(s))
4612 return enum_all_printers_info_2(buffer, offered, needed, returned);
4613 else
4614 return WERR_INVALID_NAME;
4617 if (flags & PRINTER_ENUM_REMOTE)
4618 return WERR_UNKNOWN_LEVEL;
4620 return WERR_OK;
4623 /********************************************************************
4624 * handle enumeration of printers at level 5
4625 ********************************************************************/
4627 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4628 NEW_BUFFER *buffer, uint32 offered,
4629 uint32 *needed, uint32 *returned)
4631 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4632 return WERR_OK;
4635 /********************************************************************
4636 * api_spoolss_enumprinters
4638 * called from api_spoolss_enumprinters (see this to understand)
4639 ********************************************************************/
4641 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4643 uint32 flags = q_u->flags;
4644 UNISTR2 *servername = &q_u->servername;
4645 uint32 level = q_u->level;
4646 NEW_BUFFER *buffer = NULL;
4647 uint32 offered = q_u->offered;
4648 uint32 *needed = &r_u->needed;
4649 uint32 *returned = &r_u->returned;
4651 fstring name;
4653 /* that's an [in out] buffer */
4654 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4655 buffer = r_u->buffer;
4657 DEBUG(4,("_spoolss_enumprinters\n"));
4659 *needed=0;
4660 *returned=0;
4663 * Level 1:
4664 * flags==PRINTER_ENUM_NAME
4665 * if name=="" then enumerates all printers
4666 * if name!="" then enumerate the printer
4667 * flags==PRINTER_ENUM_REMOTE
4668 * name is NULL, enumerate printers
4669 * Level 2: name!="" enumerates printers, name can't be NULL
4670 * Level 3: doesn't exist
4671 * Level 4: does a local registry lookup
4672 * Level 5: same as Level 2
4675 unistr2_to_ascii(name, servername, sizeof(name)-1);
4676 strupper(name);
4678 switch (level) {
4679 case 1:
4680 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4681 case 2:
4682 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4683 case 5:
4684 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4685 case 3:
4686 case 4:
4687 break;
4689 return WERR_UNKNOWN_LEVEL;
4692 /****************************************************************************
4693 ****************************************************************************/
4695 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4697 PRINTER_INFO_0 *printer=NULL;
4699 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4700 return WERR_NOMEM;
4702 construct_printer_info_0(print_hnd, printer, snum);
4704 /* check the required size. */
4705 *needed += spoolss_size_printer_info_0(printer);
4707 if (!alloc_buffer_size(buffer, *needed)) {
4708 SAFE_FREE(printer);
4709 return WERR_INSUFFICIENT_BUFFER;
4712 /* fill the buffer with the structures */
4713 smb_io_printer_info_0("", buffer, printer, 0);
4715 /* clear memory */
4716 SAFE_FREE(printer);
4718 if (*needed > offered) {
4719 return WERR_INSUFFICIENT_BUFFER;
4722 return WERR_OK;
4725 /****************************************************************************
4726 ****************************************************************************/
4728 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4730 PRINTER_INFO_1 *printer=NULL;
4732 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4733 return WERR_NOMEM;
4735 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4737 /* check the required size. */
4738 *needed += spoolss_size_printer_info_1(printer);
4740 if (!alloc_buffer_size(buffer, *needed)) {
4741 SAFE_FREE(printer);
4742 return WERR_INSUFFICIENT_BUFFER;
4745 /* fill the buffer with the structures */
4746 smb_io_printer_info_1("", buffer, printer, 0);
4748 /* clear memory */
4749 SAFE_FREE(printer);
4751 if (*needed > offered) {
4752 return WERR_INSUFFICIENT_BUFFER;
4755 return WERR_OK;
4758 /****************************************************************************
4759 ****************************************************************************/
4761 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4763 PRINTER_INFO_2 *printer=NULL;
4765 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4766 return WERR_NOMEM;
4768 construct_printer_info_2(print_hnd, printer, snum);
4770 /* check the required size. */
4771 *needed += spoolss_size_printer_info_2(printer);
4773 if (!alloc_buffer_size(buffer, *needed)) {
4774 free_printer_info_2(printer);
4775 return WERR_INSUFFICIENT_BUFFER;
4778 /* fill the buffer with the structures */
4779 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4780 free_printer_info_2(printer);
4781 return WERR_NOMEM;
4784 /* clear memory */
4785 free_printer_info_2(printer);
4787 if (*needed > offered) {
4788 return WERR_INSUFFICIENT_BUFFER;
4791 return WERR_OK;
4794 /****************************************************************************
4795 ****************************************************************************/
4797 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4799 PRINTER_INFO_3 *printer=NULL;
4801 if (!construct_printer_info_3(print_hnd, &printer, snum))
4802 return WERR_NOMEM;
4804 /* check the required size. */
4805 *needed += spoolss_size_printer_info_3(printer);
4807 if (!alloc_buffer_size(buffer, *needed)) {
4808 free_printer_info_3(printer);
4809 return WERR_INSUFFICIENT_BUFFER;
4812 /* fill the buffer with the structures */
4813 smb_io_printer_info_3("", buffer, printer, 0);
4815 /* clear memory */
4816 free_printer_info_3(printer);
4818 if (*needed > offered) {
4819 return WERR_INSUFFICIENT_BUFFER;
4822 return WERR_OK;
4825 /****************************************************************************
4826 ****************************************************************************/
4828 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4830 PRINTER_INFO_4 *printer=NULL;
4832 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4833 return WERR_NOMEM;
4835 if (!construct_printer_info_4(print_hnd, printer, snum))
4836 return WERR_NOMEM;
4838 /* check the required size. */
4839 *needed += spoolss_size_printer_info_4(printer);
4841 if (!alloc_buffer_size(buffer, *needed)) {
4842 free_printer_info_4(printer);
4843 return WERR_INSUFFICIENT_BUFFER;
4846 /* fill the buffer with the structures */
4847 smb_io_printer_info_4("", buffer, printer, 0);
4849 /* clear memory */
4850 free_printer_info_4(printer);
4852 if (*needed > offered) {
4853 return WERR_INSUFFICIENT_BUFFER;
4856 return WERR_OK;
4859 /****************************************************************************
4860 ****************************************************************************/
4862 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4864 PRINTER_INFO_5 *printer=NULL;
4866 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4867 return WERR_NOMEM;
4869 if (!construct_printer_info_5(print_hnd, printer, snum))
4870 return WERR_NOMEM;
4872 /* check the required size. */
4873 *needed += spoolss_size_printer_info_5(printer);
4875 if (!alloc_buffer_size(buffer, *needed)) {
4876 free_printer_info_5(printer);
4877 return WERR_INSUFFICIENT_BUFFER;
4880 /* fill the buffer with the structures */
4881 smb_io_printer_info_5("", buffer, printer, 0);
4883 /* clear memory */
4884 free_printer_info_5(printer);
4886 if (*needed > offered) {
4887 return WERR_INSUFFICIENT_BUFFER;
4890 return WERR_OK;
4893 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4895 PRINTER_INFO_7 *printer=NULL;
4897 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4898 return WERR_NOMEM;
4900 if (!construct_printer_info_7(print_hnd, printer, snum))
4901 return WERR_NOMEM;
4903 /* check the required size. */
4904 *needed += spoolss_size_printer_info_7(printer);
4906 if (!alloc_buffer_size(buffer, *needed)) {
4907 free_printer_info_7(printer);
4908 return WERR_INSUFFICIENT_BUFFER;
4911 /* fill the buffer with the structures */
4912 smb_io_printer_info_7("", buffer, printer, 0);
4914 /* clear memory */
4915 free_printer_info_7(printer);
4917 if (*needed > offered) {
4918 return WERR_INSUFFICIENT_BUFFER;
4921 return WERR_OK;
4924 /****************************************************************************
4925 ****************************************************************************/
4927 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4929 POLICY_HND *handle = &q_u->handle;
4930 uint32 level = q_u->level;
4931 NEW_BUFFER *buffer = NULL;
4932 uint32 offered = q_u->offered;
4933 uint32 *needed = &r_u->needed;
4934 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4936 int snum;
4938 /* that's an [in out] buffer */
4939 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4940 buffer = r_u->buffer;
4942 *needed=0;
4944 if (!get_printer_snum(p, handle, &snum))
4945 return WERR_BADFID;
4947 switch (level) {
4948 case 0:
4949 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4950 case 1:
4951 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4952 case 2:
4953 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4954 case 3:
4955 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4956 case 4:
4957 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4958 case 5:
4959 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4960 case 7:
4961 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4963 return WERR_UNKNOWN_LEVEL;
4966 /********************************************************************
4967 * fill a DRIVER_INFO_1 struct
4968 ********************************************************************/
4970 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4972 init_unistr( &info->name, driver.info_3->name);
4975 /********************************************************************
4976 * construct_printer_driver_info_1
4977 ********************************************************************/
4979 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4981 NT_PRINTER_INFO_LEVEL *printer = NULL;
4982 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4984 ZERO_STRUCT(driver);
4986 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4987 return WERR_INVALID_PRINTER_NAME;
4989 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4990 return WERR_UNKNOWN_PRINTER_DRIVER;
4992 fill_printer_driver_info_1(info, driver, servername, architecture);
4994 free_a_printer(&printer,2);
4996 return WERR_OK;
4999 /********************************************************************
5000 * construct_printer_driver_info_2
5001 * fill a printer_info_2 struct
5002 ********************************************************************/
5004 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5006 pstring temp;
5008 info->version=driver.info_3->cversion;
5010 init_unistr( &info->name, driver.info_3->name );
5011 init_unistr( &info->architecture, driver.info_3->environment );
5014 if (strlen(driver.info_3->driverpath)) {
5015 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5016 init_unistr( &info->driverpath, temp );
5017 } else
5018 init_unistr( &info->driverpath, "" );
5020 if (strlen(driver.info_3->datafile)) {
5021 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5022 init_unistr( &info->datafile, temp );
5023 } else
5024 init_unistr( &info->datafile, "" );
5026 if (strlen(driver.info_3->configfile)) {
5027 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5028 init_unistr( &info->configfile, temp );
5029 } else
5030 init_unistr( &info->configfile, "" );
5033 /********************************************************************
5034 * construct_printer_driver_info_2
5035 * fill a printer_info_2 struct
5036 ********************************************************************/
5038 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5040 NT_PRINTER_INFO_LEVEL *printer = NULL;
5041 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5043 ZERO_STRUCT(printer);
5044 ZERO_STRUCT(driver);
5046 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5047 return WERR_INVALID_PRINTER_NAME;
5049 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5050 return WERR_UNKNOWN_PRINTER_DRIVER;
5052 fill_printer_driver_info_2(info, driver, servername);
5054 free_a_printer(&printer,2);
5056 return WERR_OK;
5059 /********************************************************************
5060 * copy a strings array and convert to UNICODE
5062 * convert an array of ascii string to a UNICODE string
5063 ********************************************************************/
5065 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5067 int i=0;
5068 int j=0;
5069 const char *v;
5070 pstring line;
5071 uint16 *tuary;
5073 DEBUG(6,("init_unistr_array\n"));
5074 *uni_array=NULL;
5076 while (True)
5078 if ( !char_array )
5079 v = "";
5080 else
5082 v = char_array[i];
5083 if (!v)
5084 v = ""; /* hack to handle null lists */
5087 /* hack to allow this to be used in places other than when generating
5088 the list of dependent files */
5090 if ( servername )
5091 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5092 else
5093 pstrcpy( line, v );
5095 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
5097 /* add one extra unit16 for the second terminating NULL */
5099 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5100 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5101 return 0;
5102 } else
5103 *uni_array = tuary;
5105 if ( !strlen(v) )
5106 break;
5108 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5109 i++;
5112 if (*uni_array) {
5113 /* special case for ""; we need to add both NULL's here */
5114 if (!j)
5115 (*uni_array)[j++]=0x0000;
5116 (*uni_array)[j]=0x0000;
5119 DEBUGADD(6,("last one:done\n"));
5121 /* return size of array in uint16's */
5123 return j+1;
5126 /********************************************************************
5127 * construct_printer_info_3
5128 * fill a printer_info_3 struct
5129 ********************************************************************/
5131 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5133 pstring temp;
5135 ZERO_STRUCTP(info);
5137 info->version=driver.info_3->cversion;
5139 init_unistr( &info->name, driver.info_3->name );
5140 init_unistr( &info->architecture, driver.info_3->environment );
5142 if (strlen(driver.info_3->driverpath)) {
5143 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5144 init_unistr( &info->driverpath, temp );
5145 } else
5146 init_unistr( &info->driverpath, "" );
5148 if (strlen(driver.info_3->datafile)) {
5149 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5150 init_unistr( &info->datafile, temp );
5151 } else
5152 init_unistr( &info->datafile, "" );
5154 if (strlen(driver.info_3->configfile)) {
5155 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5156 init_unistr( &info->configfile, temp );
5157 } else
5158 init_unistr( &info->configfile, "" );
5160 if (strlen(driver.info_3->helpfile)) {
5161 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5162 init_unistr( &info->helpfile, temp );
5163 } else
5164 init_unistr( &info->helpfile, "" );
5166 init_unistr( &info->monitorname, driver.info_3->monitorname );
5167 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5169 info->dependentfiles=NULL;
5170 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5173 /********************************************************************
5174 * construct_printer_info_3
5175 * fill a printer_info_3 struct
5176 ********************************************************************/
5178 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5180 NT_PRINTER_INFO_LEVEL *printer = NULL;
5181 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5182 WERROR status;
5183 ZERO_STRUCT(driver);
5185 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5186 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5187 if (!W_ERROR_IS_OK(status))
5188 return WERR_INVALID_PRINTER_NAME;
5190 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5191 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5193 #if 0 /* JERRY */
5196 * I put this code in during testing. Helpful when commenting out the
5197 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5198 * as win2k always queries the driver using an infor level of 6.
5199 * I've left it in (but ifdef'd out) because I'll probably
5200 * use it in experimentation again in the future. --jerry 22/01/2002
5203 if (!W_ERROR_IS_OK(status)) {
5205 * Is this a W2k client ?
5207 if (version == 3) {
5208 /* Yes - try again with a WinNT driver. */
5209 version = 2;
5210 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5211 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5213 #endif
5215 if (!W_ERROR_IS_OK(status)) {
5216 free_a_printer(&printer,2);
5217 return WERR_UNKNOWN_PRINTER_DRIVER;
5220 #if 0 /* JERRY */
5222 #endif
5225 fill_printer_driver_info_3(info, driver, servername);
5227 free_a_printer(&printer,2);
5229 return WERR_OK;
5232 /********************************************************************
5233 * construct_printer_info_6
5234 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5235 ********************************************************************/
5237 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5239 pstring temp;
5240 fstring nullstr;
5242 ZERO_STRUCTP(info);
5243 memset(&nullstr, '\0', sizeof(fstring));
5245 info->version=driver.info_3->cversion;
5247 init_unistr( &info->name, driver.info_3->name );
5248 init_unistr( &info->architecture, driver.info_3->environment );
5250 if (strlen(driver.info_3->driverpath)) {
5251 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5252 init_unistr( &info->driverpath, temp );
5253 } else
5254 init_unistr( &info->driverpath, "" );
5256 if (strlen(driver.info_3->datafile)) {
5257 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5258 init_unistr( &info->datafile, temp );
5259 } else
5260 init_unistr( &info->datafile, "" );
5262 if (strlen(driver.info_3->configfile)) {
5263 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5264 init_unistr( &info->configfile, temp );
5265 } else
5266 init_unistr( &info->configfile, "" );
5268 if (strlen(driver.info_3->helpfile)) {
5269 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5270 init_unistr( &info->helpfile, temp );
5271 } else
5272 init_unistr( &info->helpfile, "" );
5274 init_unistr( &info->monitorname, driver.info_3->monitorname );
5275 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5277 info->dependentfiles = NULL;
5278 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5280 info->previousdrivernames=NULL;
5281 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5283 info->driver_date.low=0;
5284 info->driver_date.high=0;
5286 info->padding=0;
5287 info->driver_version_low=0;
5288 info->driver_version_high=0;
5290 init_unistr( &info->mfgname, "");
5291 init_unistr( &info->oem_url, "");
5292 init_unistr( &info->hardware_id, "");
5293 init_unistr( &info->provider, "");
5296 /********************************************************************
5297 * construct_printer_info_6
5298 * fill a printer_info_6 struct
5299 ********************************************************************/
5301 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5302 fstring servername, fstring architecture, uint32 version)
5304 NT_PRINTER_INFO_LEVEL *printer = NULL;
5305 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5306 WERROR status;
5308 ZERO_STRUCT(driver);
5310 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5312 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5314 if (!W_ERROR_IS_OK(status))
5315 return WERR_INVALID_PRINTER_NAME;
5317 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5319 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5321 if (!W_ERROR_IS_OK(status))
5324 * Is this a W2k client ?
5327 if (version < 3) {
5328 free_a_printer(&printer,2);
5329 return WERR_UNKNOWN_PRINTER_DRIVER;
5332 /* Yes - try again with a WinNT driver. */
5333 version = 2;
5334 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5335 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5336 if (!W_ERROR_IS_OK(status)) {
5337 free_a_printer(&printer,2);
5338 return WERR_UNKNOWN_PRINTER_DRIVER;
5342 fill_printer_driver_info_6(info, driver, servername);
5344 free_a_printer(&printer,2);
5345 free_a_printer_driver(driver, 3);
5347 return WERR_OK;
5350 /****************************************************************************
5351 ****************************************************************************/
5353 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5355 SAFE_FREE(info->dependentfiles);
5358 /****************************************************************************
5359 ****************************************************************************/
5361 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5363 SAFE_FREE(info->dependentfiles);
5367 /****************************************************************************
5368 ****************************************************************************/
5370 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5372 DRIVER_INFO_1 *info=NULL;
5373 WERROR status;
5375 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5376 return WERR_NOMEM;
5378 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5379 if (!W_ERROR_IS_OK(status)) {
5380 SAFE_FREE(info);
5381 return status;
5384 /* check the required size. */
5385 *needed += spoolss_size_printer_driver_info_1(info);
5387 if (!alloc_buffer_size(buffer, *needed)) {
5388 SAFE_FREE(info);
5389 return WERR_INSUFFICIENT_BUFFER;
5392 /* fill the buffer with the structures */
5393 smb_io_printer_driver_info_1("", buffer, info, 0);
5395 /* clear memory */
5396 SAFE_FREE(info);
5398 if (*needed > offered)
5399 return WERR_INSUFFICIENT_BUFFER;
5401 return WERR_OK;
5404 /****************************************************************************
5405 ****************************************************************************/
5407 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5409 DRIVER_INFO_2 *info=NULL;
5410 WERROR status;
5412 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5413 return WERR_NOMEM;
5415 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5416 if (!W_ERROR_IS_OK(status)) {
5417 SAFE_FREE(info);
5418 return status;
5421 /* check the required size. */
5422 *needed += spoolss_size_printer_driver_info_2(info);
5424 if (!alloc_buffer_size(buffer, *needed)) {
5425 SAFE_FREE(info);
5426 return WERR_INSUFFICIENT_BUFFER;
5429 /* fill the buffer with the structures */
5430 smb_io_printer_driver_info_2("", buffer, info, 0);
5432 /* clear memory */
5433 SAFE_FREE(info);
5435 if (*needed > offered)
5436 return WERR_INSUFFICIENT_BUFFER;
5438 return WERR_OK;
5441 /****************************************************************************
5442 ****************************************************************************/
5444 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5446 DRIVER_INFO_3 info;
5447 WERROR status;
5449 ZERO_STRUCT(info);
5451 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5452 if (!W_ERROR_IS_OK(status)) {
5453 return status;
5456 /* check the required size. */
5457 *needed += spoolss_size_printer_driver_info_3(&info);
5459 if (!alloc_buffer_size(buffer, *needed)) {
5460 free_printer_driver_info_3(&info);
5461 return WERR_INSUFFICIENT_BUFFER;
5464 /* fill the buffer with the structures */
5465 smb_io_printer_driver_info_3("", buffer, &info, 0);
5467 free_printer_driver_info_3(&info);
5469 if (*needed > offered)
5470 return WERR_INSUFFICIENT_BUFFER;
5472 return WERR_OK;
5475 /****************************************************************************
5476 ****************************************************************************/
5478 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5480 DRIVER_INFO_6 info;
5481 WERROR status;
5483 ZERO_STRUCT(info);
5485 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5486 if (!W_ERROR_IS_OK(status)) {
5487 return status;
5490 /* check the required size. */
5491 *needed += spoolss_size_printer_driver_info_6(&info);
5493 if (!alloc_buffer_size(buffer, *needed)) {
5494 free_printer_driver_info_6(&info);
5495 return WERR_INSUFFICIENT_BUFFER;
5498 /* fill the buffer with the structures */
5499 smb_io_printer_driver_info_6("", buffer, &info, 0);
5501 free_printer_driver_info_6(&info);
5503 if (*needed > offered)
5504 return WERR_INSUFFICIENT_BUFFER;
5506 return WERR_OK;
5509 /****************************************************************************
5510 ****************************************************************************/
5512 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5514 POLICY_HND *handle = &q_u->handle;
5515 UNISTR2 *uni_arch = &q_u->architecture;
5516 uint32 level = q_u->level;
5517 uint32 clientmajorversion = q_u->clientmajorversion;
5518 NEW_BUFFER *buffer = NULL;
5519 uint32 offered = q_u->offered;
5520 uint32 *needed = &r_u->needed;
5521 uint32 *servermajorversion = &r_u->servermajorversion;
5522 uint32 *serverminorversion = &r_u->serverminorversion;
5524 fstring servername;
5525 fstring architecture;
5526 int snum;
5528 /* that's an [in out] buffer */
5529 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5530 buffer = r_u->buffer;
5532 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5534 *needed = 0;
5535 *servermajorversion = 0;
5536 *serverminorversion = 0;
5538 fstrcpy(servername, get_called_name());
5539 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5541 if (!get_printer_snum(p, handle, &snum))
5542 return WERR_BADFID;
5544 switch (level) {
5545 case 1:
5546 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5547 case 2:
5548 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5549 case 3:
5550 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5551 case 6:
5552 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5555 return WERR_UNKNOWN_LEVEL;
5558 /****************************************************************************
5559 ****************************************************************************/
5561 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5563 POLICY_HND *handle = &q_u->handle;
5565 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5567 if (!Printer) {
5568 DEBUG(3,("Error in startpageprinter printer handle\n"));
5569 return WERR_BADFID;
5572 Printer->page_started=True;
5573 return WERR_OK;
5576 /****************************************************************************
5577 ****************************************************************************/
5579 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5581 POLICY_HND *handle = &q_u->handle;
5582 int snum;
5584 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5586 if (!Printer) {
5587 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5588 return WERR_BADFID;
5591 if (!get_printer_snum(p, handle, &snum))
5592 return WERR_BADFID;
5594 Printer->page_started=False;
5595 print_job_endpage(snum, Printer->jobid);
5597 return WERR_OK;
5600 /********************************************************************
5601 * api_spoolss_getprinter
5602 * called from the spoolss dispatcher
5604 ********************************************************************/
5606 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5608 POLICY_HND *handle = &q_u->handle;
5609 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5610 uint32 *jobid = &r_u->jobid;
5612 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5613 int snum;
5614 pstring jobname;
5615 fstring datatype;
5616 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5617 struct current_user user;
5619 if (!Printer) {
5620 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5621 return WERR_BADFID;
5624 get_current_user(&user, p);
5627 * a nice thing with NT is it doesn't listen to what you tell it.
5628 * when asked to send _only_ RAW datas, it tries to send datas
5629 * in EMF format.
5631 * So I add checks like in NT Server ...
5634 if (info_1->p_datatype != 0) {
5635 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5636 if (strcmp(datatype, "RAW") != 0) {
5637 (*jobid)=0;
5638 return WERR_INVALID_DATATYPE;
5642 /* get the share number of the printer */
5643 if (!get_printer_snum(p, handle, &snum)) {
5644 return WERR_BADFID;
5647 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5649 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5651 /* An error occured in print_job_start() so return an appropriate
5652 NT error code. */
5654 if (Printer->jobid == -1) {
5655 return map_werror_from_unix(errno);
5658 Printer->document_started=True;
5659 (*jobid) = Printer->jobid;
5661 return WERR_OK;
5664 /********************************************************************
5665 * api_spoolss_getprinter
5666 * called from the spoolss dispatcher
5668 ********************************************************************/
5670 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5672 POLICY_HND *handle = &q_u->handle;
5674 return _spoolss_enddocprinter_internal(p, handle);
5677 /****************************************************************************
5678 ****************************************************************************/
5680 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5682 POLICY_HND *handle = &q_u->handle;
5683 uint32 buffer_size = q_u->buffer_size;
5684 uint8 *buffer = q_u->buffer;
5685 uint32 *buffer_written = &q_u->buffer_size2;
5686 int snum;
5687 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5689 if (!Printer) {
5690 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5691 r_u->buffer_written = q_u->buffer_size2;
5692 return WERR_BADFID;
5695 if (!get_printer_snum(p, handle, &snum))
5696 return WERR_BADFID;
5698 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5699 if (*buffer_written == -1) {
5700 r_u->buffer_written = 0;
5701 if (errno == ENOSPC)
5702 return WERR_NO_SPOOL_SPACE;
5703 else
5704 return WERR_ACCESS_DENIED;
5707 r_u->buffer_written = q_u->buffer_size2;
5709 return WERR_OK;
5712 /********************************************************************
5713 * api_spoolss_getprinter
5714 * called from the spoolss dispatcher
5716 ********************************************************************/
5718 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5719 pipes_struct *p)
5721 struct current_user user;
5722 int snum;
5723 WERROR errcode = WERR_BADFUNC;
5724 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5726 get_current_user(&user, p);
5728 if (!Printer) {
5729 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5730 return WERR_BADFID;
5733 if (!get_printer_snum(p, handle, &snum))
5734 return WERR_BADFID;
5736 switch (command) {
5737 case PRINTER_CONTROL_PAUSE:
5738 if (print_queue_pause(&user, snum, &errcode)) {
5739 errcode = WERR_OK;
5741 break;
5742 case PRINTER_CONTROL_RESUME:
5743 case PRINTER_CONTROL_UNPAUSE:
5744 if (print_queue_resume(&user, snum, &errcode)) {
5745 errcode = WERR_OK;
5747 break;
5748 case PRINTER_CONTROL_PURGE:
5749 if (print_queue_purge(&user, snum, &errcode)) {
5750 errcode = WERR_OK;
5752 break;
5753 default:
5754 return WERR_UNKNOWN_LEVEL;
5757 return errcode;
5760 /********************************************************************
5761 * api_spoolss_abortprinter
5762 * From MSDN: "Deletes printer's spool file if printer is configured
5763 * for spooling"
5764 ********************************************************************/
5766 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5768 POLICY_HND *handle = &q_u->handle;
5769 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5770 int snum;
5771 struct current_user user;
5772 WERROR errcode = WERR_OK;
5774 if (!Printer) {
5775 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5776 return WERR_BADFID;
5779 if (!get_printer_snum(p, handle, &snum))
5780 return WERR_BADFID;
5782 get_current_user( &user, p );
5784 print_job_delete( &user, snum, Printer->jobid, &errcode );
5786 return errcode;
5789 /********************************************************************
5790 * called by spoolss_api_setprinter
5791 * when updating a printer description
5792 ********************************************************************/
5794 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5795 const SPOOL_PRINTER_INFO_LEVEL *info,
5796 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5798 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5799 struct current_user user;
5800 WERROR result;
5801 int snum;
5803 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5805 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5806 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5807 OUR_HANDLE(handle)));
5809 result = WERR_BADFID;
5810 goto done;
5813 /* NT seems to like setting the security descriptor even though
5814 nothing may have actually changed. This causes annoying
5815 dialog boxes when the user doesn't have permission to change
5816 the security descriptor. */
5818 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5820 if (DEBUGLEVEL >= 10) {
5821 SEC_ACL *the_acl;
5822 int i;
5824 the_acl = old_secdesc_ctr->sec->dacl;
5825 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5826 PRINTERNAME(snum), the_acl->num_aces));
5828 for (i = 0; i < the_acl->num_aces; i++) {
5829 fstring sid_str;
5831 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5833 DEBUG(10, ("%s 0x%08x\n", sid_str,
5834 the_acl->ace[i].info.mask));
5837 the_acl = secdesc_ctr->sec->dacl;
5839 if (the_acl) {
5840 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5841 PRINTERNAME(snum), the_acl->num_aces));
5843 for (i = 0; i < the_acl->num_aces; i++) {
5844 fstring sid_str;
5846 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5848 DEBUG(10, ("%s 0x%08x\n", sid_str,
5849 the_acl->ace[i].info.mask));
5851 } else {
5852 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5856 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5858 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5859 result = WERR_OK;
5860 goto done;
5863 /* Work out which user is performing the operation */
5865 get_current_user(&user, p);
5867 /* Check the user has permissions to change the security
5868 descriptor. By experimentation with two NT machines, the user
5869 requires Full Access to the printer to change security
5870 information. */
5872 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5873 result = WERR_ACCESS_DENIED;
5874 goto done;
5877 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5879 done:
5881 return result;
5884 /********************************************************************
5885 Do Samba sanity checks on a printer info struct.
5886 this has changed purpose: it now "canonicalises" printer
5887 info from a client rather than just checking it is correct
5888 ********************************************************************/
5890 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5892 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5893 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5895 /* we force some elements to "correct" values */
5896 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5897 fstrcpy(info->sharename, lp_servicename(snum));
5898 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5899 get_called_name(), info->sharename);
5900 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5903 return True;
5906 /****************************************************************************
5907 ****************************************************************************/
5909 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5911 extern userdom_struct current_user_info;
5912 char *cmd = lp_addprinter_cmd();
5913 char **qlines;
5914 pstring command;
5915 int numlines;
5916 int ret;
5917 int fd;
5918 fstring remote_machine = "%m";
5920 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5922 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5923 cmd, printer->info_2->printername, printer->info_2->sharename,
5924 printer->info_2->portname, printer->info_2->drivername,
5925 printer->info_2->location, printer->info_2->comment, remote_machine);
5927 DEBUG(10,("Running [%s]\n", command));
5928 ret = smbrun(command, &fd);
5929 DEBUGADD(10,("returned [%d]\n", ret));
5931 if ( ret != 0 ) {
5932 if (fd != -1)
5933 close(fd);
5934 return False;
5937 numlines = 0;
5938 /* Get lines and convert them back to dos-codepage */
5939 qlines = fd_lines_load(fd, &numlines);
5940 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5941 close(fd);
5943 if(numlines) {
5944 /* Set the portname to what the script says the portname should be. */
5945 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5946 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5948 /* Send SIGHUP to process group... is there a better way? */
5949 kill(0, SIGHUP);
5951 /* reload our services immediately */
5952 reload_services( False );
5955 file_lines_free(qlines);
5956 return True;
5959 /********************************************************************
5960 * Called by spoolss_api_setprinter
5961 * when updating a printer description.
5962 ********************************************************************/
5964 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5965 const SPOOL_PRINTER_INFO_LEVEL *info,
5966 DEVICEMODE *devmode)
5968 int snum;
5969 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5970 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5971 WERROR result;
5972 UNISTR2 buffer;
5973 fstring asc_buffer;
5975 DEBUG(8,("update_printer\n"));
5977 result = WERR_OK;
5979 if (!Printer) {
5980 result = WERR_BADFID;
5981 goto done;
5984 if (!get_printer_snum(p, handle, &snum)) {
5985 result = WERR_BADFID;
5986 goto done;
5989 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5990 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5991 result = WERR_BADFID;
5992 goto done;
5995 DEBUGADD(8,("Converting info_2 struct\n"));
5998 * convert_printer_info converts the incoming
5999 * info from the client and overwrites the info
6000 * just read from the tdb in the pointer 'printer'.
6003 if (!convert_printer_info(info, printer, level)) {
6004 result = WERR_NOMEM;
6005 goto done;
6008 if (devmode) {
6009 /* we have a valid devmode
6010 convert it and link it*/
6012 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6013 if (!convert_devicemode(printer->info_2->printername, devmode,
6014 &printer->info_2->devmode)) {
6015 result = WERR_NOMEM;
6016 goto done;
6020 /* Do sanity check on the requested changes for Samba */
6022 if (!check_printer_ok(printer->info_2, snum)) {
6023 result = WERR_INVALID_PARAM;
6024 goto done;
6027 /* FIXME!!! If the driver has changed we really should verify that
6028 it is installed before doing much else --jerry */
6030 /* Check calling user has permission to update printer description */
6032 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6033 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6034 result = WERR_ACCESS_DENIED;
6035 goto done;
6038 /* Call addprinter hook */
6039 /* Check changes to see if this is really needed */
6041 if ( *lp_addprinter_cmd()
6042 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6043 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6044 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6045 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6047 if ( !add_printer_hook(printer) ) {
6048 result = WERR_ACCESS_DENIED;
6049 goto done;
6053 * make sure we actually reload the services after
6054 * this as smb.conf could have a new section in it
6055 * .... shouldn't .... but could
6057 reload_services(False);
6061 * When a *new* driver is bound to a printer, the drivername is used to
6062 * lookup previously saved driver initialization info, which is then
6063 * bound to the printer, simulating what happens in the Windows arch.
6065 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6067 if (!set_driver_init(printer, 2))
6069 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6070 printer->info_2->drivername));
6073 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6074 printer->info_2->drivername));
6076 notify_printer_driver(snum, printer->info_2->drivername);
6080 * flag which changes actually occured. This is a small subset of
6081 * all the possible changes. We also have to update things in the
6082 * DsSpooler key.
6085 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6086 init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 );
6087 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6088 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6090 notify_printer_comment(snum, printer->info_2->comment);
6093 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6094 init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 );
6095 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6096 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6097 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6098 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6100 notify_printer_sharename(snum, printer->info_2->sharename);
6103 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6104 init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 );
6105 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6106 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6108 notify_printer_port(snum, printer->info_2->portname);
6111 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6112 init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 );
6113 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6114 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6116 notify_printer_location(snum, printer->info_2->location);
6119 /* here we need to update some more DsSpooler keys */
6120 /* uNCName, serverName, shortServerName */
6122 init_unistr2( &buffer, global_myname(), strlen(global_myname())+1 );
6123 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6124 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6125 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6126 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6128 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6129 global_myname(), printer->info_2->sharename );
6130 init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 );
6131 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6132 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6134 /* Update printer info */
6135 result = mod_a_printer(*printer, 2);
6137 done:
6138 free_a_printer(&printer, 2);
6139 free_a_printer(&old_printer, 2);
6142 return result;
6145 /****************************************************************************
6146 ****************************************************************************/
6147 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6148 const SPOOL_PRINTER_INFO_LEVEL *info)
6150 #ifdef HAVE_ADS
6151 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6152 int snum;
6153 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6154 WERROR result;
6156 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6158 result = WERR_OK;
6160 if (!Printer)
6161 return WERR_BADFID;
6163 if (!get_printer_snum(p, handle, &snum))
6164 return WERR_BADFID;
6166 nt_printer_publish(Printer, snum, info7->action);
6168 return WERR_OK;
6169 #else
6170 return WERR_UNKNOWN_LEVEL;
6171 #endif
6173 /****************************************************************************
6174 ****************************************************************************/
6176 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6178 POLICY_HND *handle = &q_u->handle;
6179 uint32 level = q_u->level;
6180 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6181 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6182 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6183 uint32 command = q_u->command;
6185 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6187 if (!Printer) {
6188 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6189 return WERR_BADFID;
6192 /* check the level */
6193 switch (level) {
6194 case 0:
6195 return control_printer(handle, command, p);
6196 case 2:
6197 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6198 case 3:
6199 return update_printer_sec(handle, level, info, p,
6200 secdesc_ctr);
6201 case 7:
6202 return publish_or_unpublish_printer(p, handle, info);
6203 default:
6204 return WERR_UNKNOWN_LEVEL;
6208 /****************************************************************************
6209 ****************************************************************************/
6211 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6213 POLICY_HND *handle = &q_u->handle;
6214 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6216 if (!Printer) {
6217 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6218 return WERR_BADFID;
6221 if (Printer->notify.client_connected==True) {
6222 int snum = -1;
6224 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6225 snum = -1;
6226 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6227 !get_printer_snum(p, handle, &snum) )
6228 return WERR_BADFID;
6230 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6233 Printer->notify.flags=0;
6234 Printer->notify.options=0;
6235 Printer->notify.localmachine[0]='\0';
6236 Printer->notify.printerlocal=0;
6237 if (Printer->notify.option)
6238 free_spool_notify_option(&Printer->notify.option);
6239 Printer->notify.client_connected=False;
6241 return WERR_OK;
6244 /****************************************************************************
6245 ****************************************************************************/
6247 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6249 /* that's an [in out] buffer (despite appearences to the contrary) */
6250 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6252 r_u->needed = 0;
6253 return WERR_INVALID_PARAM; /* this is what a NT server
6254 returns for AddJob. AddJob
6255 must fail on non-local
6256 printers */
6259 /****************************************************************************
6260 ****************************************************************************/
6262 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6263 int position, int snum)
6265 pstring temp_name;
6267 struct tm *t;
6269 t=gmtime(&queue->time);
6270 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6272 job_info->jobid=queue->job;
6273 init_unistr(&job_info->printername, lp_servicename(snum));
6274 init_unistr(&job_info->machinename, temp_name);
6275 init_unistr(&job_info->username, queue->fs_user);
6276 init_unistr(&job_info->document, queue->fs_file);
6277 init_unistr(&job_info->datatype, "RAW");
6278 init_unistr(&job_info->text_status, "");
6279 job_info->status=nt_printj_status(queue->status);
6280 job_info->priority=queue->priority;
6281 job_info->position=position;
6282 job_info->totalpages=queue->page_count;
6283 job_info->pagesprinted=0;
6285 make_systemtime(&job_info->submitted, t);
6288 /****************************************************************************
6289 ****************************************************************************/
6291 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6292 int position, int snum,
6293 NT_PRINTER_INFO_LEVEL *ntprinter,
6294 DEVICEMODE *devmode)
6296 pstring temp_name;
6297 struct tm *t;
6299 t=gmtime(&queue->time);
6300 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6302 job_info->jobid=queue->job;
6304 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6306 init_unistr(&job_info->machinename, temp_name);
6307 init_unistr(&job_info->username, queue->fs_user);
6308 init_unistr(&job_info->document, queue->fs_file);
6309 init_unistr(&job_info->notifyname, queue->fs_user);
6310 init_unistr(&job_info->datatype, "RAW");
6311 init_unistr(&job_info->printprocessor, "winprint");
6312 init_unistr(&job_info->parameters, "");
6313 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6314 init_unistr(&job_info->text_status, "");
6316 /* and here the security descriptor */
6318 job_info->status=nt_printj_status(queue->status);
6319 job_info->priority=queue->priority;
6320 job_info->position=position;
6321 job_info->starttime=0;
6322 job_info->untiltime=0;
6323 job_info->totalpages=queue->page_count;
6324 job_info->size=queue->size;
6325 make_systemtime(&(job_info->submitted), t);
6326 job_info->timeelapsed=0;
6327 job_info->pagesprinted=0;
6329 job_info->devmode = devmode;
6331 return (True);
6334 /****************************************************************************
6335 Enumjobs at level 1.
6336 ****************************************************************************/
6338 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6339 NEW_BUFFER *buffer, uint32 offered,
6340 uint32 *needed, uint32 *returned)
6342 JOB_INFO_1 *info;
6343 int i;
6345 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6346 if (info==NULL) {
6347 SAFE_FREE(queue);
6348 *returned=0;
6349 return WERR_NOMEM;
6352 for (i=0; i<*returned; i++)
6353 fill_job_info_1(&info[i], &queue[i], i, snum);
6355 SAFE_FREE(queue);
6357 /* check the required size. */
6358 for (i=0; i<*returned; i++)
6359 (*needed) += spoolss_size_job_info_1(&info[i]);
6361 if (!alloc_buffer_size(buffer, *needed)) {
6362 SAFE_FREE(info);
6363 return WERR_INSUFFICIENT_BUFFER;
6366 /* fill the buffer with the structures */
6367 for (i=0; i<*returned; i++)
6368 smb_io_job_info_1("", buffer, &info[i], 0);
6370 /* clear memory */
6371 SAFE_FREE(info);
6373 if (*needed > offered) {
6374 *returned=0;
6375 return WERR_INSUFFICIENT_BUFFER;
6378 return WERR_OK;
6381 /****************************************************************************
6382 Enumjobs at level 2.
6383 ****************************************************************************/
6385 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6386 NEW_BUFFER *buffer, uint32 offered,
6387 uint32 *needed, uint32 *returned)
6389 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6390 JOB_INFO_2 *info = NULL;
6391 int i;
6392 WERROR result;
6393 DEVICEMODE *devmode = NULL;
6395 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6396 if (info==NULL) {
6397 *returned=0;
6398 result = WERR_NOMEM;
6399 goto done;
6402 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6403 if (!W_ERROR_IS_OK(result)) {
6404 *returned = 0;
6405 goto done;
6408 /* this should not be a failure condition if the devmode is NULL */
6410 devmode = construct_dev_mode(snum);
6412 for (i=0; i<*returned; i++)
6413 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6414 devmode);
6416 free_a_printer(&ntprinter, 2);
6417 SAFE_FREE(queue);
6419 /* check the required size. */
6420 for (i=0; i<*returned; i++)
6421 (*needed) += spoolss_size_job_info_2(&info[i]);
6423 if (*needed > offered) {
6424 *returned=0;
6425 result = WERR_INSUFFICIENT_BUFFER;
6426 goto done;
6429 if (!alloc_buffer_size(buffer, *needed)) {
6430 SAFE_FREE(info);
6431 result = WERR_INSUFFICIENT_BUFFER;
6432 goto done;
6435 /* fill the buffer with the structures */
6436 for (i=0; i<*returned; i++)
6437 smb_io_job_info_2("", buffer, &info[i], 0);
6439 result = WERR_OK;
6441 done:
6442 free_a_printer(&ntprinter, 2);
6443 free_devmode(devmode);
6444 SAFE_FREE(queue);
6445 SAFE_FREE(info);
6447 return result;
6451 /****************************************************************************
6452 Enumjobs.
6453 ****************************************************************************/
6455 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6457 POLICY_HND *handle = &q_u->handle;
6458 uint32 level = q_u->level;
6459 NEW_BUFFER *buffer = NULL;
6460 uint32 offered = q_u->offered;
6461 uint32 *needed = &r_u->needed;
6462 uint32 *returned = &r_u->returned;
6463 WERROR wret;
6465 int snum;
6466 print_status_struct prt_status;
6467 print_queue_struct *queue=NULL;
6469 /* that's an [in out] buffer */
6470 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6471 buffer = r_u->buffer;
6473 DEBUG(4,("_spoolss_enumjobs\n"));
6475 *needed=0;
6476 *returned=0;
6478 if (!get_printer_snum(p, handle, &snum))
6479 return WERR_BADFID;
6481 *returned = print_queue_status(snum, &queue, &prt_status);
6482 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6484 if (*returned == 0) {
6485 set_enumjobs_timestamp(snum);
6486 SAFE_FREE(queue);
6487 return WERR_OK;
6490 switch (level) {
6491 case 1:
6492 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6493 set_enumjobs_timestamp(snum);
6494 return wret;
6495 case 2:
6496 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6497 set_enumjobs_timestamp(snum);
6498 return wret;
6499 default:
6500 SAFE_FREE(queue);
6501 *returned=0;
6502 return WERR_UNKNOWN_LEVEL;
6506 /****************************************************************************
6507 ****************************************************************************/
6509 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6511 return WERR_OK;
6514 /****************************************************************************
6515 ****************************************************************************/
6517 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6519 POLICY_HND *handle = &q_u->handle;
6520 uint32 jobid = q_u->jobid;
6521 uint32 command = q_u->command;
6523 struct current_user user;
6524 int snum;
6525 WERROR errcode = WERR_BADFUNC;
6527 if (!get_printer_snum(p, handle, &snum)) {
6528 return WERR_BADFID;
6531 if (!print_job_exists(snum, jobid)) {
6532 return WERR_INVALID_PRINTER_NAME;
6535 get_current_user(&user, p);
6537 switch (command) {
6538 case JOB_CONTROL_CANCEL:
6539 case JOB_CONTROL_DELETE:
6540 if (print_job_delete(&user, snum, jobid, &errcode)) {
6541 errcode = WERR_OK;
6543 break;
6544 case JOB_CONTROL_PAUSE:
6545 if (print_job_pause(&user, snum, jobid, &errcode)) {
6546 errcode = WERR_OK;
6548 break;
6549 case JOB_CONTROL_RESTART:
6550 case JOB_CONTROL_RESUME:
6551 if (print_job_resume(&user, snum, jobid, &errcode)) {
6552 errcode = WERR_OK;
6554 break;
6555 default:
6556 return WERR_UNKNOWN_LEVEL;
6559 return errcode;
6562 /****************************************************************************
6563 Enumerates all printer drivers at level 1.
6564 ****************************************************************************/
6566 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6568 int i;
6569 int ndrivers;
6570 uint32 version;
6571 fstring *list = NULL;
6573 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6574 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6576 *returned=0;
6578 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6579 list=NULL;
6580 ndrivers=get_ntdrivers(&list, architecture, version);
6581 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6583 if(ndrivers == -1)
6584 return WERR_NOMEM;
6586 if(ndrivers != 0) {
6587 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6588 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6589 SAFE_FREE(driver_info_1);
6590 SAFE_FREE(list);
6591 return WERR_NOMEM;
6593 else driver_info_1 = tdi1;
6596 for (i=0; i<ndrivers; i++) {
6597 WERROR status;
6598 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6599 ZERO_STRUCT(driver);
6600 status = get_a_printer_driver(&driver, 3, list[i],
6601 architecture, version);
6602 if (!W_ERROR_IS_OK(status)) {
6603 SAFE_FREE(list);
6604 return status;
6606 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6607 free_a_printer_driver(driver, 3);
6610 *returned+=ndrivers;
6611 SAFE_FREE(list);
6614 /* check the required size. */
6615 for (i=0; i<*returned; i++) {
6616 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6617 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6620 if (!alloc_buffer_size(buffer, *needed)) {
6621 SAFE_FREE(driver_info_1);
6622 return WERR_INSUFFICIENT_BUFFER;
6625 /* fill the buffer with the driver structures */
6626 for (i=0; i<*returned; i++) {
6627 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6628 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6631 SAFE_FREE(driver_info_1);
6633 if (*needed > offered) {
6634 *returned=0;
6635 return WERR_INSUFFICIENT_BUFFER;
6638 return WERR_OK;
6641 /****************************************************************************
6642 Enumerates all printer drivers at level 2.
6643 ****************************************************************************/
6645 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6647 int i;
6648 int ndrivers;
6649 uint32 version;
6650 fstring *list = NULL;
6652 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6653 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6655 *returned=0;
6657 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6658 list=NULL;
6659 ndrivers=get_ntdrivers(&list, architecture, version);
6660 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6662 if(ndrivers == -1)
6663 return WERR_NOMEM;
6665 if(ndrivers != 0) {
6666 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6667 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6668 SAFE_FREE(driver_info_2);
6669 SAFE_FREE(list);
6670 return WERR_NOMEM;
6672 else driver_info_2 = tdi2;
6675 for (i=0; i<ndrivers; i++) {
6676 WERROR status;
6678 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6679 ZERO_STRUCT(driver);
6680 status = get_a_printer_driver(&driver, 3, list[i],
6681 architecture, version);
6682 if (!W_ERROR_IS_OK(status)) {
6683 SAFE_FREE(list);
6684 return status;
6686 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6687 free_a_printer_driver(driver, 3);
6690 *returned+=ndrivers;
6691 SAFE_FREE(list);
6694 /* check the required size. */
6695 for (i=0; i<*returned; i++) {
6696 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6697 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6700 if (!alloc_buffer_size(buffer, *needed)) {
6701 SAFE_FREE(driver_info_2);
6702 return WERR_INSUFFICIENT_BUFFER;
6705 /* fill the buffer with the form structures */
6706 for (i=0; i<*returned; i++) {
6707 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6708 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6711 SAFE_FREE(driver_info_2);
6713 if (*needed > offered) {
6714 *returned=0;
6715 return WERR_INSUFFICIENT_BUFFER;
6718 return WERR_OK;
6721 /****************************************************************************
6722 Enumerates all printer drivers at level 3.
6723 ****************************************************************************/
6725 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6727 int i;
6728 int ndrivers;
6729 uint32 version;
6730 fstring *list = NULL;
6732 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6733 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6735 *returned=0;
6737 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6738 list=NULL;
6739 ndrivers=get_ntdrivers(&list, architecture, version);
6740 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6742 if(ndrivers == -1)
6743 return WERR_NOMEM;
6745 if(ndrivers != 0) {
6746 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6747 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6748 SAFE_FREE(driver_info_3);
6749 SAFE_FREE(list);
6750 return WERR_NOMEM;
6752 else driver_info_3 = tdi3;
6755 for (i=0; i<ndrivers; i++) {
6756 WERROR status;
6758 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6759 ZERO_STRUCT(driver);
6760 status = get_a_printer_driver(&driver, 3, list[i],
6761 architecture, version);
6762 if (!W_ERROR_IS_OK(status)) {
6763 SAFE_FREE(list);
6764 return status;
6766 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6767 free_a_printer_driver(driver, 3);
6770 *returned+=ndrivers;
6771 SAFE_FREE(list);
6774 /* check the required size. */
6775 for (i=0; i<*returned; i++) {
6776 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6777 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6780 if (!alloc_buffer_size(buffer, *needed)) {
6781 SAFE_FREE(driver_info_3);
6782 return WERR_INSUFFICIENT_BUFFER;
6785 /* fill the buffer with the driver structures */
6786 for (i=0; i<*returned; i++) {
6787 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6788 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6791 for (i=0; i<*returned; i++)
6792 SAFE_FREE(driver_info_3[i].dependentfiles);
6794 SAFE_FREE(driver_info_3);
6796 if (*needed > offered) {
6797 *returned=0;
6798 return WERR_INSUFFICIENT_BUFFER;
6801 return WERR_OK;
6804 /****************************************************************************
6805 Enumerates all printer drivers.
6806 ****************************************************************************/
6808 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6810 UNISTR2 *environment = &q_u->environment;
6811 uint32 level = q_u->level;
6812 NEW_BUFFER *buffer = NULL;
6813 uint32 offered = q_u->offered;
6814 uint32 *needed = &r_u->needed;
6815 uint32 *returned = &r_u->returned;
6817 fstring *list = NULL;
6818 fstring servername;
6819 fstring architecture;
6821 /* that's an [in out] buffer */
6822 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6823 buffer = r_u->buffer;
6825 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6826 fstrcpy(servername, get_called_name());
6827 *needed=0;
6828 *returned=0;
6830 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6832 switch (level) {
6833 case 1:
6834 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6835 case 2:
6836 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6837 case 3:
6838 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6839 default:
6840 *returned=0;
6841 SAFE_FREE(list);
6842 return WERR_UNKNOWN_LEVEL;
6846 /****************************************************************************
6847 ****************************************************************************/
6849 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6851 form->flag=list->flag;
6852 init_unistr(&form->name, list->name);
6853 form->width=list->width;
6854 form->length=list->length;
6855 form->left=list->left;
6856 form->top=list->top;
6857 form->right=list->right;
6858 form->bottom=list->bottom;
6861 /****************************************************************************
6862 ****************************************************************************/
6864 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6866 uint32 level = q_u->level;
6867 NEW_BUFFER *buffer = NULL;
6868 uint32 offered = q_u->offered;
6869 uint32 *needed = &r_u->needed;
6870 uint32 *numofforms = &r_u->numofforms;
6871 uint32 numbuiltinforms;
6873 nt_forms_struct *list=NULL;
6874 nt_forms_struct *builtinlist=NULL;
6875 FORM_1 *forms_1;
6876 int buffer_size=0;
6877 int i;
6879 /* that's an [in out] buffer */
6880 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6881 buffer = r_u->buffer;
6883 DEBUG(4,("_spoolss_enumforms\n"));
6884 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6885 DEBUGADD(5,("Info level [%d]\n", level));
6887 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6888 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6889 *numofforms = get_ntforms(&list);
6890 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6891 *numofforms += numbuiltinforms;
6893 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6895 switch (level) {
6896 case 1:
6897 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6898 *numofforms=0;
6899 return WERR_NOMEM;
6902 /* construct the list of form structures */
6903 for (i=0; i<numbuiltinforms; i++) {
6904 DEBUGADD(6,("Filling form number [%d]\n",i));
6905 fill_form_1(&forms_1[i], &builtinlist[i]);
6908 SAFE_FREE(builtinlist);
6910 for (; i<*numofforms; i++) {
6911 DEBUGADD(6,("Filling form number [%d]\n",i));
6912 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6915 SAFE_FREE(list);
6917 /* check the required size. */
6918 for (i=0; i<numbuiltinforms; i++) {
6919 DEBUGADD(6,("adding form [%d]'s size\n",i));
6920 buffer_size += spoolss_size_form_1(&forms_1[i]);
6922 for (; i<*numofforms; i++) {
6923 DEBUGADD(6,("adding form [%d]'s size\n",i));
6924 buffer_size += spoolss_size_form_1(&forms_1[i]);
6927 *needed=buffer_size;
6929 if (!alloc_buffer_size(buffer, buffer_size)){
6930 SAFE_FREE(forms_1);
6931 return WERR_INSUFFICIENT_BUFFER;
6934 /* fill the buffer with the form structures */
6935 for (i=0; i<numbuiltinforms; i++) {
6936 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6937 smb_io_form_1("", buffer, &forms_1[i], 0);
6939 for (; i<*numofforms; i++) {
6940 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6941 smb_io_form_1("", buffer, &forms_1[i], 0);
6944 SAFE_FREE(forms_1);
6946 if (*needed > offered) {
6947 *numofforms=0;
6948 return WERR_INSUFFICIENT_BUFFER;
6950 else
6951 return WERR_OK;
6953 default:
6954 SAFE_FREE(list);
6955 SAFE_FREE(builtinlist);
6956 return WERR_UNKNOWN_LEVEL;
6961 /****************************************************************************
6962 ****************************************************************************/
6964 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6966 uint32 level = q_u->level;
6967 UNISTR2 *uni_formname = &q_u->formname;
6968 NEW_BUFFER *buffer = NULL;
6969 uint32 offered = q_u->offered;
6970 uint32 *needed = &r_u->needed;
6972 nt_forms_struct *list=NULL;
6973 nt_forms_struct builtin_form;
6974 BOOL foundBuiltin;
6975 FORM_1 form_1;
6976 fstring form_name;
6977 int buffer_size=0;
6978 int numofforms=0, i=0;
6980 /* that's an [in out] buffer */
6981 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6982 buffer = r_u->buffer;
6984 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6986 DEBUG(4,("_spoolss_getform\n"));
6987 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6988 DEBUGADD(5,("Info level [%d]\n", level));
6990 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6991 if (!foundBuiltin) {
6992 numofforms = get_ntforms(&list);
6993 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6995 if (numofforms == 0)
6996 return WERR_BADFID;
6999 switch (level) {
7000 case 1:
7001 if (foundBuiltin) {
7002 fill_form_1(&form_1, &builtin_form);
7003 } else {
7005 /* Check if the requested name is in the list of form structures */
7006 for (i=0; i<numofforms; i++) {
7008 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7010 if (strequal(form_name, list[i].name)) {
7011 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7012 fill_form_1(&form_1, &list[i]);
7013 break;
7017 SAFE_FREE(list);
7018 if (i == numofforms) {
7019 return WERR_BADFID;
7022 /* check the required size. */
7024 *needed=spoolss_size_form_1(&form_1);
7026 if (!alloc_buffer_size(buffer, buffer_size)){
7027 return WERR_INSUFFICIENT_BUFFER;
7030 if (*needed > offered) {
7031 return WERR_INSUFFICIENT_BUFFER;
7034 /* fill the buffer with the form structures */
7035 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7036 smb_io_form_1("", buffer, &form_1, 0);
7038 return WERR_OK;
7040 default:
7041 SAFE_FREE(list);
7042 return WERR_UNKNOWN_LEVEL;
7046 /****************************************************************************
7047 ****************************************************************************/
7049 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7051 init_unistr(&port->port_name, name);
7054 /****************************************************************************
7055 ****************************************************************************/
7057 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7059 init_unistr(&port->port_name, name);
7060 init_unistr(&port->monitor_name, "Local Monitor");
7061 init_unistr(&port->description, "Local Port");
7062 #define PORT_TYPE_WRITE 1
7063 port->port_type=PORT_TYPE_WRITE;
7064 port->reserved=0x0;
7067 /****************************************************************************
7068 enumports level 1.
7069 ****************************************************************************/
7071 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7073 PORT_INFO_1 *ports=NULL;
7074 int i=0;
7076 if (*lp_enumports_cmd()) {
7077 char *cmd = lp_enumports_cmd();
7078 char **qlines;
7079 pstring command;
7080 int numlines;
7081 int ret;
7082 int fd;
7084 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7086 DEBUG(10,("Running [%s]\n", command));
7087 ret = smbrun(command, &fd);
7088 DEBUG(10,("Returned [%d]\n", ret));
7089 if (ret != 0) {
7090 if (fd != -1)
7091 close(fd);
7092 /* Is this the best error to return here? */
7093 return WERR_ACCESS_DENIED;
7096 numlines = 0;
7097 qlines = fd_lines_load(fd, &numlines);
7098 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7099 close(fd);
7101 if(numlines) {
7102 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7103 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7104 dos_errstr(WERR_NOMEM)));
7105 file_lines_free(qlines);
7106 return WERR_NOMEM;
7109 for (i=0; i<numlines; i++) {
7110 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7111 fill_port_1(&ports[i], qlines[i]);
7114 file_lines_free(qlines);
7117 *returned = numlines;
7119 } else {
7120 *returned = 1; /* Sole Samba port returned. */
7122 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7123 return WERR_NOMEM;
7125 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7127 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7130 /* check the required size. */
7131 for (i=0; i<*returned; i++) {
7132 DEBUGADD(6,("adding port [%d]'s size\n", i));
7133 *needed += spoolss_size_port_info_1(&ports[i]);
7136 if (!alloc_buffer_size(buffer, *needed)) {
7137 SAFE_FREE(ports);
7138 return WERR_INSUFFICIENT_BUFFER;
7141 /* fill the buffer with the ports structures */
7142 for (i=0; i<*returned; i++) {
7143 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7144 smb_io_port_1("", buffer, &ports[i], 0);
7147 SAFE_FREE(ports);
7149 if (*needed > offered) {
7150 *returned=0;
7151 return WERR_INSUFFICIENT_BUFFER;
7154 return WERR_OK;
7157 /****************************************************************************
7158 enumports level 2.
7159 ****************************************************************************/
7161 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7163 PORT_INFO_2 *ports=NULL;
7164 int i=0;
7166 if (*lp_enumports_cmd()) {
7167 char *cmd = lp_enumports_cmd();
7168 char *path;
7169 char **qlines;
7170 pstring tmp_file;
7171 pstring command;
7172 int numlines;
7173 int ret;
7174 int fd;
7176 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7177 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7178 else
7179 path = lp_lockdir();
7181 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7182 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7184 unlink(tmp_file);
7185 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7186 ret = smbrun(command, &fd);
7187 DEBUGADD(10,("returned [%d]\n", ret));
7188 if (ret != 0) {
7189 if (fd != -1)
7190 close(fd);
7191 /* Is this the best error to return here? */
7192 return WERR_ACCESS_DENIED;
7195 numlines = 0;
7196 qlines = fd_lines_load(fd, &numlines);
7197 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7198 close(fd);
7200 if(numlines) {
7201 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7202 file_lines_free(qlines);
7203 return WERR_NOMEM;
7206 for (i=0; i<numlines; i++) {
7207 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7208 fill_port_2(&(ports[i]), qlines[i]);
7211 file_lines_free(qlines);
7214 *returned = numlines;
7216 } else {
7218 *returned = 1;
7220 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7221 return WERR_NOMEM;
7223 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7225 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7228 /* check the required size. */
7229 for (i=0; i<*returned; i++) {
7230 DEBUGADD(6,("adding port [%d]'s size\n", i));
7231 *needed += spoolss_size_port_info_2(&ports[i]);
7234 if (!alloc_buffer_size(buffer, *needed)) {
7235 SAFE_FREE(ports);
7236 return WERR_INSUFFICIENT_BUFFER;
7239 /* fill the buffer with the ports structures */
7240 for (i=0; i<*returned; i++) {
7241 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7242 smb_io_port_2("", buffer, &ports[i], 0);
7245 SAFE_FREE(ports);
7247 if (*needed > offered) {
7248 *returned=0;
7249 return WERR_INSUFFICIENT_BUFFER;
7252 return WERR_OK;
7255 /****************************************************************************
7256 enumports.
7257 ****************************************************************************/
7259 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7261 uint32 level = q_u->level;
7262 NEW_BUFFER *buffer = NULL;
7263 uint32 offered = q_u->offered;
7264 uint32 *needed = &r_u->needed;
7265 uint32 *returned = &r_u->returned;
7267 /* that's an [in out] buffer */
7268 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7269 buffer = r_u->buffer;
7271 DEBUG(4,("_spoolss_enumports\n"));
7273 *returned=0;
7274 *needed=0;
7276 switch (level) {
7277 case 1:
7278 return enumports_level_1(buffer, offered, needed, returned);
7279 case 2:
7280 return enumports_level_2(buffer, offered, needed, returned);
7281 default:
7282 return WERR_UNKNOWN_LEVEL;
7286 /****************************************************************************
7287 ****************************************************************************/
7289 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7290 const SPOOL_PRINTER_INFO_LEVEL *info,
7291 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7292 uint32 user_switch, const SPOOL_USER_CTR *user,
7293 POLICY_HND *handle)
7295 NT_PRINTER_INFO_LEVEL *printer = NULL;
7296 fstring name;
7297 int snum;
7298 WERROR err = WERR_OK;
7300 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7301 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7302 return WERR_NOMEM;
7305 ZERO_STRUCTP(printer);
7307 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7308 if (!convert_printer_info(info, printer, 2)) {
7309 free_a_printer(&printer, 2);
7310 return WERR_NOMEM;
7313 /* check to see if the printer already exists */
7315 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7316 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7317 printer->info_2->sharename));
7318 free_a_printer(&printer, 2);
7319 return WERR_PRINTER_ALREADY_EXISTS;
7322 /* FIXME!!! smbd should check to see if the driver is installed before
7323 trying to add a printer like this --jerry */
7325 if (*lp_addprinter_cmd() ) {
7326 if ( !add_printer_hook(printer) ) {
7327 free_a_printer(&printer,2);
7328 return WERR_ACCESS_DENIED;
7332 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7333 printer->info_2->sharename);
7336 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7337 free_a_printer(&printer,2);
7338 return WERR_ACCESS_DENIED;
7341 /* you must be a printer admin to add a new printer */
7342 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7343 free_a_printer(&printer,2);
7344 return WERR_ACCESS_DENIED;
7348 * Do sanity check on the requested changes for Samba.
7351 if (!check_printer_ok(printer->info_2, snum)) {
7352 free_a_printer(&printer,2);
7353 return WERR_INVALID_PARAM;
7357 * When a printer is created, the drivername bound to the printer is used
7358 * to lookup previously saved driver initialization info, which is then
7359 * bound to the new printer, simulating what happens in the Windows arch.
7362 if (!devmode)
7364 set_driver_init(printer, 2);
7366 else
7368 /* A valid devmode was included, convert and link it
7370 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7372 if (!convert_devicemode(printer->info_2->printername, devmode,
7373 &printer->info_2->devmode))
7374 return WERR_NOMEM;
7377 /* write the ASCII on disk */
7378 err = mod_a_printer(*printer, 2);
7379 if (!W_ERROR_IS_OK(err)) {
7380 free_a_printer(&printer,2);
7381 return err;
7384 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7385 /* Handle open failed - remove addition. */
7386 del_a_printer(printer->info_2->sharename);
7387 free_a_printer(&printer,2);
7388 return WERR_ACCESS_DENIED;
7391 update_c_setprinter(False);
7392 free_a_printer(&printer,2);
7394 return WERR_OK;
7397 /****************************************************************************
7398 ****************************************************************************/
7400 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7402 UNISTR2 *uni_srv_name = &q_u->server_name;
7403 uint32 level = q_u->level;
7404 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7405 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7406 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7407 uint32 user_switch = q_u->user_switch;
7408 SPOOL_USER_CTR *user = &q_u->user_ctr;
7409 POLICY_HND *handle = &r_u->handle;
7411 switch (level) {
7412 case 1:
7413 /* we don't handle yet */
7414 /* but I know what to do ... */
7415 return WERR_UNKNOWN_LEVEL;
7416 case 2:
7417 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7418 devmode, sdb,
7419 user_switch, user, handle);
7420 default:
7421 return WERR_UNKNOWN_LEVEL;
7425 /****************************************************************************
7426 ****************************************************************************/
7428 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7430 uint32 level = q_u->level;
7431 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7432 WERROR err = WERR_OK;
7433 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7434 struct current_user user;
7435 fstring driver_name;
7436 uint32 version;
7438 ZERO_STRUCT(driver);
7440 get_current_user(&user, p);
7442 if (!convert_printer_driver_info(info, &driver, level)) {
7443 err = WERR_NOMEM;
7444 goto done;
7447 DEBUG(5,("Cleaning driver's information\n"));
7448 err = clean_up_driver_struct(driver, level, &user);
7449 if (!W_ERROR_IS_OK(err))
7450 goto done;
7452 DEBUG(5,("Moving driver to final destination\n"));
7453 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7454 if (W_ERROR_IS_OK(err))
7455 err = WERR_ACCESS_DENIED;
7456 goto done;
7459 if (add_a_printer_driver(driver, level)!=0) {
7460 err = WERR_ACCESS_DENIED;
7461 goto done;
7464 /* BEGIN_ADMIN_LOG */
7465 switch(level) {
7466 case 3:
7467 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7468 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7469 fstrcpy(driver_name, driver.info_3->name);
7470 break;
7471 case 6:
7472 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7473 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7474 fstrcpy(driver_name, driver.info_6->name);
7475 break;
7477 /* END_ADMIN_LOG */
7480 * I think this is where he DrvUpgradePrinter() hook would be
7481 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7482 * server. Right now, we just need to send ourselves a message
7483 * to update each printer bound to this driver. --jerry
7486 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7487 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7488 driver_name));
7492 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7493 * decide if the driver init data should be deleted. The rules are:
7494 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7495 * 2) delete init data only if there is no 2k/Xp driver
7496 * 3) always delete init data
7497 * The generalized rule is always use init data from the highest order driver.
7498 * It is necessary to follow the driver install by an initialization step to
7499 * finish off this process.
7501 if (level == 3)
7502 version = driver.info_3->cversion;
7503 else if (level == 6)
7504 version = driver.info_6->version;
7505 else
7506 version = -1;
7507 switch (version) {
7509 * 9x printer driver - never delete init data
7511 case 0:
7512 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7513 driver_name));
7514 break;
7517 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7518 * there is no 2k/Xp driver init data for this driver name.
7520 case 2:
7522 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7524 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7526 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7528 if (!del_driver_init(driver_name))
7529 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7530 } else {
7532 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7534 free_a_printer_driver(driver1,3);
7535 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7536 driver_name));
7539 break;
7542 * 2k or Xp printer driver - always delete init data
7544 case 3:
7545 if (!del_driver_init(driver_name))
7546 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7547 break;
7549 default:
7550 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7551 break;
7555 done:
7556 free_a_printer_driver(driver, level);
7557 return err;
7560 /********************************************************************
7561 * spoolss_addprinterdriverex
7562 ********************************************************************/
7564 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7566 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7567 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7570 * we only support the semantics of AddPrinterDriver()
7571 * i.e. only copy files that are newer than existing ones
7574 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7575 return WERR_ACCESS_DENIED;
7577 ZERO_STRUCT(q_u_local);
7578 ZERO_STRUCT(r_u_local);
7580 /* just pass the information off to _spoolss_addprinterdriver() */
7581 q_u_local.server_name_ptr = q_u->server_name_ptr;
7582 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7583 q_u_local.level = q_u->level;
7584 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7586 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7589 /****************************************************************************
7590 ****************************************************************************/
7592 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7594 init_unistr(&info->name, name);
7597 /****************************************************************************
7598 ****************************************************************************/
7600 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7602 pstring path;
7603 pstring long_archi;
7604 pstring short_archi;
7605 DRIVER_DIRECTORY_1 *info=NULL;
7607 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7609 if (get_short_archi(short_archi, long_archi)==False)
7610 return WERR_INVALID_ENVIRONMENT;
7612 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7613 return WERR_NOMEM;
7615 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7617 DEBUG(4,("printer driver directory: [%s]\n", path));
7619 fill_driverdir_1(info, path);
7621 *needed += spoolss_size_driverdir_info_1(info);
7623 if (!alloc_buffer_size(buffer, *needed)) {
7624 SAFE_FREE(info);
7625 return WERR_INSUFFICIENT_BUFFER;
7628 smb_io_driverdir_1("", buffer, info, 0);
7630 SAFE_FREE(info);
7632 if (*needed > offered)
7633 return WERR_INSUFFICIENT_BUFFER;
7635 return WERR_OK;
7638 /****************************************************************************
7639 ****************************************************************************/
7641 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7643 UNISTR2 *name = &q_u->name;
7644 UNISTR2 *uni_environment = &q_u->environment;
7645 uint32 level = q_u->level;
7646 NEW_BUFFER *buffer = NULL;
7647 uint32 offered = q_u->offered;
7648 uint32 *needed = &r_u->needed;
7650 /* that's an [in out] buffer */
7651 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7652 buffer = r_u->buffer;
7654 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7656 *needed=0;
7658 switch(level) {
7659 case 1:
7660 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7661 default:
7662 return WERR_UNKNOWN_LEVEL;
7666 /****************************************************************************
7667 ****************************************************************************/
7669 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7671 POLICY_HND *handle = &q_u->handle;
7672 uint32 idx = q_u->index;
7673 uint32 in_value_len = q_u->valuesize;
7674 uint32 in_data_len = q_u->datasize;
7675 uint32 *out_max_value_len = &r_u->valuesize;
7676 uint16 **out_value = &r_u->value;
7677 uint32 *out_value_len = &r_u->realvaluesize;
7678 uint32 *out_type = &r_u->type;
7679 uint32 *out_max_data_len = &r_u->datasize;
7680 uint8 **data_out = &r_u->data;
7681 uint32 *out_data_len = &r_u->realdatasize;
7683 NT_PRINTER_INFO_LEVEL *printer = NULL;
7685 uint32 param_index;
7686 uint32 biggest_valuesize;
7687 uint32 biggest_datasize;
7688 uint32 data_len;
7689 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7690 int snum;
7691 WERROR result;
7692 REGISTRY_VALUE *val = NULL;
7693 NT_PRINTER_DATA *p_data;
7694 int i, key_index, num_values;
7695 int name_length;
7697 ZERO_STRUCT( printer );
7699 *out_type = 0;
7701 *out_max_data_len = 0;
7702 *data_out = NULL;
7703 *out_data_len = 0;
7705 DEBUG(5,("spoolss_enumprinterdata\n"));
7707 if (!Printer) {
7708 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7709 return WERR_BADFID;
7712 if (!get_printer_snum(p,handle, &snum))
7713 return WERR_BADFID;
7715 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7716 if (!W_ERROR_IS_OK(result))
7717 return result;
7719 p_data = &printer->info_2->data;
7720 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7722 result = WERR_OK;
7725 * The NT machine wants to know the biggest size of value and data
7727 * cf: MSDN EnumPrinterData remark section
7730 if ( !in_value_len && !in_data_len && (key_index != -1) )
7732 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7734 param_index = 0;
7735 biggest_valuesize = 0;
7736 biggest_datasize = 0;
7738 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7740 for ( i=0; i<num_values; i++ )
7742 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7744 name_length = strlen(val->valuename);
7745 if ( strlen(val->valuename) > biggest_valuesize )
7746 biggest_valuesize = name_length;
7748 if ( val->size > biggest_datasize )
7749 biggest_datasize = val->size;
7751 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7752 biggest_datasize));
7755 /* the value is an UNICODE string but real_value_size is the length
7756 in bytes including the trailing 0 */
7758 *out_value_len = 2 * (1+biggest_valuesize);
7759 *out_data_len = biggest_datasize;
7761 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7763 goto done;
7767 * the value len is wrong in NT sp3
7768 * that's the number of bytes not the number of unicode chars
7771 if ( key_index != -1 )
7772 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7774 if ( !val )
7777 /* out_value should default to "" or else NT4 has
7778 problems unmarshalling the response */
7780 *out_max_value_len=(in_value_len/sizeof(uint16));
7782 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7784 result = WERR_NOMEM;
7785 goto done;
7788 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7790 /* the data is counted in bytes */
7792 *out_max_data_len = in_data_len;
7793 *out_data_len = in_data_len;
7795 /* only allocate when given a non-zero data_len */
7797 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7799 result = WERR_NOMEM;
7800 goto done;
7803 result = WERR_NO_MORE_ITEMS;
7805 else
7808 * the value is:
7809 * - counted in bytes in the request
7810 * - counted in UNICODE chars in the max reply
7811 * - counted in bytes in the real size
7813 * take a pause *before* coding not *during* coding
7816 /* name */
7817 *out_max_value_len=(in_value_len/sizeof(uint16));
7818 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7820 result = WERR_NOMEM;
7821 goto done;
7824 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7826 /* type */
7828 *out_type = regval_type( val );
7830 /* data - counted in bytes */
7832 *out_max_data_len = in_data_len;
7833 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7835 result = WERR_NOMEM;
7836 goto done;
7838 data_len = (size_t)regval_size(val);
7839 memcpy( *data_out, regval_data_p(val), data_len );
7840 *out_data_len = data_len;
7843 done:
7844 free_a_printer(&printer, 2);
7845 return result;
7848 /****************************************************************************
7849 ****************************************************************************/
7851 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7853 POLICY_HND *handle = &q_u->handle;
7854 UNISTR2 *value = &q_u->value;
7855 uint32 type = q_u->type;
7856 uint8 *data = q_u->data;
7857 uint32 real_len = q_u->real_len;
7859 NT_PRINTER_INFO_LEVEL *printer = NULL;
7860 int snum=0;
7861 WERROR status = WERR_OK;
7862 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7863 fstring valuename;
7865 DEBUG(5,("spoolss_setprinterdata\n"));
7867 if (!Printer) {
7868 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7869 return WERR_BADFID;
7872 if (!get_printer_snum(p,handle, &snum))
7873 return WERR_BADFID;
7876 * Access check : NT returns "access denied" if you make a
7877 * SetPrinterData call without the necessary privildge.
7878 * we were originally returning OK if nothing changed
7879 * which made Win2k issue **a lot** of SetPrinterData
7880 * when connecting to a printer --jerry
7883 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7885 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7886 status = WERR_ACCESS_DENIED;
7887 goto done;
7890 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7891 if (!W_ERROR_IS_OK(status))
7892 return status;
7894 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7897 * When client side code sets a magic printer data key, detect it and save
7898 * the current printer data and the magic key's data (its the DEVMODE) for
7899 * future printer/driver initializations.
7901 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7903 /* Set devmode and printer initialization info */
7904 status = save_driver_init( printer, 2, data, real_len );
7906 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7908 else
7910 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7911 type, data, real_len );
7912 if ( W_ERROR_IS_OK(status) )
7913 status = mod_a_printer(*printer, 2);
7916 done:
7917 free_a_printer(&printer, 2);
7919 return status;
7922 /****************************************************************************
7923 ****************************************************************************/
7925 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7927 POLICY_HND *handle = &q_u->handle;
7928 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7929 int snum;
7931 DEBUG(5,("_spoolss_resetprinter\n"));
7934 * All we do is to check to see if the handle and queue is valid.
7935 * This call really doesn't mean anything to us because we only
7936 * support RAW printing. --jerry
7939 if (!Printer) {
7940 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7941 return WERR_BADFID;
7944 if (!get_printer_snum(p,handle, &snum))
7945 return WERR_BADFID;
7948 /* blindly return success */
7949 return WERR_OK;
7953 /****************************************************************************
7954 ****************************************************************************/
7956 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7958 POLICY_HND *handle = &q_u->handle;
7959 UNISTR2 *value = &q_u->valuename;
7961 NT_PRINTER_INFO_LEVEL *printer = NULL;
7962 int snum=0;
7963 WERROR status = WERR_OK;
7964 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7965 pstring valuename;
7967 DEBUG(5,("spoolss_deleteprinterdata\n"));
7969 if (!Printer) {
7970 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7971 return WERR_BADFID;
7974 if (!get_printer_snum(p, handle, &snum))
7975 return WERR_BADFID;
7977 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7978 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7979 return WERR_ACCESS_DENIED;
7982 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7983 if (!W_ERROR_IS_OK(status))
7984 return status;
7986 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7988 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7990 free_a_printer(&printer, 2);
7992 return status;
7995 /****************************************************************************
7996 ****************************************************************************/
7998 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *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_addform\n"));
8013 if (!Printer) {
8014 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8015 return WERR_BADFID;
8019 /* forms can be added on printer of on the print server handle */
8021 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8023 if (!get_printer_snum(p,handle, &snum))
8024 return WERR_BADFID;
8026 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8027 if (!W_ERROR_IS_OK(status))
8028 goto done;
8031 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8032 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8033 status = WERR_ACCESS_DENIED;
8034 goto done;
8037 /* can't add if builtin */
8039 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8040 status = WERR_ALREADY_EXISTS;
8041 goto done;
8044 count = get_ntforms(&list);
8046 if(!add_a_form(&list, form, &count)) {
8047 status = WERR_NOMEM;
8048 goto done;
8051 write_ntforms(&list, count);
8054 * ChangeID must always be set if this is a printer
8057 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8058 status = mod_a_printer(*printer, 2);
8060 done:
8061 if ( printer )
8062 free_a_printer(&printer, 2);
8063 SAFE_FREE(list);
8065 return status;
8068 /****************************************************************************
8069 ****************************************************************************/
8071 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8073 POLICY_HND *handle = &q_u->handle;
8074 UNISTR2 *form_name = &q_u->name;
8075 nt_forms_struct tmpForm;
8076 int count=0;
8077 nt_forms_struct *list=NULL;
8078 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8079 int snum;
8080 WERROR status = WERR_OK;
8081 NT_PRINTER_INFO_LEVEL *printer = NULL;
8083 DEBUG(5,("spoolss_deleteform\n"));
8085 if (!Printer) {
8086 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8087 return WERR_BADFID;
8090 /* forms can be deleted on printer of on the print server handle */
8092 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8094 if (!get_printer_snum(p,handle, &snum))
8095 return WERR_BADFID;
8097 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8098 if (!W_ERROR_IS_OK(status))
8099 goto done;
8102 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8103 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8104 status = WERR_ACCESS_DENIED;
8105 goto done;
8108 /* can't delete if builtin */
8110 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8111 status = WERR_INVALID_PARAM;
8112 goto done;
8115 count = get_ntforms(&list);
8117 if ( !delete_a_form(&list, form_name, &count, &status ))
8118 goto done;
8121 * ChangeID must always be set if this is a printer
8124 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8125 status = mod_a_printer(*printer, 2);
8127 done:
8128 if ( printer )
8129 free_a_printer(&printer, 2);
8130 SAFE_FREE(list);
8132 return status;
8135 /****************************************************************************
8136 ****************************************************************************/
8138 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8140 POLICY_HND *handle = &q_u->handle;
8141 FORM *form = &q_u->form;
8142 nt_forms_struct tmpForm;
8143 int snum;
8144 WERROR status = WERR_OK;
8145 NT_PRINTER_INFO_LEVEL *printer = NULL;
8147 int count=0;
8148 nt_forms_struct *list=NULL;
8149 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8151 DEBUG(5,("spoolss_setform\n"));
8153 if (!Printer) {
8154 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8155 return WERR_BADFID;
8158 /* forms can be modified on printer of on the print server handle */
8160 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8162 if (!get_printer_snum(p,handle, &snum))
8163 return WERR_BADFID;
8165 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8166 if (!W_ERROR_IS_OK(status))
8167 goto done;
8170 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8171 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8172 status = WERR_ACCESS_DENIED;
8173 goto done;
8176 /* can't set if builtin */
8177 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8178 status = WERR_INVALID_PARAM;
8179 goto done;
8182 count = get_ntforms(&list);
8183 update_a_form(&list, form, count);
8184 write_ntforms(&list, count);
8187 * ChangeID must always be set if this is a printer
8190 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8191 status = mod_a_printer(*printer, 2);
8194 done:
8195 if ( printer )
8196 free_a_printer(&printer, 2);
8197 SAFE_FREE(list);
8199 return status;
8202 /****************************************************************************
8203 enumprintprocessors level 1.
8204 ****************************************************************************/
8206 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8208 PRINTPROCESSOR_1 *info_1=NULL;
8210 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8211 return WERR_NOMEM;
8213 (*returned) = 0x1;
8215 init_unistr(&info_1->name, "winprint");
8217 *needed += spoolss_size_printprocessor_info_1(info_1);
8219 if (!alloc_buffer_size(buffer, *needed))
8220 return WERR_INSUFFICIENT_BUFFER;
8222 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8224 SAFE_FREE(info_1);
8226 if (*needed > offered) {
8227 *returned=0;
8228 return WERR_INSUFFICIENT_BUFFER;
8231 return WERR_OK;
8234 /****************************************************************************
8235 ****************************************************************************/
8237 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8239 uint32 level = q_u->level;
8240 NEW_BUFFER *buffer = NULL;
8241 uint32 offered = q_u->offered;
8242 uint32 *needed = &r_u->needed;
8243 uint32 *returned = &r_u->returned;
8245 /* that's an [in out] buffer */
8246 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8247 buffer = r_u->buffer;
8249 DEBUG(5,("spoolss_enumprintprocessors\n"));
8252 * Enumerate the print processors ...
8254 * Just reply with "winprint", to keep NT happy
8255 * and I can use my nice printer checker.
8258 *returned=0;
8259 *needed=0;
8261 switch (level) {
8262 case 1:
8263 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8264 default:
8265 return WERR_UNKNOWN_LEVEL;
8269 /****************************************************************************
8270 enumprintprocdatatypes level 1.
8271 ****************************************************************************/
8273 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8275 PRINTPROCDATATYPE_1 *info_1=NULL;
8277 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8278 return WERR_NOMEM;
8280 (*returned) = 0x1;
8282 init_unistr(&info_1->name, "RAW");
8284 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8286 if (!alloc_buffer_size(buffer, *needed))
8287 return WERR_INSUFFICIENT_BUFFER;
8289 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8291 SAFE_FREE(info_1);
8293 if (*needed > offered) {
8294 *returned=0;
8295 return WERR_INSUFFICIENT_BUFFER;
8298 return WERR_OK;
8301 /****************************************************************************
8302 ****************************************************************************/
8304 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8306 uint32 level = q_u->level;
8307 NEW_BUFFER *buffer = NULL;
8308 uint32 offered = q_u->offered;
8309 uint32 *needed = &r_u->needed;
8310 uint32 *returned = &r_u->returned;
8312 /* that's an [in out] buffer */
8313 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8314 buffer = r_u->buffer;
8316 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8318 *returned=0;
8319 *needed=0;
8321 switch (level) {
8322 case 1:
8323 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8324 default:
8325 return WERR_UNKNOWN_LEVEL;
8329 /****************************************************************************
8330 enumprintmonitors level 1.
8331 ****************************************************************************/
8333 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8335 PRINTMONITOR_1 *info_1=NULL;
8337 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8338 return WERR_NOMEM;
8340 (*returned) = 0x1;
8342 init_unistr(&info_1->name, "Local Port");
8344 *needed += spoolss_size_printmonitor_info_1(info_1);
8346 if (!alloc_buffer_size(buffer, *needed))
8347 return WERR_INSUFFICIENT_BUFFER;
8349 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8351 SAFE_FREE(info_1);
8353 if (*needed > offered) {
8354 *returned=0;
8355 return WERR_INSUFFICIENT_BUFFER;
8358 return WERR_OK;
8361 /****************************************************************************
8362 enumprintmonitors level 2.
8363 ****************************************************************************/
8365 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8367 PRINTMONITOR_2 *info_2=NULL;
8369 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8370 return WERR_NOMEM;
8372 (*returned) = 0x1;
8374 init_unistr(&info_2->name, "Local Port");
8375 init_unistr(&info_2->environment, "Windows NT X86");
8376 init_unistr(&info_2->dll_name, "localmon.dll");
8378 *needed += spoolss_size_printmonitor_info_2(info_2);
8380 if (!alloc_buffer_size(buffer, *needed))
8381 return WERR_INSUFFICIENT_BUFFER;
8383 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8385 SAFE_FREE(info_2);
8387 if (*needed > offered) {
8388 *returned=0;
8389 return WERR_INSUFFICIENT_BUFFER;
8392 return WERR_OK;
8395 /****************************************************************************
8396 ****************************************************************************/
8398 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8400 uint32 level = q_u->level;
8401 NEW_BUFFER *buffer = NULL;
8402 uint32 offered = q_u->offered;
8403 uint32 *needed = &r_u->needed;
8404 uint32 *returned = &r_u->returned;
8406 /* that's an [in out] buffer */
8407 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8408 buffer = r_u->buffer;
8410 DEBUG(5,("spoolss_enumprintmonitors\n"));
8413 * Enumerate the print monitors ...
8415 * Just reply with "Local Port", to keep NT happy
8416 * and I can use my nice printer checker.
8419 *returned=0;
8420 *needed=0;
8422 switch (level) {
8423 case 1:
8424 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8425 case 2:
8426 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8427 default:
8428 return WERR_UNKNOWN_LEVEL;
8432 /****************************************************************************
8433 ****************************************************************************/
8435 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8437 int i=0;
8438 BOOL found=False;
8439 JOB_INFO_1 *info_1=NULL;
8441 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8443 if (info_1 == NULL) {
8444 return WERR_NOMEM;
8447 for (i=0; i<count && found==False; i++) {
8448 if (queue[i].job==(int)jobid)
8449 found=True;
8452 if (found==False) {
8453 SAFE_FREE(info_1);
8454 /* NT treats not found as bad param... yet another bad choice */
8455 return WERR_INVALID_PARAM;
8458 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8460 *needed += spoolss_size_job_info_1(info_1);
8462 if (!alloc_buffer_size(buffer, *needed)) {
8463 SAFE_FREE(info_1);
8464 return WERR_INSUFFICIENT_BUFFER;
8467 smb_io_job_info_1("", buffer, info_1, 0);
8469 SAFE_FREE(info_1);
8471 if (*needed > offered)
8472 return WERR_INSUFFICIENT_BUFFER;
8474 return WERR_OK;
8477 /****************************************************************************
8478 ****************************************************************************/
8480 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8482 int i = 0;
8483 BOOL found = False;
8484 JOB_INFO_2 *info_2;
8485 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8486 WERROR ret;
8487 DEVICEMODE *devmode = NULL;
8488 NT_DEVICEMODE *nt_devmode = NULL;
8490 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8492 ZERO_STRUCTP(info_2);
8494 if (info_2 == NULL) {
8495 ret = WERR_NOMEM;
8496 goto done;
8499 for ( i=0; i<count && found==False; i++ )
8501 if (queue[i].job == (int)jobid)
8502 found = True;
8505 if ( !found )
8507 /* NT treats not found as bad param... yet another bad
8508 choice */
8509 ret = WERR_INVALID_PARAM;
8510 goto done;
8513 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8514 if (!W_ERROR_IS_OK(ret))
8515 goto done;
8518 * if the print job does not have a DEVMODE associated with it,
8519 * just use the one for the printer. A NULL devicemode is not
8520 * a failure condition
8523 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8524 devmode = construct_dev_mode(snum);
8525 else {
8526 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8527 ZERO_STRUCTP( devmode );
8528 convert_nt_devicemode( devmode, nt_devmode );
8532 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8534 *needed += spoolss_size_job_info_2(info_2);
8536 if (!alloc_buffer_size(buffer, *needed)) {
8537 ret = WERR_INSUFFICIENT_BUFFER;
8538 goto done;
8541 smb_io_job_info_2("", buffer, info_2, 0);
8543 if (*needed > offered) {
8544 ret = WERR_INSUFFICIENT_BUFFER;
8545 goto done;
8548 ret = WERR_OK;
8550 done:
8551 /* Cleanup allocated memory */
8553 free_job_info_2(info_2); /* Also frees devmode */
8554 SAFE_FREE(info_2);
8555 free_a_printer(&ntprinter, 2);
8557 return ret;
8560 /****************************************************************************
8561 ****************************************************************************/
8563 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8565 POLICY_HND *handle = &q_u->handle;
8566 uint32 jobid = q_u->jobid;
8567 uint32 level = q_u->level;
8568 NEW_BUFFER *buffer = NULL;
8569 uint32 offered = q_u->offered;
8570 uint32 *needed = &r_u->needed;
8571 WERROR wstatus = WERR_OK;
8573 int snum;
8574 int count;
8575 print_queue_struct *queue = NULL;
8576 print_status_struct prt_status;
8578 /* that's an [in out] buffer */
8579 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8580 buffer = r_u->buffer;
8582 DEBUG(5,("spoolss_getjob\n"));
8584 *needed = 0;
8586 if (!get_printer_snum(p, handle, &snum))
8587 return WERR_BADFID;
8589 count = print_queue_status(snum, &queue, &prt_status);
8591 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8592 count, prt_status.status, prt_status.message));
8594 switch ( level ) {
8595 case 1:
8596 wstatus = getjob_level_1(queue, count, snum, jobid,
8597 buffer, offered, needed);
8598 break;
8599 case 2:
8600 wstatus = getjob_level_2(queue, count, snum, jobid,
8601 buffer, offered, needed);
8602 break;
8603 default:
8604 wstatus = WERR_UNKNOWN_LEVEL;
8605 break;
8608 SAFE_FREE(queue);
8609 return wstatus;
8612 /********************************************************************
8613 spoolss_getprinterdataex
8615 From MSDN documentation of GetPrinterDataEx: pass request
8616 to GetPrinterData if key is "PrinterDriverData".
8617 ********************************************************************/
8619 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8621 POLICY_HND *handle = &q_u->handle;
8622 uint32 in_size = q_u->size;
8623 uint32 *type = &r_u->type;
8624 uint32 *out_size = &r_u->size;
8625 uint8 **data = &r_u->data;
8626 uint32 *needed = &r_u->needed;
8627 fstring keyname, valuename;
8629 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8631 NT_PRINTER_INFO_LEVEL *printer = NULL;
8632 int snum = 0;
8633 WERROR status = WERR_OK;
8635 DEBUG(4,("_spoolss_getprinterdataex\n"));
8637 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8638 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8640 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8641 keyname, valuename));
8643 /* in case of problem, return some default values */
8645 *needed = 0;
8646 *type = 0;
8647 *out_size = in_size;
8649 if (!Printer) {
8650 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8651 status = WERR_BADFID;
8652 goto done;
8655 /* Is the handle to a printer or to the server? */
8657 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8658 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8659 status = WERR_INVALID_PARAM;
8660 goto done;
8663 if ( !get_printer_snum(p,handle, &snum) )
8664 return WERR_BADFID;
8666 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8667 if ( !W_ERROR_IS_OK(status) )
8668 goto done;
8670 /* check to see if the keyname is valid */
8671 if ( !strlen(keyname) ) {
8672 status = WERR_INVALID_PARAM;
8673 goto done;
8676 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8677 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8678 free_a_printer( &printer, 2 );
8679 status = WERR_BADFILE;
8680 goto done;
8683 /* When given a new keyname, we should just create it */
8685 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8687 if (*needed > *out_size)
8688 status = WERR_MORE_DATA;
8690 done:
8691 if ( !W_ERROR_IS_OK(status) )
8693 DEBUG(5, ("error: allocating %d\n", *out_size));
8695 /* reply this param doesn't exist */
8697 if ( *out_size )
8699 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8700 status = WERR_NOMEM;
8701 goto done;
8704 else {
8705 *data = NULL;
8709 if ( printer )
8710 free_a_printer( &printer, 2 );
8712 return status;
8715 /********************************************************************
8716 * spoolss_setprinterdataex
8717 ********************************************************************/
8719 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8721 POLICY_HND *handle = &q_u->handle;
8722 uint32 type = q_u->type;
8723 uint8 *data = q_u->data;
8724 uint32 real_len = q_u->real_len;
8726 NT_PRINTER_INFO_LEVEL *printer = NULL;
8727 int snum = 0;
8728 WERROR status = WERR_OK;
8729 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8730 fstring valuename;
8731 fstring keyname;
8732 char *oid_string;
8734 DEBUG(4,("_spoolss_setprinterdataex\n"));
8736 /* From MSDN documentation of SetPrinterDataEx: pass request to
8737 SetPrinterData if key is "PrinterDriverData" */
8739 if (!Printer) {
8740 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8741 return WERR_BADFID;
8744 if ( !get_printer_snum(p,handle, &snum) )
8745 return WERR_BADFID;
8748 * Access check : NT returns "access denied" if you make a
8749 * SetPrinterData call without the necessary privildge.
8750 * we were originally returning OK if nothing changed
8751 * which made Win2k issue **a lot** of SetPrinterData
8752 * when connecting to a printer --jerry
8755 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8757 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8758 return WERR_ACCESS_DENIED;
8761 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8762 if (!W_ERROR_IS_OK(status))
8763 return status;
8765 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8766 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8768 /* check for OID in valuename */
8770 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8772 *oid_string = '\0';
8773 oid_string++;
8776 /* save the registry data */
8778 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8780 if ( W_ERROR_IS_OK(status) )
8782 /* save the OID if one was specified */
8783 if ( oid_string ) {
8784 fstrcat( keyname, "\\" );
8785 fstrcat( keyname, SPOOL_OID_KEY );
8788 * I'm not checking the status here on purpose. Don't know
8789 * if this is right, but I'm returning the status from the
8790 * previous set_printer_dataex() call. I have no idea if
8791 * this is right. --jerry
8794 set_printer_dataex( printer, keyname, valuename,
8795 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8798 status = mod_a_printer(*printer, 2);
8801 free_a_printer(&printer, 2);
8803 return status;
8807 /********************************************************************
8808 * spoolss_deleteprinterdataex
8809 ********************************************************************/
8811 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8813 POLICY_HND *handle = &q_u->handle;
8814 UNISTR2 *value = &q_u->valuename;
8815 UNISTR2 *key = &q_u->keyname;
8817 NT_PRINTER_INFO_LEVEL *printer = NULL;
8818 int snum=0;
8819 WERROR status = WERR_OK;
8820 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8821 pstring valuename, keyname;
8823 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8825 if (!Printer) {
8826 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8827 return WERR_BADFID;
8830 if (!get_printer_snum(p, handle, &snum))
8831 return WERR_BADFID;
8833 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8834 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8835 return WERR_ACCESS_DENIED;
8838 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8839 if (!W_ERROR_IS_OK(status))
8840 return status;
8842 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8843 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8845 status = delete_printer_dataex( printer, keyname, valuename );
8847 free_a_printer(&printer, 2);
8849 return status;
8852 /********************************************************************
8853 * spoolss_enumprinterkey
8854 ********************************************************************/
8857 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8859 fstring key;
8860 fstring *keynames = NULL;
8861 uint16 *enumkeys = NULL;
8862 int num_keys;
8863 int printerkey_len;
8864 POLICY_HND *handle = &q_u->handle;
8865 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8866 NT_PRINTER_DATA *data;
8867 NT_PRINTER_INFO_LEVEL *printer = NULL;
8868 int snum = 0;
8869 WERROR status = WERR_BADFILE;
8872 DEBUG(4,("_spoolss_enumprinterkey\n"));
8874 if (!Printer) {
8875 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8876 return WERR_BADFID;
8879 if ( !get_printer_snum(p,handle, &snum) )
8880 return WERR_BADFID;
8882 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8883 if (!W_ERROR_IS_OK(status))
8884 return status;
8886 /* get the list of subkey names */
8888 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8889 data = &printer->info_2->data;
8891 num_keys = get_printer_subkeys( data, key, &keynames );
8893 if ( num_keys == -1 ) {
8894 status = WERR_BADFILE;
8895 goto done;
8898 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8900 r_u->needed = printerkey_len*2;
8902 if ( q_u->size < r_u->needed ) {
8903 status = WERR_MORE_DATA;
8904 goto done;
8907 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8908 status = WERR_NOMEM;
8909 goto done;
8912 status = WERR_OK;
8914 if ( q_u->size < r_u->needed )
8915 status = WERR_MORE_DATA;
8917 done:
8918 free_a_printer( &printer, 2 );
8919 SAFE_FREE( keynames );
8921 return status;
8924 /********************************************************************
8925 * spoolss_deleteprinterkey
8926 ********************************************************************/
8928 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8930 POLICY_HND *handle = &q_u->handle;
8931 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8932 fstring key;
8933 NT_PRINTER_INFO_LEVEL *printer = NULL;
8934 int snum=0;
8935 WERROR status;
8937 DEBUG(5,("spoolss_deleteprinterkey\n"));
8939 if (!Printer) {
8940 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8941 return WERR_BADFID;
8944 /* if keyname == NULL, return error */
8946 if ( !q_u->keyname.buffer )
8947 return WERR_INVALID_PARAM;
8949 if (!get_printer_snum(p, handle, &snum))
8950 return WERR_BADFID;
8952 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8953 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8954 return WERR_ACCESS_DENIED;
8957 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8958 if (!W_ERROR_IS_OK(status))
8959 return status;
8961 /* delete the key and all subneys */
8963 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8965 status = delete_all_printer_data( printer->info_2, key );
8967 if ( W_ERROR_IS_OK(status) )
8968 status = mod_a_printer(*printer, 2);
8970 free_a_printer( &printer, 2 );
8972 return status;
8976 /********************************************************************
8977 * spoolss_enumprinterdataex
8978 ********************************************************************/
8980 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8982 POLICY_HND *handle = &q_u->handle;
8983 uint32 in_size = q_u->size;
8984 uint32 num_entries,
8985 needed;
8986 NT_PRINTER_INFO_LEVEL *printer = NULL;
8987 PRINTER_ENUM_VALUES *enum_values = NULL;
8988 NT_PRINTER_DATA *p_data;
8989 fstring key;
8990 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8991 int snum;
8992 WERROR result;
8993 int key_index;
8994 int i;
8995 REGISTRY_VALUE *val;
8996 char *value_name;
8997 int data_len;
9000 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9002 if (!Printer) {
9003 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9004 return WERR_BADFID;
9008 * first check for a keyname of NULL or "". Win2k seems to send
9009 * this a lot and we should send back WERR_INVALID_PARAM
9010 * no need to spend time looking up the printer in this case.
9011 * --jerry
9014 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9015 if ( !strlen(key) ) {
9016 result = WERR_INVALID_PARAM;
9017 goto done;
9020 /* get the printer off of disk */
9022 if (!get_printer_snum(p,handle, &snum))
9023 return WERR_BADFID;
9025 ZERO_STRUCT(printer);
9026 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9027 if (!W_ERROR_IS_OK(result))
9028 return result;
9030 /* now look for a match on the key name */
9032 p_data = &printer->info_2->data;
9034 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9035 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9037 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9038 result = WERR_INVALID_PARAM;
9039 goto done;
9042 result = WERR_OK;
9043 needed = 0;
9045 /* allocate the memory for the array of pointers -- if necessary */
9047 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9048 if ( num_entries )
9050 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9052 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
9053 num_entries*sizeof(PRINTER_ENUM_VALUES)));
9054 result = WERR_NOMEM;
9055 goto done;
9058 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9062 * loop through all params and build the array to pass
9063 * back to the client
9066 for ( i=0; i<num_entries; i++ )
9068 /* lookup the registry value */
9070 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9071 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9073 /* copy the data */
9075 value_name = regval_name( val );
9076 init_unistr( &enum_values[i].valuename, value_name );
9077 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9078 enum_values[i].type = regval_type( val );
9080 data_len = regval_size( val );
9081 if ( data_len ) {
9082 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9084 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9085 data_len ));
9086 result = WERR_NOMEM;
9087 goto done;
9090 enum_values[i].data_len = data_len;
9092 /* keep track of the size of the array in bytes */
9094 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9097 /* housekeeping information in the reply */
9099 r_u->needed = needed;
9100 r_u->returned = num_entries;
9102 if (needed > in_size) {
9103 result = WERR_MORE_DATA;
9104 goto done;
9107 /* copy data into the reply */
9109 r_u->ctr.size = r_u->needed;
9110 r_u->ctr.size_of_array = r_u->returned;
9111 r_u->ctr.values = enum_values;
9115 done:
9116 if ( printer )
9117 free_a_printer(&printer, 2);
9119 return result;
9122 /****************************************************************************
9123 ****************************************************************************/
9125 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9127 init_unistr(&info->name, name);
9130 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9131 UNISTR2 *environment,
9132 NEW_BUFFER *buffer,
9133 uint32 offered,
9134 uint32 *needed)
9136 pstring path;
9137 pstring long_archi;
9138 pstring short_archi;
9139 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9141 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9143 if (get_short_archi(short_archi, long_archi)==False)
9144 return WERR_INVALID_ENVIRONMENT;
9146 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9147 return WERR_NOMEM;
9149 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9151 fill_printprocessordirectory_1(info, path);
9153 *needed += spoolss_size_printprocessordirectory_info_1(info);
9155 if (!alloc_buffer_size(buffer, *needed)) {
9156 safe_free(info);
9157 return WERR_INSUFFICIENT_BUFFER;
9160 smb_io_printprocessordirectory_1("", buffer, info, 0);
9162 safe_free(info);
9164 if (*needed > offered)
9165 return WERR_INSUFFICIENT_BUFFER;
9166 else
9167 return WERR_OK;
9170 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9172 uint32 level = q_u->level;
9173 NEW_BUFFER *buffer = NULL;
9174 uint32 offered = q_u->offered;
9175 uint32 *needed = &r_u->needed;
9176 WERROR result;
9178 /* that's an [in out] buffer */
9179 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9180 buffer = r_u->buffer;
9182 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9184 *needed=0;
9186 switch(level) {
9187 case 1:
9188 result = getprintprocessordirectory_level_1
9189 (&q_u->name, &q_u->environment, buffer, offered, needed);
9190 break;
9191 default:
9192 result = WERR_UNKNOWN_LEVEL;
9195 return result;
9198 #if 0
9200 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9201 SPOOL_R_REPLYOPENPRINTER *r_u)
9203 DEBUG(5,("_spoolss_replyopenprinter\n"));
9205 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9207 return WERR_OK;
9210 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9211 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9213 DEBUG(5,("_spoolss_replycloseprinter\n"));
9214 return WERR_OK;
9217 #endif